# `Calendrical.Islamic.UmmAlQura.Astronomical`

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**:

    1. The geocentric conjunction occurs **before** sunset in Mecca.
    2. 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

# `evaluate_era_4_conditions`

```elixir
@spec evaluate_era_4_conditions(Date.t()) :: {:ok, map()} | {:error, term()}
```

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`    – `DateTime` of geocentric conjunction (new moon)
  - `:sunset_mecca`       – `DateTime` of sunset in Mecca (UTC)
  - `:moonset_mecca`      – `DateTime` of 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)

# `first_day_of_month`

```elixir
@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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
