No description
Find a file
2026-06-13 11:52:27 -04:00
.github chore: P1 final polish — type accuracy, AGENTS.md sync, E5/E6 refinements 2026-05-30 18:40:41 -04:00
src ci: fix eslint parser devDeps, typed-linting config, coverage ignores, prettier format 2026-05-31 08:48:01 -04:00
.editorconfig feat: v2.0.0 — FCNA calendar, dual ESM/CJS build, weekday bug fix, full test suite 2026-02-25 13:25:11 -05:00
.gitignore refactor: code quality improvements across the board 2026-03-08 11:42:29 -04:00
.npmrc chore: clear .npmrc to remove pnpm-only key that warns on npm publish 2026-02-25 15:09:10 -05:00
.nvmrc feat: v2.0.0 — FCNA calendar, dual ESM/CJS build, weekday bug fix, full test suite 2026-02-25 13:25:11 -05:00
CHANGELOG.md chore: bump to v3.0.3 2026-06-13 11:52:27 -04:00
eslint.config.mjs ci: fix eslint parser devDeps, typed-linting config, coverage ignores, prettier format 2026-05-31 08:48:01 -04:00
LICENSE feat: v2.0.0 — FCNA calendar, dual ESM/CJS build, weekday bug fix, full test suite 2026-02-25 13:25:11 -05:00
luxon-hijri.test.ts test: align day-boundary tests and docs with hijri-core's UTC-day contract 2026-06-10 16:38:29 -04:00
package.json chore: bump to v3.0.3 2026-06-13 11:52:27 -04:00
pnpm-lock.yaml chore: update hijri-core to 1.0.3 2026-06-10 16:49:20 -04:00
pnpm-workspace.yaml feat: v2.0.0 — FCNA calendar, dual ESM/CJS build, weekday bug fix, full test suite 2026-02-25 13:25:11 -05:00
README.md test: align day-boundary tests and docs with hijri-core's UTC-day contract 2026-06-10 16:38:29 -04:00
test-cjs.cjs test: align day-boundary tests and docs with hijri-core's UTC-day contract 2026-06-10 16:38:29 -04:00
test-crossval.mjs docs: add quickstart, advanced guide, examples, and cross-validation test for luxon-hijri 2026-05-28 14:14:23 -04:00
test.mjs test: align day-boundary tests and docs with hijri-core's UTC-day contract 2026-06-10 16:38:29 -04:00
tsconfig.json chore: adopt shared config packages (tsconfig, eslint, prettier) 2026-05-30 15:08:47 -04:00
tsup.config.ts feat: v2.1.0 — delegate engine logic to hijri-core 2026-02-25 14:14:29 -05:00
typedoc.json docs: add TypeDoc API generation (typedoc@0.28.19 + typedoc-plugin-markdown@4.11.0) 2026-05-30 16:41:58 -04:00
vitest.config.ts test: align day-boundary tests and docs with hijri-core's UTC-day contract 2026-06-10 16:38:29 -04:00

luxon-hijri

npm version CI License: MIT Wiki

Hijri/Gregorian date conversion and formatting for Luxon users. Thin adapter over hijri-core. Supports the Umm al-Qura calendar (1318-1500 AH, table-based) and the FCNA/ISNA calendar (astronomical, all Hijri years).

Installation

pnpm add luxon-hijri luxon hijri-core
# or
npm install luxon-hijri luxon hijri-core

Quick Start

import { toHijri, toGregorian, formatHijriDate } from 'luxon-hijri';

// Gregorian to Hijri (Umm al-Qura, default) — use Date.UTC for cross-host consistency
const h = toHijri(new Date(Date.UTC(2023, 2, 23)));
// { hy: 1444, hm: 9, hd: 1 }

// Hijri to Gregorian
const g = toGregorian(1444, 9, 1);
// Date: 2023-03-23T00:00:00.000Z

// Format a Hijri date
formatHijriDate({ hy: 1444, hm: 9, hd: 1 }, 'iEEEE, iD iMMMM iYYYY ioooo');
// "Yawm al-Khamis, 1 Ramadan 1444 AH"

// FCNA/ISNA calendar
toHijri(new Date(Date.UTC(2025, 2, 1)), { calendar: 'fcna' });

Day boundaries and time zones

toHijri(date) reads the UTC calendar day of the Date you pass. toGregorian(hy, hm, hd) returns a Date at UTC midnight on the corresponding Gregorian day. Round-trips are therefore exact and produce identical results on any machine regardless of local timezone.

Converting a zone-aware Luxon DateTime. Pass the DateTime's calendar fields, not .toJSDate(), unless the DateTime is already pinned to UTC:

import { DateTime } from 'luxon';
import { toHijri } from 'luxon-hijri';

const dt = DateTime.now().setZone('America/New_York');

// Correct — reads the calendar date in the DateTime's own zone
const h = toHijri(new Date(Date.UTC(dt.year, dt.month - 1, dt.day)));

// Wrong if dt is not UTC-anchored — toJSDate() produces local-zone midnight,
// which may land on the previous UTC day for western timezones
// const h = toHijri(dt.toJSDate());

ISO string parsing. new Date("2025-03-01") parses as UTC midnight — that is exactly the right input for a calendar-day conversion and will produce the correct Hijri date.

Note: determining when the Hijri day begins at local sunset is out of scope for this library.

TypeScript

import { toHijri, toGregorian, formatHijriDate, isValidHijriDate } from 'luxon-hijri';
import type { HijriDate, CalendarSystem, ConversionOptions } from 'luxon-hijri';

Documentation

Full API reference, format token guide, calendar background, and architecture notes: GitHub Wiki

Acknowledgments

The Umm al-Qura table is derived from data published by KACST (King Abdulaziz City for Science and Technology). The FCNA new moon algorithm follows Jean Meeus, "Astronomical Algorithms," 2nd ed., Chapter 49.

License

MIT. Copyright (c) 2024-2026 Aric Camarata.