# `Calendrical.Ecclesiastical`

Computes the dates of Christian ecclesiastical events for a given
Gregorian year.

This module bundles the Reingold-style algorithms for the
movable and fixed festivals of the Western, Eastern Orthodox, and
*astronomical* (WCC 1997 proposed) Christian liturgical traditions.

## Three traditions

Calendrical exposes three different *Easter* computations because
they really are three distinct calculations. The differences are
small in most years (and the three frequently coincide) but the
underlying definitions and target audiences are different.

| Function | Method | Calendar | Used by |
|---|---|---|---|
| `easter_sunday/1` | Gregorian *computus* (tabular) | Western Gregorian | Roman Catholic, Anglican, most Protestants |
| `astronomical_easter_sunday/1` | **Astronomical** Paschal Full Moon + first Sunday after | (proleptic Gregorian, UTC) | "Astronomical Easter" — proposed by the World Council of Churches in 1997, no Church follows it |
| `orthodox_easter_sunday/1` | Julian *computus* (tabular) | Eastern Orthodox Julian | Eastern Orthodox |

Western Easter and Orthodox Easter coincide in years like **2025**;
they can differ by one, four, or five weeks in other years
because the Western (Gregorian) and Eastern (Julian) computus use
different lookup tables and different leap-year rules. The
astronomical reckoning agrees with the Western Gregorian computus
for most years in the 21st century but is not actually used by any
Church — it is included here for comparison and research.

## Movable feasts (Western)

* `easter_sunday/1` — Western Easter Sunday (Gregorian computus).

* `good_friday/1` — Western Good Friday (two days before Western
  Easter Sunday).

* `pentecost/1` — Western Pentecost Sunday, exactly 49 days after
  `easter_sunday/1`.

* `advent/1` — the first Sunday of Advent, the Sunday closest to
  30 November.

## Movable feasts (Eastern Orthodox, Julian-based)

All Eastern Orthodox functions return `Calendrical.Julian` dates
so that the Julian-calendar context is immediately visible in the
result. Use `Date.convert/2` to project them onto another calendar.

* `orthodox_easter_sunday/1` — Eastern Orthodox Easter Sunday
  (Julian computus).

* `orthodox_good_friday/1` — Eastern Orthodox Good Friday (two
  days before Orthodox Easter Sunday).

* `orthodox_pentecost/1` — Eastern Orthodox Pentecost Sunday,
  exactly 49 days after `orthodox_easter_sunday/1`.

* `orthodox_advent/1` — the start of the Eastern Orthodox
  *Nativity Fast* on **15 November** (Julian). This is a fixed
  40-day Lenten preparation for Christmas, not a movable Sunday
  observance. Eastern Orthodoxy does not have a direct equivalent
  of the Western "Advent Sunday".

## Movable feasts (astronomical, WCC 1997)

* `astronomical_easter_sunday/1` — Astronomical Easter Sunday: the
  first Sunday strictly after the astronomical Paschal Full Moon.
  This is the calculation proposed by the World Council of
  Churches at the 1997 Aleppo Consultation as a basis for unifying
  Western and Eastern Easter dates. No Church has yet adopted it.

* `astronomical_good_friday/1` — Astronomical Good Friday (two
  days before `astronomical_easter_sunday/1`).

* `paschal_full_moon/1` — the *astronomical* Paschal Full Moon —
  the first astronomical full moon on or after the March vernal
  equinox. Used internally by the astronomical Easter functions.
  Uses the `Astro` library for the equinox and full-moon
  calculations.

## Fixed feasts

* `christmas/1` — Western (Gregorian) Christmas Day,
  25 December.

* `epiphany/1` — Epiphany as observed in the United States: the
  first Sunday after 1 January. (The traditional fixed-date
  Epiphany on 6 January is also widely observed.)

