# `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 van Gent's dates
  for the era; 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. After them the calendar
reaches as far as the installed JPL ephemeris: to about 1524 AH with the
ephemeris Astro bundles, and about 1575 AH with the full one.

## 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).

This module is tested against van Gent's tables
(`Calendrical.Islamic.UmmAlQura.ReferenceData`), which apply the same
rules.

## Against KACST's table and ICU

For the official Saudi calendar use `Calendrical.Islamic.UmmAlQura`,
which is built from KACST's published month lengths and, after 1500 AH,
ICU's. This calendar computes the published rule; the tables follow it
only so far.

* **To 1450 AH the rule is KACST's.** 335 of the 336 months of 1423 to
  1450 AH begin on the day KACST's table begins them.

* **From 1451 AH the tables begin a third of months a day later.** 209 of
  the 600 months of 1451 to 1500 AH begin a day after this calendar's, and
  so do 92 of the 287 months of 1501 to 1524 AH in ICU's table, which is
  the same data. Never a day earlier.

* **They are the months whose moon barely sets after the sun.** On the
  29th each of those months meets the rule, but its moon sets less than
  about 20 minutes after the sun; the months the tables begin as this
  calendar does have a median of 35 minutes.

We think the reason is that the tables' months from 1451 AH, which begins
in 2029 CE, are KACST's projections rather than announced dates, and are
computed by a stricter procedure than the published rule. That procedure
is not documented: it is not a crescent-visibility criterion (Yallop's
and Odeh's separate the months only far below any of their zones), not
another site (Riyadh fits worse than Mecca), and not a difference of rise
and set conventions, which is a minute or two. ICU and the JDK carry
KACST's table without a rule of their own, so they do not explain it
either. Until KACST's criterion is known, this calendar keeps the
published rule.

## 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)](https://github.com/dralshehri/hijri-converter), which ships van Gent's tables.

* Dershowitz & Reingold, *Calendrical Calculations* (4th ed.), Chapter 6.

# `evaluate_era_4_conditions`

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

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).

### Arguments

* `date` is the Gregorian `t:Date.t/0` of the candidate 29th day
  of the Hijri month.

### Returns

* `{:ok, map}` where the map has these keys:

  * `:date` is the candidate 29th Gregorian date.

  * `:conjunction_utc` is the `t:DateTime.t/0` of the geocentric
    conjunction (new moon).

  * `:sunset_mecca` is the `t:DateTime.t/0` of sunset in Mecca (UTC).

  * `:moonset_mecca` is the `t:DateTime.t/0` of moonset in Mecca
    (UTC), or `:no_time`.

  * `:conjunction_before_sunset?` is a boolean.

  * `:moonset_after_sunset?` is a boolean.

  * `:new_month_starts_next_day?` is `true` when both conditions
    are met, otherwise `false`.

* `{:error, %Calendrical.UnsupportedDateRangeError{}}` for a date the
  installed ephemeris does not cover, or

* `{:error, %Calendrical.AstronomyError{}}` where the sun does not set
  at Mecca that day.

### Examples

    iex> {:ok, evaluation} =
    ...>   Calendrical.Islamic.UmmAlQura.Astronomical.evaluate_era_4_conditions(~D[2025-02-28])
    iex> evaluation.new_month_starts_next_day?
    true

# `first_day_of_month`

```elixir
@spec first_day_of_month(pos_integer(), 1..12) ::
  {:ok, Date.t()} | {:error, Exception.t()}
```

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.

### Arguments

* `hijri_year` is the Hijri year, from 1392 AH.

* `hijri_month` is the Hijri month, from `1` to `12`.

### Returns

* `{:ok, date}` where `date` is the Gregorian `t:Date.t/0` of the
  first day of the month.

* `{:error, %Calendrical.UnsupportedDateRangeError{}}` for a year before
  1392 AH, or a month the installed ephemeris does not cover, or

* `{:error, %Calendrical.InvalidMonthError{}}` for a month not from 1
  to 12.

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