Calendrical.Islamic.UmmAlQura.Astronomical
(Calendrical v0.3.0)
Copy Markdown
Implements the Umm al-Qura calendar for determining the first day of each Hijri month using the astronomical rules documented by R. H. van Gent.
Eras
Era 2 (1392–1419 AH / 1972–1999 CE) — Conjunction rule (best effort). The first day of the month is the Gregorian day following the geocentric conjunction. This reproduces 96.7 % of the published KACST dates; the remaining ≈ 3 % differ by one day due to undocumented details in the historical Saudi determination process.
Era 3 (1420–1422 AH / 1999–2002 CE) — Moonset-only rule. On the 29th of the current month, if moonset occurs after sunset at Mecca the next day is 1st of the new month; otherwise the month is extended to 30 days.
Era 4 (1423 AH onward / 2002 CE onward) — Full Umm al-Qura rule. On the 29th day of the current Hijri month, if both of the following conditions hold as observed from Mecca (21.4225° N, 39.8262° E), then the following day is the 1st day of the new Hijri month:
- The geocentric conjunction occurs before sunset in Mecca.
- Moonset in Mecca occurs after sunset in Mecca.
If either condition fails, the current month is extended to 30 days.
Years before 1392 AH are not supported because no reliable astronomical rule has been established for that period.
Accuracy
The astronomical computation uses centre-of-disk sunset and centre-of-disk moonset conventions (matching Skyfield/van Gent) and achieves 99.7 % agreement (934 of 937 months) with the van Gent reference dataset for Era 4 (1423–1500 AH). The three boundary-case months where the algorithm disagrees are:
| Hijri month | Gregorian (van Gent) | Gregorian (algorithm) | Root cause |
|---|---|---|---|
| 1446/6 | 2024-12-02 | 2024-12-03 | Moonset 7 s before sunset |
| 1475/11 | 2053-06-17 | 2053-06-18 | Moonset 3 s before sunset (Skyfield also fails) |
| 1485/10 | 2063-01-30 | 2063-01-31 | Moonset 5 s before sunset |
All three involve moonset-sunset gaps of less than 10 seconds — below
the precision floor of any rise/set calculation given atmospheric
refraction uncertainty (±2 arcmin ≈ ±10 s). The van Gent reference
data — independently corroborated by the hijridate package (dralshehri,
sourced from KACST archival publications) — is used as the canonical
calendar via Calendrical.Islamic.UmmAlQura.ReferenceData.
Reference
- R.H. van Gent, "The Umm al-Qura Calendar of Saudi Arabia", https://webspace.science.uu.nl/~gent0113/islam/ummalqura_rules.htm
- hijridate (dralshehri), independent KACST-verified dataset, https://github.com/dralshehri/hijri-converter
- Dershowitz & Reingold, Calendrical Calculations (4th ed.), Chapter 6
Summary
Functions
Returns a map with the detailed astronomical data used in evaluating the Umm al-Qura rule for the given Gregorian date (which should be the 29th day of the current Hijri month).
Calculates the Gregorian date of the 1st day of the Hijri month identified by
hijri_year and hijri_month (1-based, 1 = Muharram … 12 = Dhū al-Ḥijja).
Functions
Returns a map with the detailed astronomical data used in evaluating the Umm al-Qura rule for the given Gregorian date (which should be the 29th day of the current Hijri month).
Returned map keys:
:date– the candidate 29th Gregorian date:conjunction_utc–DateTimeof geocentric conjunction (new moon):sunset_mecca–DateTimeof sunset in Mecca (UTC):moonset_mecca–DateTimeof moonset in Mecca (UTC), or:no_time:conjunction_before_sunset– boolean:moonset_after_sunset– boolean:new_month_starts_next_day– boolean (true iff both conditions are met)
@spec first_day_of_month(pos_integer(), 1..12) :: {:ok, Date.t()} | {:error, term()}
Calculates the Gregorian date of the 1st day of the Hijri month identified by
hijri_year and hijri_month (1-based, 1 = Muharram … 12 = Dhū al-Ḥijja).
- Era 4 (≥ 1423 AH): full Umm al-Qura rule (conjunction before sunset AND moonset after sunset).
- Era 3 (1420–1422 AH): moonset-after-sunset only.
- Era 2 (1392–1419 AH): conjunction within 3 h of 0 h UTC.
Returns {:ok, %Date{}} on success, or {:error, reason} if the year/month
falls outside the supported range (< 1392 AH or invalid month).
Examples
iex> Calendrical.Islamic.UmmAlQura.Astronomical.first_day_of_month(1446, 9)
{:ok, ~D[2025-03-01]} # Era 4 — full rule
iex> Calendrical.Islamic.UmmAlQura.Astronomical.first_day_of_month(1421, 1)
{:ok, ~D[2000-04-06]} # Era 3 — moonset only
iex> Calendrical.Islamic.UmmAlQura.Astronomical.first_day_of_month(1400, 9)
{:ok, ~D[1980-07-13]} # Era 2 — conjunction rule