* `eastern_orthodox_christmas/1` — Eastern Orthodox Christmas
  Day, 25 December (Julian) projected onto the proleptic Gregorian
  calendar. May fall in either January or December of the
  requested Gregorian year, so a list is returned.

* `coptic_christmas/1` — Coptic Christmas, 29 Koiak in the Coptic
  calendar (`Calendrical.Coptic`), projected onto the proleptic
  Gregorian calendar. Like Eastern Orthodox Christmas, may return
  zero, one, or two dates.

## Reference

- Dershowitz & Reingold, *Calendrical Calculations* (4th ed.),
  Chapter 9 ("Ecclesiastical Calendars").

- World Council of Churches, *Towards a Common Date for Easter*,
  Aleppo Consultation, 1997.

# `advent`

```elixir
@spec advent(Calendar.year()) :: Date.t()
```

Returns the date of *Advent Sunday* in the given Gregorian year:
the Sunday closest to 30 November.

## Examples

    iex> Calendrical.Ecclesiastical.advent(2024)
    ~D[2024-12-01 Calendrical.Gregorian]

    iex> Calendrical.Ecclesiastical.advent(2025)
    ~D[2025-11-30 Calendrical.Gregorian]

# `astronomical_easter_sunday`

```elixir
@spec astronomical_easter_sunday(Calendar.year()) ::
  {:ok, Date.t()} | {:error, Exception.t()}
```

Returns the date of *Astronomical Easter Sunday* in the given
Gregorian year — the first Sunday strictly after the astronomical
Paschal Full Moon.

This is the World Council of Churches' 1997 Aleppo Consultation
proposal for unifying Western and Eastern Easter dates. **No
Church currently follows it.** It is included for comparison
with the Western (`easter_sunday/1`) and Eastern Orthodox
(`orthodox_easter_sunday/1`) computus calculations.

Uses `paschal_full_moon/1` (which in turn uses the `Astro`
library) and so is restricted to the year range `1000..3000`.
The result is returned as a `Calendar.ISO` `Date`.

## Examples

    iex> Calendrical.Ecclesiastical.astronomical_easter_sunday(2024)
    {:ok, ~D[2024-03-31]}

    iex> Calendrical.Ecclesiastical.astronomical_easter_sunday(2025)
    {:ok, ~D[2025-04-20]}

# `astronomical_good_friday`

```elixir
@spec astronomical_good_friday(Calendar.year()) ::
  {:ok, Date.t()} | {:error, Exception.t()}
```

Returns the date of *Astronomical Good Friday* in the given
Gregorian year — exactly two days before
`astronomical_easter_sunday/1`.

## Examples

    iex> Calendrical.Ecclesiastical.astronomical_good_friday(2024)
    {:ok, ~D[2024-03-29]}

    iex> Calendrical.Ecclesiastical.astronomical_good_friday(2025)
    {:ok, ~D[2025-04-18]}

# `christmas`

```elixir
@spec christmas(Calendar.year()) :: Date.t()
```

Returns the date of Western *Christmas Day* (25 December) in the
given Gregorian year.

## Examples

    iex> Calendrical.Ecclesiastical.christmas(2024)
    ~D[2024-12-25 Calendrical.Gregorian]

# `coptic_christmas`

```elixir
@spec coptic_christmas(Calendar.year()) :: [Date.t()]
```

Returns the dates of *Coptic Christmas* (29 Koiak in the Coptic
calendar) that fall in the given Gregorian year.

Returns a list of zero, one, or two `t:Calendar.date/0` values for the
same reason as `eastern_orthodox_christmas/1`.

## Examples

    iex> Calendrical.Ecclesiastical.coptic_christmas(2024)
    [~D[2024-01-08 Calendrical.Gregorian]]

    iex> Calendrical.Ecclesiastical.coptic_christmas(2025)
    [~D[2025-01-07 Calendrical.Gregorian]]

# `easter_sunday`

```elixir
@spec easter_sunday(Calendar.year()) :: Date.t()
```

