mirror of
https://github.com/acamarata/luxon-hijri.git
synced 2026-06-30 18:54:28 +00:00
3.5 KiB
3.5 KiB
Advanced Usage
Format tokens
All Hijri-specific tokens use the i prefix. For the full token table, see the API Reference.
Common tokens:
| Token | Example | Description |
|---|---|---|
iD |
1–30 |
Hijri day, no padding |
iDD |
01–30 |
Hijri day, zero-padded |
iM |
1–12 |
Hijri month number, no padding |
iMM |
01–12 |
Hijri month number, zero-padded |
iMMMM |
Ramadan |
Full Hijri month name |
iYY |
46 |
Last two digits of Hijri year |
iYYYY |
1446 |
Full Hijri year |
ioooo |
AH |
Hijri era |
import { toHijri, formatHijriDate } from 'luxon-hijri';
const h = toHijri(new Date('2025-03-20'));
console.log(formatHijriDate(h, 'iDD/iMM/iYYYY')); // 20/09/1446
console.log(formatHijriDate(h, 'iD iMMMM iYYYY')); // 20 Ramadan 1446
console.log(formatHijriDate(h, 'iD iMMMM iYYYY ioooo')); // 20 Ramadan 1446 AH
Hijri date arithmetic with Luxon
Luxon handles Gregorian arithmetic. Use toGregorian to convert Hijri endpoints, then work in Gregorian:
import { DateTime } from 'luxon';
import { toHijri, toGregorian } from 'luxon-hijri';
// Find when Eid al-Fitr (1 Shawwal) starts for this year
const today = new Date();
const h = toHijri(today);
if (h) {
const eidStart = toGregorian(h.hy, 10, 1); // 1 Shawwal
const eid = DateTime.fromJSDate(eidStart);
console.log(`Eid al-Fitr ${h.hy}: ${eid.toFormat('MMMM d, yyyy')}`);
}
Generating a Hijri month calendar
The UAQ table encodes day counts per month in a bitmask. To iterate a month, convert each Hijri day to Gregorian and stop when toGregorian throws:
import { toGregorian } from 'luxon-hijri';
import { DateTime } from 'luxon';
const HY = 1446;
const HM = 9; // Ramadan
// Determine the month length (29 or 30 days)
let days = 29;
try { toGregorian(HY, HM, 30); days = 30; } catch (_) {}
const NAMES = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
console.log(`Ramadan ${HY}\n`);
console.log(NAMES.join(' '));
const firstGreg = DateTime.fromJSDate(toGregorian(HY, HM, 1));
let line = ' '.repeat(firstGreg.weekday % 7); // Sunday = 0
for (let d = 1; d <= days; d++) {
const greg = DateTime.fromJSDate(toGregorian(HY, HM, d));
line += String(d).padStart(3) + ' ';
if (greg.weekday === 6) { // Saturday ends row
console.log(line);
line = '';
}
}
if (line.trim()) console.log(line);
FCNA vs UAQ differences
FCNA and UAQ can differ by a day around month transitions:
import { toHijri } from 'luxon-hijri';
const borderDates = [
new Date('2025-02-28'),
new Date('2025-03-01'),
new Date('2025-03-02'),
];
for (const d of borderDates) {
const uaq = toHijri(d, { calendar: 'uaq' });
const fcna = toHijri(d, { calendar: 'fcna' });
const fmt = h => h ? `${h.hd}/${h.hm}/${h.hy}` : 'null';
console.log(`${d.toISOString().slice(0, 10)} UAQ: ${fmt(uaq)} FCNA: ${fmt(fcna)}`);
}
Batch conversion
import { toHijri } from 'luxon-hijri';
const isoList = [
'2025-01-01', '2025-03-01', '2025-03-30',
'2025-06-06', '2025-12-31',
];
for (const iso of isoList) {
const h = toHijri(new Date(iso));
const result = h ? `${h.hd}/${h.hm}/${h.hy} AH` : 'out of range';
console.log(`${iso} → ${result}`);
}
Related pages
- API Reference — all functions, format tokens, types
- Hijri Calendar — background on UAQ and FCNA calendar systems
- Architecture — internals, conversion engine, accuracy