# `Calendrical.Hebrew`

Implementation of the Hebrew (Jewish) calendar.

The Hebrew calendar is a *lunisolar* calendar with 12 months in an
ordinary year and 13 months in a leap year. The leap month
(*Adar I*) is inserted before *Adar* (which becomes *Adar II*) in
the 3rd, 6th, 8th, 11th, 14th, 17th and 19th years of each 19-year
*Metonic* cycle.

Year length varies between 353, 354, 355 (ordinary) and 383, 384,
385 (leap) days. The variability comes from two of the twelve
"fixed" months — *Heshvan* (month 2) and *Kislev* (month 3) — which
can each be either 29 or 30 days, plus the *molad of Tishri* delay
rules used to keep the calendar aligned with both the lunar and
solar cycles and to prevent certain holidays from falling on
prohibited days of the week.

## Month numbering

A Hebrew date's `month` is the month's **position in its year**, as it
is in every calendar: 1 (*Tishri*) to 12 (*Elul*) in an ordinary year,
and 1 to 13 in a leap year, whose leap month *Adar I* is month 6. So
`Date.new/4`, `months_in_year/1` and `days_in_month/2` agree, and the
months of any year are `1..months_in_year(year)`.

The months from *Adar I* on therefore sit one place later in a leap
year. The **traditional** numbering names the same month in every
year. It follows [RFC 7529](https://www.rfc-editor.org/rfc/rfc7529)
(and the `monthCode` of JavaScript's Temporal): *Tishri* is 1 and
*Elul* 12, 6 is *Adar* in an ordinary year and *Adar II* in a leap
year, and *Adar I* is `{5, :leap}`, the leap month that follows month
5. `ordinal_month_from_traditional/2` finds a traditional month's position in a year
and `lunar_month_of_year/2` goes the other way.

| Month | Ordinary year | Leap year | Traditional | Days |
|---|---|---|---|---|
| Tishri | 1 | 1 | 1 | 30 |
| Heshvan | 2 | 2 | 2 | 29 or 30 |
| Kislev | 3 | 3 | 3 | 30 or 29 |
| Tevet | 4 | 4 | 4 | 29 |
| Shevat | 5 | 5 | 5 | 30 |
| Adar I | — | 6 | `{5, :leap}` | 30 |
| Adar / Adar II | 6 | 7 | 6 | 29 |
| Nisan | 7 | 8 | 7 | 30 |
| Iyar | 8 | 9 | 8 | 29 |
| Sivan | 9 | 10 | 9 | 30 |
| Tamuz | 10 | 11 | 10 | 29 |
| Av | 11 | 12 | 11 | 30 |
| Elul | 12 | 13 | 12 | 29 |

*Heshvan* is long in 355- and 385-day years, and *Kislev* is short
in 353- and 383-day years.

Month names come from CLDR, whose Hebrew data numbers the months 1
(*Tishri*) to 13 (*Elul*) with 6 for *Adar I*, whether or not the
year has it. `month_of_year/3` returns that CLDR number, which is
how `Calendrical.localize/3` names a date's month, and
`Calendrical.month_names/2` lists the names by it.

Days are assumed to begin at midnight rather than at sunset.

## Reference

Algorithms are taken from Dershowitz & Reingold, *Calendrical
Calculations* (4th ed.), Chapter 8, "The Hebrew Calendar", which
numbers the months from *Nisan*; this module numbers them by their
position in the year, from *Tishri*.

# `day`

```elixir
@type day() :: 1..30
```

# `month`

```elixir
@type month() :: 1..13
```

# `traditional_month`

```elixir
@type traditional_month() :: 1..12 | {5, :leap}
```

A traditional Hebrew month (RFC 7529): `1..12`, or `{5, :leap}` for
*Adar I*.

# `year`

```elixir
@type year() :: pos_integer()
```

# `add`

Adds whole years, quarters or months to the fields of a naive
datetime, keeping its time of day: the `add/9` callback
[`CalendarInterval`](https://hexdocs.pm/calendar_interval) steps an
interval of a year or a month with. The date moves as `shift/6`
moves it, clamping the day into a shorter month.

### Arguments

* `year`, `month` and `day` are the date's fields in this calendar.

* `hour`, `minute`, `second` and `microsecond` are the time of day,
  returned unchanged.

* `precision` is `:year`, `:quarter` or `:month`.

* `step` is the number of years, quarters or months to add, which
  may be negative.

### Returns

* `{year, month, day, hour, minute, second, microsecond}`.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {year, month, day, 12, 30, 0, {0, 0}} =
    ...>   Calendrical.Hebrew.add(date.year, date.month, date.day, 12, 30, 0, {0, 0}, :month, 1)
    iex> {year, month, day} == Calendrical.Hebrew.shift(date.year, date.month, date.day, :months, 1, [])
    true

# `calendar_base`

Returns what this calendar's year is built of, `:month` or `:week`,
as its `info/0` states.

### Returns

* `:week` for a calendar whose year is built of weeks.

* `:month` otherwise.

### Examples

    iex> Calendrical.Hebrew.calendar_base() in [:month, :week]
    true

# `calendar_from_cldr_calendar_type`

Returns the calendar module whose CLDR calendar type is the one
given, whichever calendar is asked
(`Calendrical.calendar_from_cldr_calendar_type/1`).

### Arguments

* `calendar_type` is a CLDR calendar type as an atom or a string.

### Returns

* `{:ok, calendar_module}`, or

* `{:error, exception}` for a calendar type no calendar module has.

### Examples

    iex> Calendrical.Hebrew.calendar_from_cldr_calendar_type(:gregorian)
    {:ok, Calendrical.Gregorian}

    iex> {:error, %Localize.UnknownCalendarError{}} =
    ...>   Calendrical.Hebrew.calendar_from_cldr_calendar_type(:not_a_calendar)

# `cardinal_day`

Returns the day a date is written with: the day of its
`written_date/3`.

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* The day of the date's `written_date/3`, or

* `{:error, %Calendrical.InvalidDateError{}}` for a date the calendar
  does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {_year, _month, written_day} = Calendrical.Hebrew.written_date(date.year, date.month, date.day)
    iex> Calendrical.Hebrew.cardinal_day(date.year, date.month, date.day) == written_day
    true

# `cardinal_month`

Returns the CLDR month a month of the year names without a year
(`Calendrical.Month.cldr_month/2`).

### Arguments

* `month` is a month of this calendar.

### Returns

* The CLDR month the month is named in the year that holds
  1 January 2000, the month itself in the Hebrew calendar, whose
  names depend on the year, and the month itself where the
  reference year has no such month.

### Examples

    iex> {:ok, date} = Date.convert(~D[2000-01-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.cardinal_month(1) == Calendrical.Hebrew.cldr_month(date.year, 1)
    true

# `cardinal_year`

Returns the year a date is written with: the year of its
`written_date/3`.

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* The year of the date's `written_date/3`, or

* `{:error, %Calendrical.InvalidDateError{}}` for a date the calendar
  does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {written_year, _month, _day} = Calendrical.Hebrew.written_date(date.year, date.month, date.day)
    iex> Calendrical.Hebrew.cardinal_year(date.year, date.month, date.day) == written_year
    true

# `cldr_calendar_type`

Returns the CLDR calendar type whose data names this calendar's
months, days and quarters, as its `info/0` states.

### Returns

* A CLDR calendar type such as `:gregorian` or `:hebrew`.

### Examples

    iex> Calendrical.Hebrew.cldr_calendar_type() == Calendrical.Hebrew.info().cldr_calendar_type
    true

# `cldr_calendar_type`

Returns the CLDR calendar type whose data names a date's months and
days: the member in effect on the date in a composite calendar, and
this calendar's own otherwise (`Calendrical.Info.cldr_calendar_type/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* A CLDR calendar type.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> in_effect = Calendrical.Info.in_effect(Calendrical.Hebrew, date.year, date.month, date.day)
    iex> Calendrical.Hebrew.cldr_calendar_type(date.year, date.month, date.day) == in_effect.cldr_calendar_type()
    true

# `cldr_month`

Returns the CLDR month of a month of a year
(`Calendrical.Month.cldr_month/3`).

### Arguments

* `year` and `month` are a month of this calendar.

### Returns

* A CLDR month number, or `{month, :leap}` where the month's name
  has a leap form, or

* `{:error, exception}` for a month the year does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> cldr_month = Calendrical.Hebrew.cldr_month(date.year, date.month)
    iex> Calendrical.Hebrew.written_month_from_cldr_month(date.year, cldr_month) ==
    ...>   Calendrical.Hebrew.numeric_month(date.year, date.month, date.day)
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidMonthError{}} = Calendrical.Hebrew.cldr_month(date.year, 99)

# `cyclic_year`

Returns the cyclic year of a date (`Calendrical.Era.cyclic_year/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* The date's place in the sexagenary cycle, `1` to `60`, in an East
  Asian calendar, and its year in a calendar whose years run in no
  such cycle, or

* `{:error, %Calendrical.InvalidDateError{}}` for a year the calendar does not have,
  or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for no
  year.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> cyclic_year = Calendrical.Hebrew.cyclic_year(date.year, date.month, date.day)
    iex> cyclic_year in 1..60 or cyclic_year == date.year
    true

    iex> {:error, %Calendrical.MissingFieldsError{}} = Calendrical.Hebrew.cyclic_year(nil, 1, 1)

# `date_at`

```elixir
@spec date_at(DateTime.t(), Keyword.t()) :: {:ok, Date.t()} | {:error, Exception.t()}
```

Returns the Hebrew date in effect at a given instant, under a chosen day-start
convention.

The Jewish day begins at sunset — more precisely the date fully changes at
*nightfall* (tzeit hakochavim) — so in the evening the Hebrew date is already
the following day. This maps an absolute instant to the Hebrew date, choosing
the boundary with the `:day_start` option. Unlike the Islamic calendars, whose
boundary is a fixed canonical city, the Hebrew boundary is the **observer's**
local sunset, so a `:location` is taken (defaulting to Jerusalem).

For the plain civil-day mapping (the calendar's default), convert a date
directly with `Date.convert/2` instead.

### Arguments

* `datetime` is a `t:DateTime.t/0` — an absolute instant. Its own time zone
  fixes the instant; the day boundary is taken at `:location`.

### Options

* `:location` is a `t:Geo.PointZ.t/0` (or `t:Geo.Point.t/0`) giving the
  observer's location. The default is Jerusalem.

* `:day_start` selects the moment the Hebrew day begins:

  * `:midnight` (the default) — 00:00 local time, the ordinary civil-day
    mapping.

  * `:sunset` — true sunset (shkiah, upper-limb) at `:location`.

  * `:nightfall` — nightfall (tzeit hakochavim), when the sun reaches a chosen
    depression below the horizon. See `:nightfall_angle`.

* `:nightfall_angle` is the sun's depression below the horizon, in degrees,
  that defines nightfall for `day_start: :nightfall`. The default is `8.5`
  (the common "three small stars" tzeit).

### Returns

* `{:ok, date}` — a Hebrew `t:Date.t/0`.

* `{:error, %Calendrical.InvalidOptionValueError{}}` for an invalid
  `:day_start`, `:nightfall_angle` or `:location`.

* `{:error, %Calendrical.UnsupportedDateRangeError{}}` for a date outside
  the range the calendar or the installed JPL ephemeris covers.

* `{:error, %Calendrical.NoDuskError{}}` where the sun does not set, or
  nightfall does not occur, at the location on that day.

### Examples

    # Morning in Jerusalem: still the civil-day date.
    iex> {:ok, date} = Calendrical.Hebrew.date_at(~U[2025-03-01 06:00:00Z])
    iex> date.calendar
    Calendrical.Hebrew

# `date_from_cardinal_date`

Returns the date of this calendar that written figures name
(`date_from_written_date/3`), as fields.

### Arguments

* `year`, `month` and `day` are the figures a date is written with,
  as `written_date/3` returns them.

### Returns

* `{year, month, day}`, the date of this calendar, or

* `{:error, %Calendrical.InvalidDateError{}}` where the figures name no date.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {year, month, day} = Calendrical.Hebrew.written_date(date.year, date.month, date.day)
    iex> Calendrical.Hebrew.date_from_cardinal_date(year, month, day) == {date.year, date.month, date.day}
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.date_from_cardinal_date(date.year, 0, 1)

# `date_from_day_of_year`

Returns the date of a day of a year, counted from the year's first
day.

### Arguments

* `year` is a year of this calendar.

* `day_of_year` is the day of the year, counted from 1.

### Returns

* A `t:Date.t/0` of this calendar, or

* `{:error, %Calendrical.InvalidDateError{}}` for a day the year does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> day_of_year = Calendrical.Hebrew.day_of_year(date.year, date.month, date.day)
    iex> Calendrical.Hebrew.date_from_day_of_year(date.year, day_of_year) == date
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.date_from_day_of_year(date.year, 1000)

# `date_from_iso_days`

```elixir
@spec date_from_iso_days(integer()) :: {year(), month(), day()}
```

Returns a Hebrew `{year, month, day}` tuple for the given ISO day
number.

### Arguments

* `iso_days` is an integer count of days since the proleptic
  ISO epoch.

### Returns

* A three-tuple `{year, month, day}` in the Hebrew calendar.

### Examples

    iex> Calendrical.Hebrew.date_from_iso_days(739_500)
    {5784, 13, 3}

# `date_from_week_date`

Returns the date of a day of a week of a week-year
(`Calendrical.Week.date_from_week_date/4`).

### Arguments

* `week_year` is a week-year of this calendar.

* `week` is a week of the week-year.

* `day` is the day of the week, numbered from 1 for the day the
  calendar's weeks begin on.

### Returns

* A `t:Date.t/0` of this calendar, or

* `{:error, %Calendrical.InvalidDateError{}}` where the week has no such day.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {week_year, week, day} = Calendrical.Hebrew.week_date_from_date(date.year, date.month, date.day)
    iex> Calendrical.Hebrew.date_from_week_date(week_year, week, day) == date
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.date_from_week_date(date.year, 1, 8)

# `date_from_written_date`

Returns the date of this calendar that written figures name: the
inverse of `written_date/3`, the fields themselves where they are a
date.

### Arguments

* `year`, `month` and `day` are the figures a date is written with,
  as `written_date/3` returns them.

### Returns

* `{:ok, {year, month, day}}`, the date of this calendar, or

* `{:error, :invalid_date}` where the figures name no date.

The reason is an atom, not an exception: Localize's date parser reads
it, as `c:Calendrical.date_from_written_date/3` sets out.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {year, month, day} = Calendrical.Hebrew.written_date(date.year, date.month, date.day)
    iex> Calendrical.Hebrew.date_from_written_date(year, month, day) == {:ok, {date.year, date.month, date.day}}
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.date_from_written_date(date.year, 0, 1)
    {:error, :invalid_date}

# `date_to_iso_days`

```elixir
@spec date_to_iso_days(year(), month(), day()) :: integer()
```

Returns the number of ISO days for the given Hebrew `year`,
`month`, and `day`.

### Arguments

* `year` is any Hebrew year as an integer.

* `month` is the month's position in the year.

* `day` is a Hebrew day-of-month.

### Returns

* An integer count of days since the proleptic ISO epoch.

### Examples

    iex> Calendrical.Hebrew.date_to_iso_days(5785, 1, 1)
    739527

# `dates_in_gregorian_year`

Returns the dates of this calendar, earliest first, whose month and
day are those given and that fall in a Gregorian year.

### Arguments

* `gregorian_year` is the Gregorian year to search within.

* `month` and `day` are a month and a day of this calendar.

### Returns

* A list of zero, one or two `t:Date.t/0` of this calendar, earliest
  first, since this calendar's years and the Gregorian years drift.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> date in Calendrical.Hebrew.dates_in_gregorian_year(2024, date.month, date.day)
    true

# `day_numbers`

Returns the days a month of a year has, as runs of their numbers
(`Calendrical.Month.day_numbers/3`).

### Arguments

* `year` and `month` are a month of this calendar.

### Returns

* A list of ranges: one from 1 in every month of every calendar but
  a composite, whose month a change of calendar falls in has the
  days that are left, and `[]` for a month the year does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.day_numbers(date.year, date.month) ==
    ...>   [1..Calendrical.Hebrew.days_in_month(date.year, date.month)//1]
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.day_numbers(date.year, 99)
    []

# `day_of_era`

Returns the day of era and era of a date (`Calendrical.Era.day_of_era/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* `{day_of_era, era}`, where the day of the era counts from the
  era's first day, or

* `{:error, %Calendrical.InvalidDateError{}}` for a date the calendar does not have,
  or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for a
  missing field.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {day_of_era, era} = Calendrical.Hebrew.day_of_era(date.year, date.month, date.day)
    iex> {_year_of_era, year_era} = Calendrical.Hebrew.year_of_era(date.year, date.month, date.day)
    iex> day_of_era >= 1 and era == year_era
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.day_of_era(date.year, date.month, 0)

# `day_of_week`

Returns the day of the week of a date (`Calendrical.Week.day_of_week/5`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

* `starting_on` is `:default` for the day this calendar's weeks
  begin on, or the name of a weekday, `:monday` to `:sunday`.

### Returns

* `{day_of_week, 1, 7}`, the day numbered from the day the week
  begins on, or

* `{:error, %Calendrical.InvalidDateError{}}` for a date the calendar does not have,
  or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for a
  missing field.

### Examples

    # 1 June 2024 is a Saturday
    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.day_of_week(date.year, date.month, date.day, :monday)
    {6, 1, 7}

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.day_of_week(date.year, date.month, 0, :monday)

# `day_of_year`

Returns the day of the year of a date (`Calendrical.Period.day_of_year/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* The day of the year, counted from 1 for its first day, or

* `{:error, %Calendrical.InvalidDateError{}}` for a date the calendar does not have,
  or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for a
  missing field.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> first_day = Calendrical.Hebrew.year(date.year).first
    iex> Calendrical.Hebrew.day_of_year(date.year, date.month, date.day) == Date.diff(date, first_day) + 1
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.day_of_year(date.year, date.month, 0)

# `days_in_month`

Returns the number of days in a month without a year
(`Calendrical.Month.days_in_month/2`).

### Arguments

* `month` is a month of this calendar.

### Returns

* The number of days where the month has as many in every year, or

* `{:ambiguous, lengths}` where its length depends on the year, the
  lengths a range or, where they are not consecutive, a list, or

* `{:error, %Calendrical.NotDefinedError{}}` for a month the calendar has in no year, or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, where
  the month is `nil`.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {fewest, most} = Calendrical.Hebrew.days_in_month_bounds(date.month)
    iex> case Calendrical.Hebrew.days_in_month(date.month) do
    ...>   days when is_integer(days) -> fewest == days and most == days
    ...>   {:ambiguous, lengths} -> Enum.min(lengths) == fewest and Enum.max(lengths) == most
    ...> end
    true

    iex> {:error, %Calendrical.NotDefinedError{}} = Calendrical.Hebrew.days_in_month(99)

# `days_in_month`

```elixir
@spec days_in_month(Calendar.year(), Calendar.month()) ::
  Calendar.day() | {:error, Exception.t()}
@spec days_in_month(year(), month()) :: 29 | 30 | {:error, Exception.t()}
```

Returns the number of days in the given Hebrew `year` and `month`.

### Arguments

* `year` is any Hebrew year as an integer.

* `month` is the month's position in the year,
  `1..months_in_year(year)`.

### Returns

* The number of days in the month, 29 or 30, or

* `{:error, %Calendrical.InvalidMonthError{}}` for a month the year does
  not have, or

* `{:error, %Calendrical.MissingFieldsError{}}` where the year or the
  month is `nil`.

### Examples

    iex> Calendrical.Hebrew.days_in_month(5785, 1)
    30

    # Adar I, the 6th month of the leap year 5784
    iex> Calendrical.Hebrew.days_in_month(5784, 6)
    30

    # Adar, the 6th month of the ordinary year 5785
    iex> Calendrical.Hebrew.days_in_month(5785, 6)
    29

    # An ordinary year has no 13th month
    iex> Calendrical.Hebrew.days_in_month(5785, 13)
    {:error, %Calendrical.InvalidMonthError{calendar: Calendrical.Hebrew, year: 5785, month: 13}}

# `days_in_month_bounds`

Returns the fewest and the most days a month has in any year
(`Calendrical.Month.days_in_month_bounds/2`).

### Arguments

* `month` is a month of this calendar.

### Returns

* `{fewest, most}`, or

* `{:error, exception}` for a month the calendar has in no year.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {fewest, most} = Calendrical.Hebrew.days_in_month_bounds(date.month)
    iex> Calendrical.Hebrew.days_in_month(date.year, date.month) in fewest..most
    true

    iex> {:error, %Calendrical.InvalidMonthError{}} = Calendrical.Hebrew.days_in_month_bounds(99)

# `days_in_week`

Returns the number of days in a week.

### Returns

* `7`.

### Examples

    iex> Calendrical.Hebrew.days_in_week()
    7

# `days_in_year`

Returns the number of days in a year (`Calendrical.Period.days_in_year/2`).

### Arguments

* `year` is a year of this calendar.

### Returns

* The number of days, or

* `{:error, %Calendrical.InvalidDateError{}}` for a year the calendar does not have,
  or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for no
  year.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.days_in_year(date.year) == Enum.count(Calendrical.Hebrew.year(date.year))
    true

    iex> {:error, %Calendrical.MissingFieldsError{}} = Calendrical.Hebrew.days_in_year(nil)

# `diff`

```elixir
@spec diff({year(), month(), day()}, {year(), month(), day()}, atom()) ::
  integer() | {:error, Exception.t()}
```

Returns the whole number of `date_part`s from one `{year, month, day}`
to another, as `shift/6` adds them.

`date_part` can be `:years`, `:quarters`, `:months`, `:weeks` or
`:days`. The count is the largest number `shift/6`, clamping the day
into a shorter month, can add to the earlier date without passing the
later one; it is negative when `to` is before `from`. Months count a
leap year's Adar I, and come from the months elapsed before each year
(235 in every 19), so a span of any length costs the same.

### Arguments

* `from` is the starting `{year, month, day}`.

* `to` is the ending `{year, month, day}`.

* `date_part` is `:years`, `:quarters`, `:months`, `:weeks` or
  `:days`.

### Returns

* The whole number of `date_part`s from `from` to `to`, as an
  integer, or

* `{:error, %Calendrical.InvalidDateError{}}` for a `from` or `to` the
  calendar does not have, `{:error, %Calendrical.MissingFieldsError{}}`
  for one missing a field, or `{:error, %Calendrical.InvalidPartError{}}`
  for a `date_part` other than the five.

### Examples

    # 5784 is a leap year of thirteen months, 5785 an ordinary one
    iex> Calendrical.Hebrew.diff({5784, 1, 1}, {5785, 1, 1}, :months)
    13

    iex> Calendrical.Hebrew.diff({5784, 1, 1}, {5786, 1, 1}, :months)
    25

# `epoch`

Returns the epoch of this calendar: the ISO day number of
its first day.

### Returns

* The epoch as an integer number of days since the ISO epoch.

### Examples

    iex> Calendrical.Hebrew.epoch() |> is_integer()
    true

# `era_calendar_type`

Returns the CLDR calendar type that names this calendar's eras, as
its `info/0` states.

### Returns

* A CLDR calendar type such as `:gregorian` or `:japanese`.

### Examples

    iex> Calendrical.Hebrew.era_calendar_type() == Calendrical.Hebrew.info().era_calendar_type
    true

# `extended_year`

Returns the extended year of a date (`Calendrical.Era.extended_year/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* The year numbered without a gap at 0, so that in a calendar with
  no year 0 the year before 1 is 0, or

* `{:error, %Calendrical.InvalidDateError{}}` for a date the calendar does not have, or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for no
  year.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.extended_year(date.year, date.month, date.day) == date.year
    true

    iex> {:error, %Calendrical.MissingFieldsError{}} = Calendrical.Hebrew.extended_year(nil, 1, 1)

# `hebrew_new_year`

```elixir
@spec hebrew_new_year(year()) :: integer()
```

Returns the ISO day number of *1 Tishri* of the given Hebrew `year`
(the start of the Hebrew year).

### Arguments

* `year` is any Hebrew year as an integer.

### Returns

* An integer count of days since the proleptic ISO epoch.

### Examples

    iex> Calendrical.Hebrew.hebrew_new_year(5785)
    739527

# `info`

Returns the static facts about this calendar, as
`t:Calendrical.Info.t/0`.

### Returns

* A `t:Calendrical.Info.t/0` describing this calendar.

### Examples

    iex> Calendrical.Hebrew.info().calendar
    Calendrical.Hebrew

# `iso_week_of_year`

Returns the ISO 8601 week-year and week of the day a date names
(`Calendrical.Week.iso_week_of_year/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* `{week_year, week}` of ISO 8601, or

* `{:error, exception}` for a date the calendar does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.iso_week_of_year(date.year, date.month, date.day)
    {2024, 22}

# `leap_month`

```elixir
@spec leap_month(Calendar.year()) :: 6 | nil
```

Returns the position of the leap month, *Adar I*, in a Hebrew year.

### Arguments

* `year` is a Hebrew year as an integer.

### Returns

* `6`, the position of *Adar I*, in a leap year.

* `nil` in an ordinary year, or for anything but an integer year.

### Examples

    iex> Calendrical.Hebrew.leap_month(5784)
    6

    iex> Calendrical.Hebrew.leap_month(5785)
    nil

# `leap_year?`

```elixir
@spec leap_year?(year()) :: boolean()
```

Returns whether the given Hebrew `year` is a leap year (i.e. it
contains the embolismic month *Adar I*).

Leap years are determined by a 19-year Metonic cycle: years
3, 6, 8, 11, 14, 17, and 19 of each cycle are leap years.

### Arguments

* `year` is any Hebrew year as an integer.

### Returns

* `true` if the year contains 13 months; otherwise `false`.

### Examples

    iex> Calendrical.Hebrew.leap_year?(5784)
    true

    iex> Calendrical.Hebrew.leap_year?(5785)
    false

# `lunar_month_of_year`

Returns the traditional month at a position in a year
(`Calendrical.Month.traditional_month/3`), or an error for a place
the year does not have.

### Arguments

* `year` and `month` are a month of this calendar.

### Returns

* The month's traditional number, or `{month, :leap}` for a leap
  month, or

* `{:error, %Calendrical.InvalidMonthError{}}` for a month the year does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.lunar_month_of_year(date.year, date.month) ==
    ...>   Calendrical.Hebrew.traditional_month(date.year, date.month)
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidMonthError{}} = Calendrical.Hebrew.lunar_month_of_year(date.year, 99)

# `month`

Returns the days of a month of a year (`Calendrical.Period.month/3`).

### Arguments

* `year` and `month` are a month of this calendar.

### Returns

* A `t:Date.Range.t/0`, or

* `{:error, %Calendrical.InvalidDateError{}}` for a month the year does not have, or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for a
  missing year or month.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> date in Calendrical.Hebrew.month(date.year, date.month)
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.month(date.year, 99)

# `month_from_traditional`

Returns the position of a traditional month in a year
(`Calendrical.Month.month_from_traditional/3`).

### Arguments

* `year` is a year of this calendar.

* `traditional_month` is a month's traditional number, or
  `{month, :leap}` for a leap month.

### Returns

* The month's position in the year, or

* `{:error, exception}` where the year has no such month.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> traditional_month = Calendrical.Hebrew.traditional_month(date.year, date.month)
    iex> Calendrical.Hebrew.month_from_traditional(date.year, traditional_month) == date.month
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidMonthError{}} = Calendrical.Hebrew.month_from_traditional(date.year, 99)

# `month_numbers`

Returns the months a year has, as runs of their numbers
(`Calendrical.Month.month_numbers/2`).

### Arguments

* `year` is a year of this calendar.

### Returns

* A list of ranges: one from 1 in every year of every calendar but a
  composite, whose year a change of calendar falls in has the months
  that are left, and `[]` for a year the calendar does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.month_numbers(date.year) == [1..Calendrical.Hebrew.months_in_year(date.year)//1]
    true

# `month_of_year`

Returns the CLDR month of a month of a year: the index of its name
in this calendar's CLDR data, with `{month, :leap}` where the name
has a leap form (`Calendrical.Month.cldr_month/3`).

### Arguments

* `year`, `month` and `day` are a date of this calendar. The year
  and the day may be `nil`: a month's name needs only the month.

### Returns

* A CLDR month number, or `{month, :leap}`, or

* `{:error, %Calendrical.InvalidDateError{}}` for a day the month does not have, or

* `{:error, exception}` for a month the year does not have, or a
  `Calendrical.MissingFieldsError` where the month is `nil`.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.month_of_year(date.year, date.month, date.day) == Calendrical.Hebrew.cldr_month(date.year, date.month)
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.month_of_year(date.year, date.month, 0)

# `months_in_leap_year`

Returns the number of months in a leap year: the most months a year
of this calendar has.

### Returns

* A positive integer.

### Examples

    iex> Calendrical.Hebrew.months_in_leap_year() >= Calendrical.Hebrew.months_in_ordinary_year()
    true

# `months_in_ordinary_year`

Returns the number of months in an ordinary year: the fewest months
a year of this calendar has.

### Returns

* A positive integer.

### Examples

    iex> Calendrical.Hebrew.months_in_ordinary_year() <= Calendrical.Hebrew.months_in_leap_year()
    true

# `months_in_year`

Returns the number of months in a year without a year: the count
where every year has as many, `{:ambiguous, range}` where a leap
year has more, and `{:error, %Calendrical.NotDefinedError{}}` for a composite calendar
(`Calendrical.Info.months_in_year/1`).

### Returns

* The number of months where every year has as many, or

* `{:ambiguous, fewest..most}` where a leap year has more, or

* `{:error, %Calendrical.NotDefinedError{}}` for a composite calendar, whose bounds
  `months_in_year_bounds/0` gives.

### Examples

    iex> case Calendrical.Hebrew.months_in_year() do
    ...>   months when is_integer(months) -> months == Calendrical.Hebrew.months_in_leap_year()
    ...>   {:ambiguous, fewest..most//1} -> {fewest, most} == Calendrical.Hebrew.info().months_in_year
    ...>   {:error, %Calendrical.NotDefinedError{}} -> is_list(Calendrical.Hebrew.info().members)
    ...> end
    true

# `months_in_year`

```elixir
@spec months_in_year(year()) :: 12..13 | {:error, Exception.t()}
```

Returns the number of months in the given Hebrew `year` (12 in an
ordinary year, 13 in a leap year).

### Arguments

* `year` is any Hebrew year as an integer.

### Returns

* `12` for an ordinary year or `13` for a leap year, or

* `{:error, %Calendrical.MissingFieldsError{}}` where `year` is `nil`, or

* `{:error, %Calendrical.InvalidDateError{}}` where `year` is no integer.

### Examples

    iex> Calendrical.Hebrew.months_in_year(5785)
    12

    iex> Calendrical.Hebrew.months_in_year(5784)
    13

# `months_in_year_bounds`

Returns the fewest and the most months a year has
(`Calendrical.Month.months_in_year_bounds/1`).

### Returns

* `{fewest, most}`, which in a composite calendar counts the months
  left in a year a change of calendar falls in.

### Examples

    iex> {fewest, most} = Calendrical.Hebrew.months_in_year_bounds()
    iex> fewest <= Calendrical.Hebrew.months_in_ordinary_year() and
    ...>   most >= Calendrical.Hebrew.months_in_leap_year()
    true

# `naive_datetime_from_iso_days`

Converts ISO days and a day fraction to a naive datetime of this
calendar, as `c:Calendar.naive_datetime_from_iso_days/1` asks.

### Arguments

* `iso_days` is `{days, {parts_in_day, parts_per_day}}`, a day and a
  fraction of it.

### Returns

* `{year, month, day, hour, minute, second, microsecond}` of this
  calendar.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {year, month, day, 12, 0, 0, {0, 6}} =
    ...>   Calendrical.Hebrew.naive_datetime_from_iso_days({739403, {43200000000, 86400000000}})
    iex> {year, month, day} == {date.year, date.month, date.day}
    true

# `naive_datetime_to_iso_days`

Converts a naive datetime of this calendar to ISO days and a day
fraction, as `c:Calendar.naive_datetime_to_iso_days/7` asks.

### Arguments

* `year`, `month` and `day` are a date of this calendar.

* `hour`, `minute`, `second` and `microsecond` are a time of day,
  the microsecond as `{microseconds, precision}`.

### Returns

* `{iso_days, {parts_in_day, parts_per_day}}`.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.naive_datetime_to_iso_days(date.year, date.month, date.day, 12, 0, 0, {0, 6})
    {739403, {43200000000, 86400000000}}

# `named_month`

Returns the days of a named month in a year
(`Calendrical.Month.named_month/3`).

### Arguments

* `year` is a year of this calendar.

* `named_month` is the CLDR month that names the month.

### Returns

* A list of `t:Date.Range.t/0`, one for each counted month that
  carries the name, earliest first, and `[]` where none does.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> cldr_month = Calendrical.Hebrew.cldr_month(date.year, date.month)
    iex> Calendrical.Hebrew.named_month(date.year, cldr_month) |> Enum.any?(&(date in &1))
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.named_month(date.year, 99)
    []

# `numeric_month`

Returns the number a date's month is written with in figures: the
month of its `written_date/3`.

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* The month of the date's `written_date/3`: a month number, or
  `{month, :leap}` for a leap month of a lunisolar calendar, or

* `{:error, %Calendrical.InvalidDateError{}}` for a date the calendar
  does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {_year, written_month, _day} = Calendrical.Hebrew.written_date(date.year, date.month, date.day)
    iex> Calendrical.Hebrew.numeric_month(date.year, date.month, date.day) == written_month
    true

# `ordinal_month_from_traditional`

Returns the position in a year of a traditional month
(`Calendrical.Month.month_from_traditional/3`), as `{:ok, month}`.

### Arguments

* `year` is a year of this calendar.

* `traditional_month` is a month's traditional number, or
  `{month, :leap}` for a leap month.

### Returns

* `{:ok, month}`, the month's position in the year, or

* `{:error, %Calendrical.InvalidMonthError{}}` for a month or a leap
  month the year does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> traditional_month = Calendrical.Hebrew.traditional_month(date.year, date.month)
    iex> Calendrical.Hebrew.ordinal_month_from_traditional(date.year, traditional_month) == {:ok, date.month}
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidMonthError{}} = Calendrical.Hebrew.ordinal_month_from_traditional(date.year, 99)

# `parse_date`

Parses a date written in this calendar's own notation.

### Arguments

* `string` is a date written `YYYY-MM-DD`, with a leading `-` for a
  year before 1, or, in a calendar of weeks, `YYYY-Www-D`.

### Returns

* `{:ok, {year, month, day}}`, or

* `{:error, :invalid_format}` where the text is not in that form or
  its fields are not digits, or

* `{:error, :invalid_date}` where the text names no date of this
  calendar.

The reason is an atom, not an exception, because `c:Calendar.parse_date/1`
requires one: `Date.from_iso8601/2` reads it.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.parse_date(Date.to_string(date)) == {:ok, {date.year, date.month, date.day}}
    true

    iex> Calendrical.Hebrew.parse_date("not a date")
    {:error, :invalid_format}

# `parse_naive_datetime`

Parses a naive datetime written in this calendar's own notation.

### Arguments

* `string` is a date as `parse_date/1` reads it, then `T` or a
  space and a time of day.

### Returns

* `{:ok, {year, month, day, hour, minute, second, microsecond}}`, or

* `{:error, reason}`, such as `:invalid_format` or `:invalid_date`,
  where the text is no such datetime.

The reason is an atom, not an exception, because
`c:Calendar.parse_naive_datetime/1` requires one:
`NaiveDateTime.from_iso8601/2` reads it.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.parse_naive_datetime(Date.to_string(date) <> "T12:00:00") ==
    ...>   {:ok, {date.year, date.month, date.day, 12, 0, 0, {0, 0}}}
    true

    iex> Calendrical.Hebrew.parse_naive_datetime("2024-06-01")
    {:error, :invalid_format}

# `parse_utc_datetime`

Parses a UTC datetime written in this calendar's own notation.

### Arguments

* `string` is a date as `parse_date/1` reads it, then `T` or a
  space, a time of day and an offset from UTC, `Z` or `±HH:MM`.

### Returns

* `{:ok, {year, month, day, hour, minute, second, microsecond}, offset}`,
  the datetime in UTC and the offset in seconds it was written with,
  or

* `{:error, reason}`, such as `:invalid_format`, `:invalid_date` or
  `:missing_offset`, where the text is no such datetime.

The reason is an atom, not an exception, because
`c:Calendar.parse_utc_datetime/1` requires one:
`DateTime.from_iso8601/2` reads it.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.parse_utc_datetime(Date.to_string(date) <> "T12:00:00Z") ==
    ...>   {:ok, {date.year, date.month, date.day, 12, 0, 0, {0, 0}}, 0}
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.parse_utc_datetime(Date.to_string(date) <> "T12:00:00")
    {:error, :missing_offset}

# `parsing_calendar`

Returns the calendar a date written for this calendar is parsed in,
as its `info/0` states.

### Returns

* A calendar module.

### Examples

    iex> Calendrical.Hebrew.parsing_calendar() == Calendrical.Hebrew.info().parsing_calendar
    true

# `parsing_calendars`

Returns the calendars a date written for this calendar may be
written in: the members of a composite calendar, and this calendar
alone otherwise (`Calendrical.Info.parsing_calendars/1`).

### Returns

* A non-empty list of calendar modules, the members of a composite
  calendar in the order they take effect.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> in_effect = Calendrical.Info.in_effect(Calendrical.Hebrew, date.year, date.month, date.day)
    iex> in_effect in Calendrical.Hebrew.parsing_calendars()
    true

# `periods_in_year`

Returns the number of periods in a year: its months.

### Arguments

* `year` is a year of this calendar.

### Returns

* The number of months in the year, as `months_in_year/1` returns
  it.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.periods_in_year(date.year) == Calendrical.Hebrew.months_in_year(date.year)
    true

# `quadrimester`

Returns the days of a quadrimester of a year
(`Calendrical.Period.quadrimester/3`).

### Arguments

* `year` is a year of this calendar.

* `quadrimester` is the quadrimester, `1` to `3`.

### Returns

* A `t:Date.Range.t/0`, or

* `{:error, %Calendrical.InvalidDateError{}}` for a quadrimester or a year the
  calendar does not have, or

* `{:error, %Calendrical.MissingFieldsError{}}` where the year or the
  quadrimester is `nil`.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.quadrimester(date.year, 1).first == Calendrical.Hebrew.year(date.year).first
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.quadrimester(date.year, 4)

# `quarter`

Returns the days of a quarter of a year (`Calendrical.Period.quarter/3`).

### Arguments

* `year` is a year of this calendar.

* `quarter` is the quarter, `1` to `4`.

### Returns

* A `t:Date.Range.t/0`, or

* `{:error, %Calendrical.InvalidDateError{}}` for a quarter or a year the calendar
  does not have, or

* `{:error, %Calendrical.MissingFieldsError{}}` where the year or the
  quarter is `nil`.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> quarter = Calendrical.Hebrew.quarter_of_year(date.year, date.month, date.day)
    iex> date in Calendrical.Hebrew.quarter(date.year, quarter)
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.quarter(date.year, 5)

# `quarter_of_year`

Returns the quarter of the year a date falls in
(`Calendrical.Period.quarter_of_year/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* The quarter, `1` to `4`, or

* `{:error, %Calendrical.InvalidDateError{}}` for a date the calendar does not have,
  or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for a
  missing year or month.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.quarter_of_year(date.year, date.month, date.day) in 1..4
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.quarter_of_year(date.year, date.month, 0)

# `related_gregorian_year`

Returns the related Gregorian year of a date
(`Calendrical.Era.related_gregorian_year/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* The Gregorian year the date's calendar year begins in, or

* `{:error, %Calendrical.InvalidDateError{}}` for a year the calendar does not have,
  or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for no
  year.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:ok, first_day} = Date.convert(Calendrical.Hebrew.year(date.year).first, Calendrical.Gregorian)
    iex> Calendrical.Hebrew.related_gregorian_year(date.year, date.month, date.day) == first_day.year
    true

# `semester`

Returns the days of a semester of a year (`Calendrical.Period.semester/3`).

### Arguments

* `year` is a year of this calendar.

* `semester` is the semester, `1` or `2`.

### Returns

* A `t:Date.Range.t/0`, or

* `{:error, %Calendrical.InvalidDateError{}}` for a semester or a year the calendar
  does not have, or

* `{:error, %Calendrical.MissingFieldsError{}}` where the year or the
  semester is `nil`.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.semester(date.year, 1).first == Calendrical.Hebrew.year(date.year).first
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.semester(date.year, 3)

# `shift`

Returns the date a number of years, quarters, months, weeks or days
on from a date of this calendar, by position, with the traditional
month kept across years and a day the resulting month lacks clamped
to its last day unless `clamp: false` (`Calendrical.Shift.shift/7`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

* `date_part` is one of `:years`, `:quarters`, `:months`, `:weeks`
  or `:days`.

* `increment` is the number of units, which may be negative.

* `options` is a keyword list of options.

### Options

* `:clamp` is whether a day the resulting month lacks becomes its
  last day. The default is `true`.

### Returns

* `{year, month, day}` of this calendar, or

* `{:error, %Calendrical.InvalidDateError{}}` where `year`, `month` and
  `day` are no date of this calendar, or

* `{:error, %Calendrical.MissingFieldsError{}}` where a field is `nil`.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.shift(date.year, date.month, date.day, :days, 0)
    {date.year, date.month, date.day}

# `shift_date`

Shifts a date by a duration: its years and months together, as
`shift/6` adds months, and then its weeks and days.

### Arguments

* `year`, `month` and `day` are a date of this calendar.

* `duration` is a `t:Duration.t/0`.

### Returns

* `{year, month, day}` of this calendar.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {year, month, day} = Calendrical.Hebrew.shift_date(date.year, date.month, date.day, Duration.new!(day: 7))
    iex> Date.new!(year, month, day, Calendrical.Hebrew) == Date.add(date, 7)
    true

# `shift_naive_datetime`

Shifts a naive datetime by a duration: its date as `shift_date/4`
shifts it, and its time as `Calendar.ISO` does.

### Arguments

* `year`, `month` and `day` are a date of this calendar.

* `hour`, `minute`, `second` and `microsecond` are a time of day,
  the microsecond as `{microseconds, precision}`.

* `duration` is a `t:Duration.t/0`.

### Returns

* `{year, month, day, hour, minute, second, microsecond}` of this
  calendar.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> next_day = Date.add(date, 1)
    iex> Calendrical.Hebrew.shift_naive_datetime(date.year, date.month, date.day, 23, 0, 0, {0, 0}, Duration.new!(hour: 2)) ==
    ...>   {next_day.year, next_day.month, next_day.day, 1, 0, 0, {0, 0}}
    true

# `shift_time`

Shifts a time by a duration, as `Calendar.ISO` does.

### Arguments

* `hour`, `minute`, `second` and `microsecond` are a time of day,
  the microsecond as `{microseconds, precision}`.

* `duration` is a `t:Duration.t/0` of time units.

### Returns

* `{hour, minute, second, microsecond}`, wrapped around midnight.

### Examples

    iex> Calendrical.Hebrew.shift_time(23, 0, 0, {0, 0}, Duration.new!(hour: 2))
    {1, 0, 0, {0, 0}}

# `solar_term`

Returns the day of a solar term of a Gregorian year, reckoned at the
place this calendar's `info/0` names, or at the Chinese calendar's
meridian, the traditional reference, where it names none.

### Arguments

* `index` is the solar term's number, `1` (lichun, 315° of solar
  longitude) to `24`, every 15° on.

* `gregorian_year` is a Gregorian year.

### Returns

* `{:ok, date}`, a `t:Date.t/0` in `Calendrical.Gregorian`, or

* `{:error, %Calendrical.InvalidSolarTermError{}}` where `index` is not
  `1` to `24`.

### Examples

    # Qingming, the fifth solar term
    iex> Calendrical.Hebrew.solar_term(5, 2025)
    {:ok, ~D[2025-04-04 Calendrical.Gregorian]}

    iex> Calendrical.Hebrew.solar_term(25, 2025)
    {:error, %Calendrical.InvalidSolarTermError{index: 25}}

# `traditional_leap_month`

Returns the traditional number of the month a year's leap month
follows, or `nil` (`Calendrical.Month.traditional_leap_month/2`).

### Arguments

* `year` is a year of this calendar.

### Returns

* The traditional number of the month the leap month follows, or

* `nil` where the year has no leap month.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> is_nil(Calendrical.Hebrew.traditional_leap_month(date.year)) ==
    ...>   is_nil(Calendrical.Hebrew.leap_month(date.year))
    true

# `traditional_month`

Returns a month of a year as this calendar names it
(`Calendrical.Month.traditional_month/3`).

### Arguments

* `year` and `month` are a month of this calendar.

### Returns

* The month's traditional number, or `{month, :leap}` for a leap
  month, or

* `{:error, exception}` for a month the year does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.traditional_month(date.year, date.month) ==
    ...>   Enum.at(Calendrical.Hebrew.traditional_months(date.year), date.month - 1)
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidMonthError{}} = Calendrical.Hebrew.traditional_month(date.year, 99)

# `traditional_months`

Returns a year's months in order, named traditionally
(`Calendrical.Month.traditional_months/2`).

### Arguments

* `year` is a year of this calendar.

### Returns

* A list of traditional months, the nth naming the year's nth month,
  with `{month, :leap}` for a leap month, and `[]` for a year the
  calendar does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> length(Calendrical.Hebrew.traditional_months(date.year)) ==
    ...>   Calendrical.Hebrew.months_in_year(date.year)
    true

# `valid_date?`

```elixir
@spec valid_date?(year(), month(), day()) :: boolean()
```

Returns whether the given `year`, `month`, and `day` form a valid
Hebrew date.

An ordinary year has 12 months and a leap year 13.

### Arguments

* `year` is any Hebrew year as an integer.

* `month` is the month's position in the year.

* `day` is a Hebrew day-of-month.

### Returns

* `true` if the date is valid; otherwise `false`.

### Examples

    iex> Calendrical.Hebrew.valid_date?(5785, 1, 30)
    true

    # Elul, the 13th month of the leap year 5784
    iex> Calendrical.Hebrew.valid_date?(5784, 13, 1)
    true

    # An ordinary year has no 13th month
    iex> Calendrical.Hebrew.valid_date?(5785, 13, 1)
    false

# `week`

Returns the seven days of a week of a year (`Calendrical.Week.week/3`).

### Arguments

* `year` is a year of this calendar.

* `week` is a week of the year.

### Returns

* A `t:Date.Range.t/0` of the week's seven days, which may begin in
  the year before or end in the year after, or

* `{:error, %Calendrical.InvalidDateError{}}` for a week the year does not have, or

* `{:error, %Calendrical.MissingFieldsError{}}` where the year or the
  week is `nil`.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {week_year, week} = Calendrical.Hebrew.week_of_year(date.year, date.month, date.day)
    iex> days = Calendrical.Hebrew.week(week_year, week)
    iex> {Enum.count(days), date in days}
    {7, true}

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.week(date.year, 0)

# `week_date_from_date`

Returns the week-year, the week and the day of the week of a date
(`Calendrical.Week.week_date_from_date/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* `{week_year, week, day_of_week}`, the day numbered from the day
  the calendar's weeks begin on, or

* `{:error, %Calendrical.InvalidDateError{}}` for a date the calendar does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {week_year, week, day} = Calendrical.Hebrew.week_date_from_date(date.year, date.month, date.day)
    iex> {week_year, week} == Calendrical.Hebrew.week_of_year(date.year, date.month, date.day) and day in 1..7
    true

# `week_of_month`

Returns the month and the week of the month a date is in
(`Calendrical.Week.week_of_month/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* `{month, week}`, where the month is the one before or after where
  the date falls in that month's last or first week, or

* `{:error, exception}` for a date the calendar does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {month, week} = Calendrical.Hebrew.week_of_month(date.year, date.month, date.day)
    iex> month in (date.month - 1)..(date.month + 1) and week >= 1
    true

# `week_of_year`

Returns the week-year and the week of the year a date is in
(`Calendrical.Week.week_of_year/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* `{week_year, week}`, where the week-year is the year before or
  after where the date falls in that year's last or first week, or

* `{:error, exception}` for a date the calendar does not have: a
  `Calendrical.MissingFieldsError` for a date missing a field, and a
  `Calendrical.InvalidDateError` otherwise.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {week_year, week} = Calendrical.Hebrew.week_of_year(date.year, date.month, date.day)
    iex> date in Calendrical.Hebrew.week(week_year, week)
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.week_of_year(date.year, date.month, 0)

# `weeks_in_week_year`

Returns the number of weeks in a week-year
(`Calendrical.Week.weeks_in_week_year/2`).

### Arguments

* `week_year` is a week-year of this calendar.

### Returns

* The number of weeks, or

* `{:error, %Calendrical.InvalidDateError{}}` for a year the calendar does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {week_year, week, _day} = Calendrical.Hebrew.week_date_from_date(date.year, date.month, date.day)
    iex> week <= Calendrical.Hebrew.weeks_in_week_year(week_year)
    true

# `weeks_in_year`

Returns the number of weeks in a year (`Calendrical.Week.weeks_in_year/2`).

### Arguments

* `year` is a year of this calendar.

### Returns

* The number of weeks, or

* `{:error, exception}` for a year the calendar does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {week_year, week} = Calendrical.Hebrew.week_of_year(date.year, date.month, date.day)
    iex> week <= Calendrical.Hebrew.weeks_in_year(week_year)
    true

# `weeks_of_month`

Returns the weeks of a month of a year in order
(`Calendrical.Week.weeks_of_month/3`).

### Arguments

* `year` and `month` are a month of this calendar.

### Returns

* A list of `t:Date.Range.t/0`, one for each week `week_of_month/3`
  names for the month, the first of which may begin in the month
  before and the last run into the month after, or

* `{:error, exception}` for a month the year does not have.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.weeks_of_month(date.year, date.month) |> Enum.all?(&(Enum.count(&1) == 7))
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidMonthError{}} = Calendrical.Hebrew.weeks_of_month(date.year, 99)

# `written_date`

Returns the figures a date is written with: its own fields, in a
calendar whose dates are written as its own.

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* `{year, month, day}` as the date is written, where the month of a
  lunisolar calendar is its traditional number, `{month, :leap}`
  for a leap month.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {year, month, day} = Calendrical.Hebrew.written_date(date.year, date.month, date.day)
    iex> Calendrical.Hebrew.date_from_written_date(year, month, day) == {:ok, {date.year, date.month, date.day}}
    true

# `written_month_from_cldr_month`

Returns the month a CLDR month is written with in a year
(`Calendrical.Month.written_month_from_cldr_month/3`).

### Arguments

* `year` is a year of this calendar.

* `cldr_month` is a CLDR month number, or `{month, :leap}`.

### Returns

* The month as `written_date/3` writes it, or

* `{:error, :invalid_month}` where the year has no month of that
  name. The reason is an atom, not an exception: Localize's date parser
  reads it, where `Calendrical.Month.written_month_from_cldr_month/3`
  answers with an exception.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {_year, written_month, _day} = Calendrical.Hebrew.written_date(date.year, date.month, date.day)
    iex> cldr_month = Calendrical.Hebrew.cldr_month(date.year, date.month)
    iex> Calendrical.Hebrew.written_month_from_cldr_month(date.year, cldr_month) == written_month
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.written_month_from_cldr_month(date.year, 99)
    {:error, :invalid_month}

# `year`

Returns the days of a year (`Calendrical.Period.year/2`).

### Arguments

* `year` is a year of this calendar.

### Returns

* A `t:Date.Range.t/0`, or

* `{:error, %Calendrical.InvalidDateError{}}` for a year the calendar does not have,
  or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for
  no year.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> date in Calendrical.Hebrew.year(date.year)
    true

    iex> {:error, %Calendrical.MissingFieldsError{}} = Calendrical.Hebrew.year(nil)

# `year_of_era`

Returns the year of era and era of a year (`Calendrical.Era.year_of_era/2`).

### Arguments

* `year` is a year of this calendar.

### Returns

* `{year_of_era, era}`, the era in effect on the year's first day,
  or

* `{:error, %Calendrical.InvalidDateError{}}` for a year the calendar does not have,
  or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for no
  year.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> Calendrical.Hebrew.year_of_era(date.year) ==
    ...>   Calendrical.Hebrew.year_of_era(date.year, date.month, date.day)
    true

# `year_of_era`

Returns the year of era and era of a date (`Calendrical.Era.year_of_era/4`).

### Arguments

* `year`, `month` and `day` are a date of this calendar.

### Returns

* `{year_of_era, era}`, or

* `{:error, %Calendrical.InvalidDateError{}}` for a date the calendar does not have,
  or

* `{:error, exception}`, a `Calendrical.MissingFieldsError`, for no
  year.

### Examples

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {year_of_era, era} = Calendrical.Hebrew.year_of_era(date.year, date.month, date.day)
    iex> year_of_era >= 1 and is_integer(era)
    true

    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> {:error, %Calendrical.InvalidDateError{}} = Calendrical.Hebrew.year_of_era(date.year, 99, 1)

# `years_in_cycle`

Returns the number of years after which this calendar's years
repeat, as its `info/0` states, or `{:error, %Calendrical.NotDefinedError{}}`.

### Returns

* The number of years in the cycle, or

* `{:error, %Calendrical.NotDefinedError{}}` where the calendar states none.

### Examples

    # A year has as many days as the year one cycle later
    iex> {:ok, date} = Date.convert(~D[2024-06-01], Calendrical.Hebrew)
    iex> case Calendrical.Hebrew.years_in_cycle() do
    ...>   {:error, %Calendrical.NotDefinedError{}} -> true
    ...>   years -> Calendrical.Hebrew.days_in_year(date.year) == Calendrical.Hebrew.days_in_year(date.year + years)
    ...> end
    true

---

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