mirror of
https://github.com/acamarata/hijri-core.git
synced 2026-06-30 18:54:27 +00:00
docs: add quickstart, advanced guide, and examples for hijri-core
This commit is contained in:
parent
4d231b8aec
commit
b6ee3b08d0
4 changed files with 325 additions and 0 deletions
48
.github/wiki/examples/gregorian-to-hijri.md
vendored
Normal file
48
.github/wiki/examples/gregorian-to-hijri.md
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Example: Gregorian to Hijri Conversion Table
|
||||
|
||||
Convert a range of notable Gregorian dates to Hijri.
|
||||
|
||||
```js
|
||||
import { toHijri } from 'hijri-core';
|
||||
|
||||
const MONTH_NAMES = [
|
||||
'', 'Muharram', 'Safar', "Rabi' al-Awwal", "Rabi' al-Thani",
|
||||
'Jumada al-Ula', 'Jumada al-Akhirah', 'Rajab', "Sha'ban",
|
||||
'Ramadan', 'Shawwal', "Dhu al-Qi'dah", 'Dhu al-Hijjah',
|
||||
];
|
||||
|
||||
const dates = [
|
||||
{ label: 'Islamic New Year 1446', date: new Date('2024-07-07') },
|
||||
{ label: 'Ashura 1446', date: new Date('2024-07-16') },
|
||||
{ label: 'Ramadan 1446 start', date: new Date('2025-03-01') },
|
||||
{ label: 'Eid al-Fitr 1446', date: new Date('2025-03-30') },
|
||||
{ label: 'Arafat Day 1446', date: new Date('2025-06-05') },
|
||||
{ label: 'Eid al-Adha 1446', date: new Date('2025-06-06') },
|
||||
];
|
||||
|
||||
console.log(`${'Event'.padEnd(26)} Gregorian Hijri`);
|
||||
console.log('-'.repeat(62));
|
||||
|
||||
for (const { label, date } of dates) {
|
||||
const h = toHijri(date);
|
||||
const greg = date.toISOString().slice(0, 10);
|
||||
const hijri = h
|
||||
? `${h.day} ${MONTH_NAMES[h.month]} ${h.year} AH`
|
||||
: 'out of range';
|
||||
|
||||
console.log(`${label.padEnd(26)} ${greg} ${hijri}`);
|
||||
}
|
||||
```
|
||||
|
||||
Sample output:
|
||||
|
||||
```
|
||||
Event Gregorian Hijri
|
||||
--------------------------------------------------------------
|
||||
Islamic New Year 1446 2024-07-07 1 Muharram 1446 AH
|
||||
Ashura 1446 2024-07-16 10 Muharram 1446 AH
|
||||
Ramadan 1446 start 2025-03-01 1 Ramadan 1446 AH
|
||||
Eid al-Fitr 1446 2025-03-30 1 Shawwal 1446 AH
|
||||
Arafat Day 1446 2025-06-05 9 Dhu al-Hijjah 1446 AH
|
||||
Eid al-Adha 1446 2025-06-06 10 Dhu al-Hijjah 1446 AH
|
||||
```
|
||||
53
.github/wiki/examples/ramadan-calendar.md
vendored
Normal file
53
.github/wiki/examples/ramadan-calendar.md
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Example: Ramadan Calendar Generator
|
||||
|
||||
Generate the full Ramadan calendar for a given Hijri year showing Gregorian dates.
|
||||
|
||||
```js
|
||||
import { toGregorian, daysInHijriMonth } from 'hijri-core';
|
||||
|
||||
const HIJRI_YEAR = 1446;
|
||||
const RAMADAN = 9;
|
||||
|
||||
const totalDays = daysInHijriMonth(HIJRI_YEAR, RAMADAN);
|
||||
|
||||
console.log(`Ramadan ${HIJRI_YEAR} AH — ${totalDays} days`);
|
||||
console.log('');
|
||||
console.log('Day Gregorian Weekday');
|
||||
console.log('-'.repeat(32));
|
||||
|
||||
const DAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
||||
|
||||
for (let d = 1; d <= totalDays; d++) {
|
||||
const greg = toGregorian(HIJRI_YEAR, RAMADAN, d);
|
||||
const iso = greg.toISOString().slice(0, 10);
|
||||
const weekday = DAYS[greg.getUTCDay()];
|
||||
|
||||
// Mark Jumu'ah
|
||||
const marker = weekday === 'Friday' ? ' ★' : '';
|
||||
|
||||
console.log(`${String(d).padStart(3)} ${iso} ${weekday}${marker}`);
|
||||
}
|
||||
```
|
||||
|
||||
Sample output:
|
||||
|
||||
```
|
||||
Ramadan 1446 AH — 30 days
|
||||
|
||||
Day Gregorian Weekday
|
||||
--------------------------------
|
||||
1 2025-03-01 Saturday
|
||||
2 2025-03-02 Sunday
|
||||
3 2025-03-03 Monday
|
||||
4 2025-03-04 Tuesday
|
||||
5 2025-03-05 Wednesday
|
||||
6 2025-03-06 Thursday
|
||||
7 2025-03-07 Friday ★
|
||||
8 2025-03-08 Saturday
|
||||
...
|
||||
28 2025-03-28 Friday ★
|
||||
29 2025-03-29 Saturday
|
||||
30 2025-03-30 Sunday
|
||||
```
|
||||
|
||||
> Eid al-Fitr falls on 1 Shawwal — the day after the last day of Ramadan.
|
||||
130
.github/wiki/guides/advanced.md
vendored
Normal file
130
.github/wiki/guides/advanced.md
vendored
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# Advanced Usage
|
||||
|
||||
## Iterating over a Hijri month
|
||||
|
||||
Build a calendar grid for a given Hijri month:
|
||||
|
||||
```js
|
||||
import { daysInHijriMonth, toGregorian } from 'hijri-core';
|
||||
|
||||
const HY = 1446;
|
||||
const HM = 9; // Ramadan
|
||||
|
||||
const days = daysInHijriMonth(HY, HM);
|
||||
|
||||
for (let d = 1; d <= days; d++) {
|
||||
const greg = toGregorian(HY, HM, d);
|
||||
console.log(`${String(d).padStart(2)} Ramadan — ${greg.toISOString().slice(0, 10)}`);
|
||||
}
|
||||
```
|
||||
|
||||
## Custom calendar engines
|
||||
|
||||
`hijri-core` exposes a registry so you can plug in your own conversion engine — a lunar sighting authority, an adjusted algorithmic calendar, or a custom dataset:
|
||||
|
||||
```js
|
||||
import { registerCalendar, toHijri } from 'hijri-core';
|
||||
|
||||
registerCalendar('my-calendar', {
|
||||
toHijri(date) {
|
||||
// Return { year, month, day, monthName, calendar: 'my-calendar' } or null
|
||||
// date is a JS Date; use local components for timezone-safe lookup
|
||||
const y = date.getFullYear();
|
||||
const m = date.getMonth() + 1;
|
||||
const d = date.getDate();
|
||||
// ... your logic
|
||||
return null;
|
||||
},
|
||||
toGregorian(hy, hm, hd) {
|
||||
// Return a Date (UTC midnight) or null for out-of-range
|
||||
return null;
|
||||
},
|
||||
isValidHijriDate(hy, hm, hd) {
|
||||
return false;
|
||||
},
|
||||
daysInHijriMonth(hy, hm) {
|
||||
return 29;
|
||||
},
|
||||
});
|
||||
|
||||
// Use it just like the built-in calendars
|
||||
const result = toHijri(new Date('2025-03-20'), { calendar: 'my-calendar' });
|
||||
```
|
||||
|
||||
## Generating a Ramadan calendar
|
||||
|
||||
Print the Gregorian dates for Ramadan across multiple years:
|
||||
|
||||
```js
|
||||
import { toGregorian } from 'hijri-core';
|
||||
|
||||
const RAMADAN = 9;
|
||||
|
||||
for (let hy = 1440; hy <= 1450; hy++) {
|
||||
const start = toGregorian(hy, RAMADAN, 1);
|
||||
const end = toGregorian(hy, RAMADAN + 1, 1);
|
||||
|
||||
if (!start) continue;
|
||||
|
||||
// Ramadan ends the day before Shawwal 1
|
||||
const last = new Date(end.getTime() - 86400_000);
|
||||
|
||||
console.log(
|
||||
`${hy} AH: ${start.toISOString().slice(0, 10)} — ${last.toISOString().slice(0, 10)}`
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Date range validation
|
||||
|
||||
Before batch-processing a range of dates, check the calendar bounds:
|
||||
|
||||
```js
|
||||
import { toHijri } from 'hijri-core';
|
||||
|
||||
function isSupportedDate(date) {
|
||||
return toHijri(date) !== null;
|
||||
}
|
||||
|
||||
const dates = [
|
||||
new Date('1900-01-01'), // outside UAQ range
|
||||
new Date('2000-01-01'), // inside range
|
||||
new Date('2077-11-16'), // may be outside future range
|
||||
];
|
||||
|
||||
for (const d of dates) {
|
||||
const supported = isSupportedDate(d);
|
||||
console.log(`${d.toISOString().slice(0, 10)}: ${supported ? 'supported' : 'out of range'}`);
|
||||
}
|
||||
```
|
||||
|
||||
## FCNA vs UAQ differences
|
||||
|
||||
FCNA and UAQ can differ by one or two days around month transitions:
|
||||
|
||||
```js
|
||||
import { toHijri } from 'hijri-core';
|
||||
|
||||
const dates = [
|
||||
new Date('2025-03-01'),
|
||||
new Date('2025-03-29'),
|
||||
new Date('2025-03-30'),
|
||||
new Date('2025-03-31'),
|
||||
];
|
||||
|
||||
console.log('Date UAQ FCNA');
|
||||
console.log('-'.repeat(48));
|
||||
|
||||
for (const d of dates) {
|
||||
const uaq = toHijri(d, { calendar: 'uaq' });
|
||||
const fcna = toHijri(d, { calendar: 'fcna' });
|
||||
|
||||
const fmtH = (h) => h ? `${h.day}/${h.month}/${h.year}` : 'out of range';
|
||||
console.log(`${d.toISOString().slice(0, 10)} ${fmtH(uaq).padEnd(16)} ${fmtH(fcna)}`);
|
||||
}
|
||||
```
|
||||
|
||||
## Related pages
|
||||
|
||||
- [API Reference](../API-Reference) — full function signatures and types
|
||||
- [Architecture](../Architecture) — calendar engine interface, table format, accuracy bounds
|
||||
94
.github/wiki/guides/quickstart.md
vendored
Normal file
94
.github/wiki/guides/quickstart.md
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# Quick Start
|
||||
|
||||
Five minutes from install to Hijri date conversions.
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install hijri-core
|
||||
```
|
||||
|
||||
## Convert Gregorian to Hijri
|
||||
|
||||
```js
|
||||
import { toHijri } from 'hijri-core';
|
||||
|
||||
const d = new Date('2025-03-20');
|
||||
const h = toHijri(d);
|
||||
|
||||
console.log(h);
|
||||
// { year: 1446, month: 9, day: 20, monthName: 'Ramadan', calendar: 'uaq' }
|
||||
|
||||
console.log(`${h.day} ${h.monthName} ${h.year} AH`);
|
||||
// 20 Ramadan 1446 AH
|
||||
```
|
||||
|
||||
## Convert Hijri to Gregorian
|
||||
|
||||
```js
|
||||
import { toGregorian } from 'hijri-core';
|
||||
|
||||
const greg = toGregorian(1446, 9, 1);
|
||||
|
||||
console.log(greg.toISOString().slice(0, 10));
|
||||
// 2025-03-01
|
||||
```
|
||||
|
||||
## Check a Hijri date is valid
|
||||
|
||||
```js
|
||||
import { isValidHijriDate } from 'hijri-core';
|
||||
|
||||
isValidHijriDate(1446, 9, 30); // true — Ramadan 1446 has 30 days
|
||||
isValidHijriDate(1446, 9, 31); // false — no 31st day in any Hijri month
|
||||
isValidHijriDate(1446, 13, 1); // false — Hijri calendar has only 12 months
|
||||
```
|
||||
|
||||
## Days in a month
|
||||
|
||||
```js
|
||||
import { daysInHijriMonth } from 'hijri-core';
|
||||
|
||||
daysInHijriMonth(1446, 9); // 30 (Ramadan 1446)
|
||||
daysInHijriMonth(1446, 10); // 29 (Shawwal 1446)
|
||||
```
|
||||
|
||||
## Choosing a calendar
|
||||
|
||||
Two calendars are built in:
|
||||
|
||||
| Name | Description |
|
||||
| ---- | ----------- |
|
||||
| `'uaq'` | Umm al-Qura (Saudi Arabia, official tabular calendar) — **default** |
|
||||
| `'fcna'` | Fiqh Council of North America (astronomical computation for North America) |
|
||||
|
||||
```js
|
||||
import { toHijri } from 'hijri-core';
|
||||
|
||||
const d = new Date('2025-03-20');
|
||||
|
||||
const uaq = toHijri(d, { calendar: 'uaq' });
|
||||
const fcna = toHijri(d, { calendar: 'fcna' });
|
||||
|
||||
console.log(uaq.day, uaq.month, uaq.year);
|
||||
console.log(fcna.day, fcna.month, fcna.year);
|
||||
```
|
||||
|
||||
## Out-of-range dates
|
||||
|
||||
Both built-in calendars cover a finite date range. `toHijri` and `toGregorian` return `null` when the input falls outside the supported range:
|
||||
|
||||
```js
|
||||
import { toHijri } from 'hijri-core';
|
||||
|
||||
const result = toHijri(new Date('1800-01-01'));
|
||||
if (result === null) {
|
||||
console.log('Date outside calendar range');
|
||||
}
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
- [API Reference](../API-Reference) — all functions and types
|
||||
- [Advanced Guide](advanced) — custom calendar engines, iteration, Ramadan calendars
|
||||
- [Architecture](../Architecture) — calendar engine design, table format
|
||||
Loading…
Reference in a new issue