mirror of
https://github.com/acamarata/date-fns-hijri.git
synced 2026-07-01 19:24:26 +00:00
Behavior changes (lock-step with hijri-core fix/utc-day-boundary): - toHijriDate and all field/format/comparison/arithmetic functions now lift input Dates through localDayToUtcSlot() before calling coreToHijri(), reading the caller's LOCAL calendar day (date-fns convention). Previously passed the raw Date which caused off-by-one results in timezones west of UTC against the new UTC-day core contract. - fromHijriDate now returns local-midnight Dates (new Date(y, m, d)) instead of UTC midnight. Local field accessors and date-fns format() render the intended calendar day on every host timezone. toISOString() is no longer the right API for this value. - addHijriMonths, addHijriYears, startOfHijriMonth, endOfHijriMonth call fromHijriDate directly; the utcMidnightToLocalNoon shim is removed. - Round-trip toHijriDate(fromHijriDate(y, m, d)) is now exact on every timezone. Verified: 58/58 ESM tests, 10/10 CJS tests, 16/16 vitest assertions across TZ=UTC, TZ=America/New_York, and TZ=Pacific/Auckland.
94 lines
3.5 KiB
Markdown
94 lines
3.5 KiB
Markdown
# date-fns-hijri
|
|
|
|
[](https://www.npmjs.com/package/date-fns-hijri)
|
|
[](https://github.com/acamarata/date-fns-hijri/actions/workflows/ci.yml)
|
|
[](LICENSE)
|
|
|
|
date-fns-style functions for Hijri calendar operations. Each function is a pure, stateless utility. Pass a `Date`, get a result. No classes, no global configuration.
|
|
|
|
Built on [hijri-core](https://github.com/acamarata/hijri-core). Supports Umm al-Qura (UAQ) and FCNA/ISNA calendar systems.
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
pnpm add date-fns-hijri hijri-core
|
|
```
|
|
|
|
`hijri-core` is a peer dependency. It provides the underlying calendar engine.
|
|
|
|
## Quick Start
|
|
|
|
```typescript
|
|
import {
|
|
toHijriDate,
|
|
fromHijriDate,
|
|
formatHijriDate,
|
|
addHijriMonths,
|
|
getHijriMonthName,
|
|
} from 'date-fns-hijri';
|
|
|
|
// Convert Gregorian to Hijri
|
|
const hijri = toHijriDate(new Date(2023, 2, 23, 12));
|
|
// { hy: 1444, hm: 9, hd: 1 } (1 Ramadan 1444)
|
|
|
|
// Format with Hijri tokens
|
|
const label = formatHijriDate(new Date(2023, 2, 23, 12), 'iD iMMMM iYYYY ioooo');
|
|
// '1 Ramadan 1444 AH'
|
|
|
|
// Add Hijri months
|
|
const eid = addHijriMonths(new Date(2023, 2, 23, 12), 1);
|
|
// Date in Shawwal 1444
|
|
|
|
// Get the month name
|
|
getHijriMonthName(9); // 'Ramadan'
|
|
```
|
|
|
|
## Documentation
|
|
|
|
Full API reference, guides, and examples: **[Wiki](https://github.com/acamarata/date-fns-hijri/wiki)**
|
|
|
|
- [API Reference](https://github.com/acamarata/date-fns-hijri/wiki/API-Reference): all 17 functions with signatures and examples
|
|
- [Architecture](https://github.com/acamarata/date-fns-hijri/wiki/Architecture): design decisions and hijri-core integration
|
|
- [Quick Start](https://github.com/acamarata/date-fns-hijri/wiki/guides/quickstart)
|
|
|
|
## Day boundaries and time zones
|
|
|
|
This package follows date-fns local-time conventions:
|
|
|
|
- **Inputs** (`toHijriDate`, `getHijri*`, `formatHijriDate`, arithmetic, comparisons) — the input `Date` is read by its **local calendar day** (using `getFullYear`/`getMonth`/`getDate`). This matches how date-fns' own `format()` and field accessors work.
|
|
- **Outputs** (`fromHijriDate` and all arithmetic/boundary functions) — returned `Date` values are **local midnight** of the equivalent Gregorian day. Local field accessors and date-fns' `format()` will render the intended date on every timezone.
|
|
|
|
Round-trips are exact on every host timezone:
|
|
|
|
```typescript
|
|
toHijriDate(fromHijriDate(1446, 9, 1)); // always { hy: 1446, hm: 9, hd: 1 }
|
|
```
|
|
|
|
**Pitfall:** `new Date("2025-03-01")` parses as UTC midnight. In timezones west of UTC this resolves to the previous local day (Feb 28), giving an off-by-one result. Use the local-date constructor instead:
|
|
|
|
```typescript
|
|
// Wrong in timezones west of UTC:
|
|
toHijriDate(new Date("2025-03-01")); // may return 29 Shaban in some zones
|
|
|
|
// Correct everywhere:
|
|
toHijriDate(new Date(2025, 2, 1)); // always 1 Ramadan 1446
|
|
```
|
|
|
|
Religious day-start (sunset boundary) is out of scope — this package only handles civil calendar day alignment.
|
|
|
|
## Related
|
|
|
|
- [hijri-core](https://github.com/acamarata/hijri-core): the calendar engine powering this library
|
|
- [luxon-hijri](https://github.com/acamarata/luxon-hijri): Hijri support for Luxon DateTime objects
|
|
- [pray-calc](https://github.com/acamarata/pray-calc): Islamic prayer times
|
|
|
|
## Compatibility
|
|
|
|
- Node.js 20, 22, 24
|
|
- ESM and CJS builds included
|
|
- TypeScript definitions bundled
|
|
- Works in browsers and all major bundlers
|
|
|
|
## License
|
|
|
|
MIT. Copyright (c) 2026 Aric Camarata.
|