No description
Find a file
Aric Camarata b98ab39a13 fix: mark dist files as having side effects
The index module registers built-in calendar engines at load time via
registerCalendar(). sideEffects:false was incorrect and could cause
bundlers to tree-shake those registration calls. Mark only the dist
entry points as having side effects so tree-shaking still works for
everything else.
2026-02-25 14:14:42 -05:00
.github/workflows feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
.wiki feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
src feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
.editorconfig feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
.gitignore feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
.npmrc feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
.nvmrc feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
CHANGELOG.md feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
LICENSE feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
package.json fix: mark dist files as having side effects 2026-02-25 14:14:42 -05:00
pnpm-lock.yaml feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
pnpm-workspace.yaml feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
README.md feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
test-cjs.cjs feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
test.mjs feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
tsconfig.json feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00
tsup.config.ts feat: initial release of hijri-core v1.0.0 2026-02-25 14:06:02 -05:00

hijri-core

npm CI license

Zero-dependency Hijri calendar engine. Supports the Umm al-Qura (UAQ) and FCNA/ISNA calendars out of the box. Extensible via a calendar registry for custom implementations.

Installation

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

Quick Start

import { toHijri, toGregorian, isValidHijriDate, daysInHijriMonth } from 'hijri-core';

// Gregorian to Hijri (UAQ, default)
const hijri = toHijri(new Date(2025, 2, 1));
// { hy: 1446, hm: 9, hd: 1 }

// Hijri to Gregorian (UAQ)
const greg = toGregorian(1446, 9, 1);
// Date: 2025-03-01

// FCNA/ISNA calendar
const hijriFcna = toHijri(new Date('2025-03-01'), { calendar: 'fcna' });
const gregFcna  = toGregorian(1446, 9, 1, { calendar: 'fcna' });

// Validation and month length
isValidHijriDate(1444, 9, 1);  // true
daysInHijriMonth(1444, 9);     // 29

Custom Calendar

import { registerCalendar, toHijri, type CalendarEngine } from 'hijri-core';

const myEngine: CalendarEngine = {
  id: 'my-calendar',
  toHijri: (date) => { /* your logic */ return { hy: 1446, hm: 1, hd: 1 }; },
  toGregorian: (hy, hm, hd) => { /* your logic */ return new Date(); },
  isValid: (hy, hm, hd) => hy > 0 && hm >= 1 && hm <= 12 && hd >= 1,
  daysInMonth: (hy, hm) => 30,
};

registerCalendar('my-calendar', myEngine);

const result = toHijri(new Date(), { calendar: 'my-calendar' });

API

Conversion functions

Function Parameters Returns Notes
toHijri(date, opts?) Date, ConversionOptions? HijriDate | null Throws on invalid Date
toGregorian(hy, hm, hd, opts?) number, number, number, ConversionOptions? Date | null Throws on invalid Hijri
isValidHijriDate(hy, hm, hd, opts?) number, number, number, ConversionOptions? boolean
daysInHijriMonth(hy, hm, opts?) number, number, ConversionOptions? number

ConversionOptions.calendar defaults to 'uaq'. Pass 'fcna' or any registered calendar name.

Registry functions

Function Parameters Returns
registerCalendar(name, engine) string, CalendarEngine void
getCalendar(name) string CalendarEngine
listCalendars() none string[]

Data exports

Export Type Description
hDatesTable HijriYearRecord[] Full Umm al-Qura reference table (184 entries)
hmLong string[] Long month names (e.g., "Ramadan")
hmMedium string[] Medium month names (e.g., "Ramadan")
hmShort string[] Short month names (e.g., "Ram")
hwLong string[] Long weekday names
hwShort string[] Short weekday names
hwNumeric number[] Weekday numbers (1 = Sunday)

Custom Calendars

Implement the CalendarEngine interface to add any calendar system:

interface CalendarEngine {
  readonly id: string;
  toHijri(date: Date): HijriDate | null;
  toGregorian(hy: number, hm: number, hd: number): Date | null;
  isValid(hy: number, hm: number, hd: number): boolean;
  daysInMonth(hy: number, hm: number): number;
}

Register with registerCalendar('my-id', myEngine). Then pass { calendar: 'my-id' } to any conversion function.

Compatibility

  • Node.js 20, 22, 24
  • Modern browsers (ESM build)
  • CommonJS and ESM

TypeScript

import type { HijriDate, HijriYearRecord, CalendarEngine, ConversionOptions } from 'hijri-core';

Documentation

Full API reference and architecture notes: GitHub Wiki

License

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