Returns the date of Western *Easter Sunday* in the given Gregorian
year, computed by the Gregorian *computus*.

This is the calculation used by the Roman Catholic Church, the
Anglican Communion, and most Protestant churches. The algorithm is
the Nicaean rule corrected for the Gregorian century rule and the
Metonic-cycle inaccuracy.

## Examples

    iex> Calendrical.Ecclesiastical.easter_sunday(2024)
    ~D[2024-03-31 Calendrical.Gregorian]

    iex> Calendrical.Ecclesiastical.easter_sunday(2025)
    ~D[2025-04-20 Calendrical.Gregorian]

    iex> Calendrical.Ecclesiastical.easter_sunday(2026)
    ~D[2026-04-05 Calendrical.Gregorian]

# `eastern_orthodox_christmas`

```elixir
@spec eastern_orthodox_christmas(Calendar.year()) :: [Date.t()]
```

Returns the dates of *Eastern Orthodox Christmas* (25 December
Julian) that fall in the given Gregorian year.

Returns a list of zero, one, or two `t:Calendar.date/0` values because
the Julian-to-Gregorian offset can place 25 December Julian in
either January or December of the same Gregorian year.

## Examples

    iex> Calendrical.Ecclesiastical.eastern_orthodox_christmas(2024)
    [~D[2024-01-07 Calendrical.Gregorian]]

    iex> Calendrical.Ecclesiastical.eastern_orthodox_christmas(2025)
    [~D[2025-01-07 Calendrical.Gregorian]]

# `epiphany`

```elixir
@spec epiphany(Calendar.year()) :: Date.t()
```

Returns the date of *Epiphany* as observed in the United States in
the given Gregorian year: the first Sunday after 1 January.

Note that the traditional fixed-date Epiphany falls on 6 January
and is more widely observed elsewhere.

## Examples

    iex> Calendrical.Ecclesiastical.epiphany(2024)
    ~D[2024-01-07 Calendrical.Gregorian]

    iex> Calendrical.Ecclesiastical.epiphany(2025)
    ~D[2025-01-05 Calendrical.Gregorian]

# `good_friday`

```elixir
@spec good_friday(Calendar.year()) :: Date.t()
```

Returns the date of Western *Good Friday* in the given Gregorian
year — exactly two days before `easter_sunday/1`.

## Examples

    iex> Calendrical.Ecclesiastical.good_friday(2024)
    ~D[2024-03-29 Calendrical.Gregorian]

    iex> Calendrical.Ecclesiastical.good_friday(2025)
    ~D[2025-04-18 Calendrical.Gregorian]

# `orthodox_advent`

```elixir
@spec orthodox_advent(Calendar.year()) :: Date.t()
```

Returns the start date of the Eastern Orthodox *Nativity Fast* in
the given Gregorian year — **15 November** in the Julian calendar
(≡ 28 November Gregorian during the current 13-day offset
period).

The Nativity Fast is a fixed 40-day Lenten preparation for
Christmas. Eastern Orthodoxy does not have a direct equivalent of
the Western *Advent Sunday* — there is no movable "first Sunday
of Advent" observance — so this function returns the (fixed)
start of the fast instead.

The result is returned as a `Calendrical.Julian` `Date`.

## Examples

    iex> Calendrical.Ecclesiastical.orthodox_advent(2024)
    ~D[2024-11-15 Calendrical.Julian]

    iex> Calendrical.Ecclesiastical.orthodox_advent(2025)
    ~D[2025-11-15 Calendrical.Julian]

# `orthodox_easter_sunday`

```elixir
@spec orthodox_easter_sunday(Calendar.year()) :: Date.t()
```

Returns the date of Eastern Orthodox *Easter Sunday* in the given
Gregorian year, computed by the Julian *computus*.

The result is returned as a `Calendrical.Julian` `Date` so that
the Julian-calendar context is immediately visible in the result.
Use `Date.convert/2` to project it onto another calendar.

