mirror of
https://github.com/acamarata/dayjs-hijri-plus.git
synced 2026-06-30 18:54:26 +00:00
Day.js plugin adding Hijri calendar support via hijri-core. Adds toHijri(), fromHijri(), hijriYear/Month/Day(), isValidHijri(), and formatHijri() to all Day.js instances. Supports UAQ and FCNA calendars via ConversionOptions. Format token escaping wraps substituted values in Day.js bracket syntax to prevent re-interpretation as format tokens. 14 ESM + 8 CJS tests passing. Dual CJS/ESM build.
190 lines
6.4 KiB
Markdown
190 lines
6.4 KiB
Markdown
# dayjs-hijri-plus
|
|
|
|
[](https://www.npmjs.com/package/dayjs-hijri-plus)
|
|
[](https://github.com/acamarata/dayjs-hijri-plus/actions/workflows/ci.yml)
|
|
[](https://opensource.org/licenses/MIT)
|
|
|
|
A Day.js plugin that adds Hijri calendar support. Converts Gregorian dates to and from Hijri, provides Hijri-aware formatting, and delegates all calendar logic to [hijri-core](https://github.com/acamarata/hijri-core) — keeping this package thin and testable.
|
|
|
|
Supports Umm al-Qura (UAQ) and FCNA/ISNA calendars out of the box. Custom calendar engines can be registered at runtime.
|
|
|
|
## Installation
|
|
|
|
```sh
|
|
pnpm add dayjs dayjs-hijri-plus hijri-core
|
|
```
|
|
|
|
Both `dayjs` and `hijri-core` are peer dependencies and must be installed alongside this plugin.
|
|
|
|
## Quick Start
|
|
|
|
```ts
|
|
import dayjs from 'dayjs';
|
|
import hijriPlugin from 'dayjs-hijri-plus';
|
|
|
|
dayjs.extend(hijriPlugin);
|
|
|
|
// Convert a Gregorian date to Hijri
|
|
const d = dayjs(new Date(2023, 2, 23));
|
|
const hijri = d.toHijri();
|
|
// => { hy: 1444, hm: 9, hd: 1 } (1 Ramadan 1444 AH)
|
|
|
|
// Format using Hijri tokens mixed with standard Day.js tokens
|
|
d.formatHijri('iYYYY-iMM-iDD'); // => '1444-09-01'
|
|
d.formatHijri('iD iMMMM iYYYY'); // => '1 Ramadan 1444'
|
|
d.formatHijri('iD iMMMM iYYYY [at] HH:mm'); // => '1 Ramadan 1444 at 00:00'
|
|
|
|
// Individual Hijri components
|
|
d.hijriYear(); // => 1444
|
|
d.hijriMonth(); // => 9
|
|
d.hijriDay(); // => 1
|
|
|
|
// Construct a Day.js instance from a Hijri date
|
|
const eid = dayjs.fromHijri(1444, 10, 1);
|
|
eid.format('YYYY-MM-DD'); // => '2023-04-21'
|
|
|
|
// FCNA/ISNA calendar variant
|
|
d.toHijri({ calendar: 'fcna' }); // => { hy: 1444, hm: 9, hd: 2 } (varies by month)
|
|
```
|
|
|
|
## API
|
|
|
|
### dayjs.extend(hijriPlugin)
|
|
|
|
Register the plugin with your Day.js instance. Call once before using any plugin methods.
|
|
|
|
### Instance Methods
|
|
|
|
#### `.toHijri(opts?)`
|
|
|
|
Convert the Day.js date to a Hijri date object.
|
|
|
|
| Parameter | Type | Description |
|
|
| --- | --- | --- |
|
|
| `opts` | `ConversionOptions` | Optional. `{ calendar: 'uaq' \| 'fcna' \| string }` |
|
|
|
|
Returns `HijriDate | null`. Returns `null` if the date is outside the supported range (approximately 1900-2077 CE for UAQ).
|
|
|
|
```ts
|
|
dayjs('2023-03-23').toHijri();
|
|
// => { hy: 1444, hm: 9, hd: 1 }
|
|
```
|
|
|
|
#### `.isValidHijri(opts?)`
|
|
|
|
Check whether the date maps to a valid Hijri date in the supported range.
|
|
|
|
Returns `boolean`.
|
|
|
|
#### `.hijriYear(opts?)`
|
|
|
|
Returns the Hijri year as a `number`, or `null` if out of range.
|
|
|
|
#### `.hijriMonth(opts?)`
|
|
|
|
Returns the Hijri month (1-12) as a `number`, or `null` if out of range.
|
|
|
|
#### `.hijriDay(opts?)`
|
|
|
|
Returns the Hijri day (1-30) as a `number`, or `null` if out of range.
|
|
|
|
#### `.formatHijri(formatStr, opts?)`
|
|
|
|
Format the date using a mix of Hijri tokens and standard Day.js tokens.
|
|
|
|
| Parameter | Type | Description |
|
|
| --- | --- | --- |
|
|
| `formatStr` | `string` | Format string — see token table below |
|
|
| `opts` | `ConversionOptions` | Optional calendar selection |
|
|
|
|
Returns `string`. Returns an empty string if the date is out of range.
|
|
|
|
Hijri tokens are replaced first. The resulting string is then passed to Day.js `.format()`, so all standard tokens (YYYY, MM, DD, HH, mm, ss, etc.) resolve normally.
|
|
|
|
### Static Methods
|
|
|
|
#### `dayjs.fromHijri(hy, hm, hd, opts?)`
|
|
|
|
Construct a Day.js instance from a Hijri date.
|
|
|
|
| Parameter | Type | Description |
|
|
| --- | --- | --- |
|
|
| `hy` | `number` | Hijri year |
|
|
| `hm` | `number` | Hijri month (1-12) |
|
|
| `hd` | `number` | Hijri day (1-30) |
|
|
| `opts` | `ConversionOptions` | Optional calendar selection |
|
|
|
|
Returns a `dayjs.Dayjs` instance. Throws `Error` if the Hijri date is invalid or outside the table range.
|
|
|
|
## Format Tokens
|
|
|
|
All Hijri-specific tokens use the `i` prefix.
|
|
|
|
| Token | Example | Description |
|
|
| --- | --- | --- |
|
|
| `iYYYY` | `1444` | 4-digit Hijri year |
|
|
| `iYY` | `44` | 2-digit Hijri year |
|
|
| `iMMMM` | `Ramadan` | Full Hijri month name |
|
|
| `iMMM` | `Ramadan` | Medium Hijri month name |
|
|
| `iMM` | `09` | Zero-padded Hijri month number |
|
|
| `iM` | `9` | Hijri month number |
|
|
| `iDD` | `01` | Zero-padded Hijri day |
|
|
| `iD` | `1` | Hijri day number |
|
|
| `iEEEE` | `Yawm al-Khamis` | Full weekday name |
|
|
| `iEEE` | `Kham` | Short weekday name |
|
|
| `iE` | `5` | Weekday number (1=Sunday ... 7=Saturday) |
|
|
| `ioooo` | `AH` | Era (Anno Hegirae) |
|
|
| `iooo` | `AH` | Era (short form, same as ioooo) |
|
|
|
|
Standard Day.js tokens pass through untouched. Square-bracket escaping (`[literal text]`) also works as expected.
|
|
|
|
## Calendar Systems
|
|
|
|
Two calendars ship with hijri-core:
|
|
|
|
- **`uaq`** (default) — Umm al-Qura, the official calendar of Saudi Arabia. Table-based, covers approximately 1318-1500 AH (1900-2077 CE).
|
|
- **`fcna`** — Fiqh Council of North America calendar. Uses an astronomical calculation with fixed criteria, independent of moon sighting.
|
|
|
|
Select a calendar by passing `{ calendar: 'fcna' }` to any method. The default is `'uaq'` when no option is provided.
|
|
|
|
Custom calendar engines can be registered:
|
|
|
|
```ts
|
|
import { registerCalendar } from 'dayjs-hijri-plus';
|
|
import type { CalendarEngine } from 'dayjs-hijri-plus';
|
|
|
|
const myEngine: CalendarEngine = { ... };
|
|
registerCalendar('my-calendar', myEngine);
|
|
|
|
dayjs().toHijri({ calendar: 'my-calendar' });
|
|
```
|
|
|
|
See the [hijri-core CalendarEngine interface](https://github.com/acamarata/hijri-core) for the full contract.
|
|
|
|
## TypeScript
|
|
|
|
Full TypeScript support is included. The plugin augments the Day.js module to add types for all instance and static methods.
|
|
|
|
```ts
|
|
import type { HijriDate, ConversionOptions } from 'dayjs-hijri-plus';
|
|
|
|
const h: HijriDate = dayjs().toHijri()!;
|
|
const opts: ConversionOptions = { calendar: 'fcna' };
|
|
```
|
|
|
|
No `@types` package is needed.
|
|
|
|
## Documentation
|
|
|
|
Full API reference, architecture notes, and calendar system comparisons are on the [GitHub Wiki](https://github.com/acamarata/dayjs-hijri-plus/wiki).
|
|
|
|
## Related
|
|
|
|
- [hijri-core](https://github.com/acamarata/hijri-core) — the zero-dependency Hijri calendar engine this plugin wraps
|
|
- [luxon-hijri](https://github.com/acamarata/luxon-hijri) — the same Hijri conversion for Luxon users
|
|
- [pray-calc](https://github.com/acamarata/pray-calc) — Islamic prayer time calculation
|
|
- [nrel-spa](https://github.com/acamarata/nrel-spa) — NREL Solar Position Algorithm in pure JavaScript
|
|
|
|
## License
|
|
|
|
MIT. Copyright (c) 2026 Aric Camarata.
|