## Examples

    iex> Calendrical.Ecclesiastical.orthodox_easter_sunday(2024)
    ~D[2024-04-22 Calendrical.Julian]

    iex> Calendrical.Ecclesiastical.orthodox_easter_sunday(2025)
    ~D[2025-04-07 Calendrical.Julian]

    iex> {:ok, gregorian} =
    ...>   Date.convert(
    ...>     Calendrical.Ecclesiastical.orthodox_easter_sunday(2024),
    ...>     Calendrical.Gregorian
    ...>   )
    iex> gregorian
    ~D[2024-05-05 Calendrical.Gregorian]

# `orthodox_good_friday`

```elixir
@spec orthodox_good_friday(Calendar.year()) :: Date.t()
```

Returns the date of Eastern Orthodox *Good Friday* in the given
Gregorian year — exactly two days before
`orthodox_easter_sunday/1`.

The result is returned as a `Calendrical.Julian` `Date`.

## Examples

    iex> Calendrical.Ecclesiastical.orthodox_good_friday(2024)
    ~D[2024-04-20 Calendrical.Julian]

    iex> Calendrical.Ecclesiastical.orthodox_good_friday(2025)
    ~D[2025-04-05 Calendrical.Julian]

# `orthodox_pentecost`

```elixir
@spec orthodox_pentecost(Calendar.year()) :: Date.t()
```

Returns the date of Eastern Orthodox *Pentecost Sunday* in the
given Gregorian year — exactly 49 days after
`orthodox_easter_sunday/1`.

The result is returned as a `Calendrical.Julian` `Date`.

## Examples

    iex> Calendrical.Ecclesiastical.orthodox_pentecost(2024)
    ~D[2024-06-10 Calendrical.Julian]

    iex> Calendrical.Ecclesiastical.orthodox_pentecost(2025)
    ~D[2025-05-26 Calendrical.Julian]

# `paschal_full_moon`

```elixir
@spec paschal_full_moon(Calendar.year()) :: {:ok, Date.t()} | {:error, Exception.t()}
```

Returns the date of the *astronomical* Paschal Full Moon for a
given Gregorian year.

The astronomical Paschal Full Moon is the first astronomical full
moon that occurs on or after the March (vernal) equinox. It is the
basis for `astronomical_easter_sunday/1`.

This function returns the *astronomical* PFM, computed from
observed lunar and solar positions via the `Astro` library. It
may occasionally differ by a day or more from the *ecclesiastical*
PFM used by the Western (`easter_sunday/1`) or Eastern
(`orthodox_easter_sunday/1`) computus, which are defined by
tabular rules rather than astronomical observation.

The returned date is a `Calendar.ISO` `Date`. The `Astro` library
returns the underlying instant in UTC.

### Arguments

* `gregorian_year` is the Gregorian year for which to compute the
  Paschal Full Moon. Must be in the range `1000..3000` due to the
  underlying equinox-calculation precision.

### Returns

* `{:ok, date}` where `date` is the `t:Calendar.date/0` of the Paschal
  Full Moon in UTC, or

* `{:error, exception}` if the calculation cannot be performed.

### Examples

    iex> Calendrical.Ecclesiastical.paschal_full_moon(2024)
    {:ok, ~D[2024-03-25]}

    iex> Calendrical.Ecclesiastical.paschal_full_moon(2025)
    {:ok, ~D[2025-04-13]}

# `pentecost`

```elixir
@spec pentecost(Calendar.year()) :: Date.t()
```

Returns the date of *Pentecost Sunday* (Whitsunday) in the given
Gregorian year. Pentecost is exactly 49 days after Western
Easter Sunday.

## Examples

    iex> Calendrical.Ecclesiastical.pentecost(2024)
    ~D[2024-05-19 Calendrical.Gregorian]

    iex> Calendrical.Ecclesiastical.pentecost(2025)
    ~D[2025-06-08 Calendrical.Gregorian]

---

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