# `Calendrical`

Calendar functions for calendars compatible with
Elixir's `Calendar` behaviour.

`Calendrical` supports the creation of calendars
that are variations on the proleptic Calendrical.Gregorian
calendar. It also adds additional functions, defined
by the `Calendrical` behaviour, to support these
derived calendars.

The common purpose of these derived calendars is
to support the creation and use of financial year
calendars that are commonly used in business.

There are two general types of calendars supported:

* `month` calendars that mirror the monthly structure
  of the proleptic `Calendrical.Gregorian` calendar but which are
  deemed to start the year in a month other than January.

* `week` calendars that are defined to have a 52 week
  structure (53 weeks in a long year). These calendars
  can be configured to start or end on the first, last or
  nearest day to the beginning or end of a `Calendrical.Gregorian`
  month.  The main intent behind this structure is to
  have each year start and end on the same day of the
  week with a consistent 13-week quarterly structure than
  enables a more straight forware comparison with
  same-period-last-year financial performance.

## The Calendrical behaviour

A Calendrical calendar implements Elixir's `Calendar` behaviour and
the eight callbacks of this module beside it, which are its kernel:

* `c:info/0` is the static facts about the calendar, as
  `t:Calendrical.Info.t/0`: the CLDR calendars that name its months
  and its eras, its epoch, whether it has a year 0, the fewest and the
  most months its years have, the rule its own weeks follow, the
  cycles its years run in, and, for a composite, its members.

* `c:date_to_iso_days/3` and `c:date_from_iso_days/1` are the spine
  every conversion runs through.

* `c:leap_month/1` is the position of a year's leap month, or `nil`.

* `c:written_date/3` is the figures a date is written with, and
  `c:date_from_written_date/3` the date those figures name: a fiscal
  date is written as the Gregorian date it is, a Hebrew date with its
  month's place in the year as ICU writes it.

* `c:shift/6` and `c:diff/3` are the calendar's arithmetic, under one
  clamping contract.

Every other answer, from the day of the week to the days of a quarter,
is derived from the kernel and from the six primitive `Calendar`
callbacks by `Calendrical.Month`, `Calendrical.Week`,
`Calendrical.Period` and `Calendrical.Era`, and every calendar carries
those answers as functions of its own module, so a consumer asks any
calendar any question and never whether it can. The makers
(`Calendrical.Calendar`, `Calendrical.Calendar.Shifted`,
`Calendrical.Calendar.Weeks`, `Calendrical.Calendar.Lunisolar` and
`Calendrical.Composite`) implement the kernel from their options.

# `additional_calendars`

```elixir
@type additional_calendars() :: %{
  iso8601: Calendrical.ISO,
  iso_week: Calendrical.ISOWeek,
  julian: Calendrical.Julian,
  julian_dec25: Calendrical.Julian.Dec25,
  julian_jan1: Calendrical.Julian.Jan1,
  julian_march1: Calendrical.Julian.March1,
  julian_march25: Calendrical.Julian.March25,
  julian_sept1: Calendrical.Julian.Sept1,
  lunar_japanese: Calendrical.LunarJapanese,
  nrf: Calendrical.NRF,
  reform_england: Calendrical.Reform.England,
  reform_japan: Calendrical.Reform.Japan,
  reform_sweden: Calendrical.Reform.Sweden,
  reform_sweden_transitional: Calendrical.Reform.Sweden.Transitional,
  vietnamese: Calendrical.Vietnamese
}
```

The calendars `additional_calendars/0` returns, by IXDTF identifier.

# `any_date_time`

```elixir
@type any_date_time() :: date() | time() | naive_date_time() | date_time()
```

Super type of any date or time.

# `calendar`

```elixir
@type calendar() :: module() | nil
```

Specifies the type of a calendar.

A calendar is a module that implements
the `Calendar` and `Calendrical`
behaviours. Calendar functions will
default to `Calendrical.Gregorian`
in most cases.

# `calendar_type`

```elixir
@type calendar_type() :: :month | :week
```

Specifies the type of a calendar

# `date`

```elixir
@type date() :: %{
  optional(:year) =&gt; year(),
  optional(:month) =&gt; month(),
  optional(:day) =&gt; day(),
  optional(:calendar) =&gt; calendar(),
  optional(any()) =&gt; any()
}
```

All date fields are optional however many functions
will require the presence of one or more - and
often all - fields be present.

# `date_error`

```elixir
@type date_error() :: {:error, Exception.t()}
```

The error a question about a date returns: `:invalid_date` for a date the calendar does not have, or a `Calendrical.MissingFieldsError` for a date missing a field the question needs.

# `date_time`

```elixir
@type date_time() :: %{
  optional(:calendar) =&gt; calendar(),
  optional(:day) =&gt; day(),
  optional(:hour) =&gt; Calendar.hour(),
  optional(:microsecond) =&gt; Calendar.microsecond(),
  optional(:minute) =&gt; Calendar.minute(),
  optional(:month) =&gt; month(),
  optional(:second) =&gt; Calendar.second(),
  optional(:std_offset) =&gt; Calendar.std_offset(),
  optional(:time_zone) =&gt; Calendar.time_zone(),
  optional(:utc_offset) =&gt; Calendar.utc_offset(),
  optional(:year) =&gt; year(),
  optional(:zone_abbr) =&gt; Calendar.zone_abbr(),
  optional(any()) =&gt; any()
}
```

All date time fields are optional however many functions
will require the presence of one or more - and
often all - fields be present.

# `day`

```elixir
@type day() :: Calendar.day() | nil
```

Specifies the day of a date as either
a positive integer or nil.

# `day_of_week`

```elixir
@type day_of_week() :: 1..7
```

Specifies the days of the week as integers.

Days of the week are encoded as the integers `1` through
`7` with `1` representing Monday and 7 representing Sunday.

Note that a calendar can be configured to start
on any day of the week. `day_of_week` is only a
way of encoding the days as an integer.

# `day_of_week_to_binary`

```elixir
@type day_of_week_to_binary() :: {day_of_week(), String.t()}
```

A mapping of a day of the week ordinal to the
localized string of the name of that day.

# `era`

```elixir
@type era() :: non_neg_integer() | nil
```

Specifies the year of a date as either
a positive integer or nil.

# `interval_relation`

```elixir
@type interval_relation() ::
  :precedes
  | :preceded_by
  | :meets
  | :met_by
  | :overlaps
  | :overlapped_by
  | :finished_by
  | :finishes
  | :contains
  | :during
  | :starts
  | :started_by
  | :equals
```

The types of relationship between two Date.Range intervals

# `iso_day_number`

```elixir
@type iso_day_number() :: integer()
```

Represents the number of days since the
calendar epoch.

The Calendar epoch is `0000-01-01`
in the proleptic gregorian calendar.

# `leap_month?`

```elixir
@type leap_month?() :: boolean() | :leap
```

Boolean indicating is this is a leap month

# `month`

```elixir
@type month() :: Calendar.month() | nil
```

Specifies the month of a date as either
a positive integer or nil.

# `naive_date_time`

```elixir
@type naive_date_time() :: %{
  optional(:calendar) =&gt; calendar(),
  optional(:day) =&gt; day(),
  optional(:hour) =&gt; Calendar.hour(),
  optional(:microsecond) =&gt; Calendar.microsecond(),
  optional(:minute) =&gt; Calendar.minute(),
  optional(:month) =&gt; month(),
  optional(:second) =&gt; Calendar.second(),
  optional(:year) =&gt; year(),
  optional(any()) =&gt; any()
}
```

All naive date time fields are optional however many functions
will require the presence of one or more - and
often all - fields be present.

# `part`

```elixir
@type part() ::
  :day_periods
  | :day_period
  | :days_of_week
  | :day_of_week
  | :month
  | :quarter
  | :cyclic_year
  | :era
```

The part of a date, time or datetime that can be
localized.

# `precision`

```elixir
@type precision() :: :years | :quarters | :months | :weeks | :days
```

The precision for date intervals

# `quadrimester`

```elixir
@type quadrimester() :: 1..3
```

Specifies the quadrimester (third) of year for a calendar date.

# `quarter`

```elixir
@type quarter() :: 1..4
```

Specifies the quarter of year for a calendar date.

# `semester`

```elixir
@type semester() :: 1..2
```

Specifies the semester (half) of year for a calendar date.

# `time`

```elixir
@type time() :: %{
  optional(:calendar) =&gt; Calendar.calendar(),
  optional(:hour) =&gt; Calendar.hour(),
  optional(:microsecond) =&gt; Calendar.microsecond(),
  optional(:minute) =&gt; Calendar.minute(),
  optional(:second) =&gt; Calendar.second(),
  optional(any()) =&gt; any()
}
```

All time fields are optional however many functions
will require the presence of one or more - and
often all - fields be present.

# `traditional_month`

```elixir
@type traditional_month() :: Calendar.month() | {Calendar.month(), :leap}
```

A traditional lunisolar month: its number in the traditional
numbering, or that number and `:leap` for a leap month.

# `week`

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

Specifies the week of year for a calendar date.

# `year`

```elixir
@type year() :: Calendar.year() | nil
```

Specifies the year of a date as either
a positive integer or nil.

# `date_from_iso_days`

```elixir
@callback date_from_iso_days(iso_day_number :: iso_day_number()) ::
  {Calendar.year(), Calendar.month(), Calendar.day()}
```

Returns the date of this calendar that falls on an ISO day number:
the reverse of `date_to_iso_days/3`.

# `date_from_written_date`

```elixir
@callback date_from_written_date(
  year :: Calendar.year(),
  month :: traditional_month(),
  day :: Calendar.day()
) ::
  {:ok, {Calendar.year(), Calendar.month(), Calendar.day()}}
  | {:error, :invalid_date}
```

Returns the date of this calendar that written figures name: the
inverse of `c:written_date/3`.

Figures that name no date are `{:error, :invalid_date}`. The reason is
an atom, not an exception as Calendrical's other functions return,
because Localize's date parser reads it from every calendar.

# `date_to_iso_days`

```elixir
@callback date_to_iso_days(year :: year(), month :: month(), day :: day()) ::
  iso_day_number()
```

Returns the ISO day number of a date of this calendar: the count of
days from Calendrical's epoch that `date_from_iso_days/1` reverses.

Every calendar's arithmetic runs through this pair, and `use
Calendrical.Calendar` refuses to compile a calendar without them.

# `diff`

```elixir
@callback diff(
  from :: {year(), month() | week(), day()},
  to :: {year(), month() | week(), day()},
  date_part :: :years | :quarters | :months | :weeks | :days
) :: integer() | {:error, Exception.t()}
```

Returns the whole number of years, quarters, months, weeks or days
from one `{year, month, day}` to another, as `shift/6` adds them.

The count is the largest number of `date_part`s that `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`.

A `{year, month, day}` that is no date of the calendar is
`{:error, %Calendrical.InvalidDateError{}}`, one missing a field a
`Calendrical.MissingFieldsError`, and a `date_part` other than the five
a `Calendrical.InvalidPartError`.

# `info`

```elixir
@callback info() :: Calendrical.Info.t()
```

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

The facts are what a calendar is: the CLDR calendars that name its
months and its eras, its epoch, whether it has a year 0, what its year
is built of, the fewest and most months a year has, the rule its own
weeks follow, its cycles, the place it is reckoned at, the lengths its
months can have, the calendar its dates are parsed in and, for a
composite, its member calendars. Every calendar Calendrical builds
answers it.

# `leap_month`

```elixir
@callback leap_month(year :: year()) :: Calendar.month() | nil
```

Returns the position of a year's leap month, or `nil` where the year
has none.

It is the one fact the traditional numbering of months rests on: a
month before the leap month keeps its number, the leap month is
`{number, :leap}` of the month it follows, and a month after it is
one less than its position. In a Chinese year whose leap month follows
month 2 it is 3, so position 3 is `{2, :leap}` and position 4 is 3; in
a Hebrew leap year it is 6, Adar I, `{5, :leap}`.

# `shift`

```elixir
@callback shift(
  year :: year(),
  month :: month() | week(),
  day :: day(),
  date_part :: :years | :quarters | :months | :weeks | :days,
  increment :: integer(),
  options :: Keyword.t()
) ::
  {Calendar.year(), Calendar.month(), Calendar.day()} | {:error, Exception.t()}
```

Returns the date a specified positive or negative integer number of
periods (years, quarters, months, weeks or days) from a
`{year, month, day}` of this calendar.

Every calendar answers for each of the five periods. The `:clamp`
option says whether a month or a day the resulting year or month does
not have is brought back into it (`true`) or kept as it is counted
(`false`); where it is not given, the calendar's own default applies.

A `{year, month, day}` that is no date of the calendar is
`{:error, %Calendrical.InvalidDateError{}}`, one missing a field a
`Calendrical.MissingFieldsError`, and a `date_part` other than the five
a `Calendrical.InvalidPartError`.

# `written_date`

```elixir
@callback written_date(year :: year(), month :: month(), day :: day()) ::
  {Calendar.year(), traditional_month(), Calendar.day()}
```

Returns the figures a date is written with: the year, the month and
the day a format prints with `y`, `M` and `d`.

A calendar whose dates are written as its own fields answers them
unchanged, which is the default every calendar has and what the
Hebrew calendar answers, as ICU writes a Hebrew month by its place in
the year. A calendar whose dates are written as another calendar's
answers that calendar's: a fiscal year that begins in July writes its
month 1 as `{gregorian_year, 7, day}`, and `Calendrical.Julian.March25`
writes its month 1 day 1 as `{label_year, 3, 25}`. A lunisolar calendar
writes a month by its traditional number, `{number, :leap}` for a leap
month, so that CLDR's numeric leap pattern applies.

# `additional_calendars`

```elixir
@spec additional_calendars() :: additional_calendars()
```

Returns every calendar Calendrical implements that no CLDR calendar type
resolves to, as a `%{atom => module}` map keyed by its IXDTF `[u-ca=…]`
identifier.

Most have no CLDR/BCP 47 calendar identifier: Julian and its year-start
variants, the reform calendars, NRF, ISO week dates, and the Vietnamese and
Japanese lunisolar calendars, which CLDR files under `chinese`. `:iso8601`,
which CLDR does define, is the Gregorian calendar with ISO 8601's week
rules, `Calendrical.ISO`. The identifiers are resolved by
`calendar_from_cldr_calendar_type/1` ahead of the CLDR lookup, so consumers
that keep to CLDR identifiers are unaffected. An identifier is written with
hyphens in the suffix: `:julian_march25` is `[u-ca=julian-march25]`.

### Returns

* A `%{atom => module}` map of the additional calendar identifiers.

### Examples

    iex> Calendrical.additional_calendars()[:vietnamese]
    Calendrical.Vietnamese

    iex> Calendrical.additional_calendars()[:julian_march25]
    Calendrical.Julian.March25

# `calendar_for_territory`

```elixir
@spec calendar_for_territory(atom() | String.t(), Keyword.t()) ::
  {:ok, calendar()} | {:error, Exception.t()}
```

Returns a calendar configured according to
the preferences defined for a territory.

### Arguments

* `territory` is any valid ISO3166-2 code as
  an `t:String.t/0` or upcased `atom`.

* `config` is a Keyword list defining the configuration
  of the calendar. The default is `[]`.

### Options

* The options of a `:month` calendar of `Calendrical.new/3`:
  `:base`, `:year_begins`, `:year_number`, `:written_year`, `:weeks`,
  `:cldr_calendar_type`, `:era_calendar_type`, `:parsing_calendar` and
  `:years_in_cycle`. The territory's own week rule is the default
  `:weeks`.

### Returns

* `{:ok, calendar_module}` or

* `{:error, exception}` where `exception` is an exception struct.

### Examples

    iex> Calendrical.calendar_for_territory(:US)
    {:ok, Calendrical.US}

    iex> {:error, %Localize.UnknownTerritoryError{}} = Calendrical.calendar_for_territory(:YY)

# `calendar_from_cldr_calendar_type`

```elixir
@spec calendar_from_cldr_calendar_type(atom() | String.t()) ::
  {:ok, module()} | {:error, Exception.t()}
```

Returns the Calendrical calendar module associated
with a CLDR calendar type.

CLDR calendar types are the atoms (or their string
equivalents) returned by `Localize.validate_calendar/1`
and listed by `supported_cldr_calendar_types/0`. This
function maps such a type to the corresponding
Calendrical calendar module if it is loaded in the
current build.

The calendars in `additional_calendars/0` resolve here too, ahead of the
CLDR lookup — every calendar Calendrical implements that no CLDR type
reaches, such as `:vietnamese` and `:julian_march25` (`"julian-march25"`),
and `:iso8601`, the Gregorian calendar with ISO 8601's week rules.

This is the one table of names. A name has no territory, so `:gregorian`
is `Calendrical.Gregorian` and `:chinese` is `Calendrical.Chinese`; a
locale that names them in its `-u-ca-` extension has a territory, and
`calendar_from_locale/1` refines those two by it.

### Arguments

* `calendar_type` is a CLDR calendar type as an atom
  or string. The string `"gregory"` is accepted as an
  alias for `:gregorian`.

### Returns

* `{:ok, calendar_module}` where `calendar_module`
  is the Calendrical calendar module for the given
  CLDR calendar type, or

* `{:error, exception}` where `exception` is an
  exception struct.

### Examples

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

    iex> Calendrical.calendar_from_cldr_calendar_type("gregory")
    {:ok, Calendrical.Gregorian}

    iex> Calendrical.calendar_from_cldr_calendar_type(:persian)
    {:ok, Calendrical.Persian}

    iex> Calendrical.calendar_from_cldr_calendar_type(:islamic_umalqura)
    {:ok, Calendrical.Islamic.UmmAlQura}

    iex> Calendrical.calendar_from_cldr_calendar_type(:ethiopic_amete_alem)
    {:ok, Calendrical.Ethiopic.AmeteAlem}

    iex> Calendrical.calendar_from_cldr_calendar_type(:dangi)
    {:ok, Calendrical.Korean}

    iex> Calendrical.calendar_from_cldr_calendar_type(:julian)
    {:ok, Calendrical.Julian}

    iex> Calendrical.calendar_from_cldr_calendar_type(:iso8601)
    {:ok, Calendrical.ISO}

    iex> Calendrical.calendar_from_cldr_calendar_type("vietnamese")
    {:ok, Calendrical.Vietnamese}

    iex> Calendrical.calendar_from_cldr_calendar_type("reform-england")
    {:ok, Calendrical.Reform.England}

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

# `calendar_from_locale`

```elixir
@spec calendar_from_locale(Localize.LanguageTag.t() | String.t() | atom()) ::
  {:ok, calendar()} | {:error, Exception.t()}
```

Returns the calendar module for a locale.

A locale's `-u-ca-<name>` extension names a CLDR calendar, and its
calendar module is the one `calendar_from_cldr_calendar_type/1` gives
that name, refined by the locale where its territory says more than the
name: `gregory` is the territory's Gregorian calendar, with its weeks,
and `chinese` in Vietnam is `Calendrical.Vietnamese`. A locale with no
`-u-ca-` takes the calendar its territory prefers. This is the mapping
from a language tag's calendar to a calendar module: Localize does not
depend on Calendrical, so it is Calendrical's to give.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`.

### Returns

* `{:ok, calendar_module}`, or

* `{:error, exception}` if the locale is not valid. A `-u-ca-` name
  that is not a CLDR calendar's, such as an identifier of
  `additional_calendars/0`, is not valid in a locale.

### Examples

    iex> Calendrical.calendar_from_locale("en-US")
    {:ok, Calendrical.US}

    iex> Calendrical.calendar_from_locale("en-GB-u-ca-gregory")
    {:ok, Calendrical.GB}

    iex> Calendrical.calendar_from_locale("fa-IR")
    {:ok, Calendrical.Persian}

    iex> Calendrical.calendar_from_locale("fa-IR-u-ca-gregory")
    {:ok, Calendrical.IR}

    iex> Calendrical.calendar_from_locale("en-u-ca-hebrew")
    {:ok, Calendrical.Hebrew}

    iex> Calendrical.calendar_from_locale("vi-u-ca-chinese")
    {:ok, Calendrical.Vietnamese}

    iex> {:error, %Localize.InvalidLocaleError{}} =
    ...>   Calendrical.calendar_from_locale("en-u-ca-julian")

# `calendar_from_territory`

```elixir
@spec calendar_from_territory(atom() | String.t()) ::
  {:ok, calendar()} | {:error, Exception.t()}
```

Returns the calendar module preferred for
a territory.

### Arguments

* `territory` is any valid ISO3166-2 code as
  an `t:String.t/0` or upcased `atom`.

### Returns

* `{:ok, calendar_module}` or

* `{:error, exception}` where `exception` is an exception struct.

### Examples

    iex> Calendrical.calendar_from_territory(:US)
    {:ok, Calendrical.US}

    iex> Calendrical.calendar_from_territory(:IR)
    {:ok, Calendrical.Persian}

    iex> {:error, %Localize.UnknownTerritoryError{}} = Calendrical.calendar_from_territory(:YY)

### Notes

The overwhelming majority of territories have
`:gregorian` as their first preferred calendar
and therefore `Calendrical.Gregorian` or
a derivation of it will be returned for most
territories.

A territory that prefers another calendar is given
that calendar's module: Iran (territory `:IR`) prefers
the `:persian` calendar, so `Calendrical.Persian` is
returned, and Thailand (`:TH`) the `:buddhist`
calendar, so `Calendrical.Buddhist` is.

# `calendar_module?`

```elixir
@spec calendar_module?(module()) :: boolean()
```

Returns a boolean indicating if a module
is a `Calendrical` module.

A calendar is a module that implements Elixir's `Calendar` behaviour
and the `Calendrical` behaviour, and says so with `@behaviour`. That
is all that is asked of it here: what the module then answers for
each callback is its author's to keep.

### Arguments

* `module` is any module name as an `atom`.

### Returns

* `true` if `module` is a calendar module that implements the
  `Calendar` and `Calendrical` behaviours, otherwise `false`.

### Examples

    iex> Calendrical.calendar_module?(Calendrical.Gregorian)
    true

    iex> Calendrical.calendar_module?(Calendar.ISO)
    false

    iex> Calendrical.calendar_module?(Enum)
    false

# `convert`

```elixir
@spec convert(Date.t() | Date.Range.t(), Calendar.calendar()) ::
  {:ok, Date.t() | Date.Range.t()} | {:error, Exception.t()}
```

Converts a date or a date range to another calendar.

If the argument is a `t:Calendar.date/0`, `Date.convert/2` is used to
do the conversion.

If the argument is a `t:Date.Range.t/0` then `Date.convert/2` is
applied to the start and end of the range and a new range returned.

### Arguments

* `date_or_range` is any `t:Calendar.date/0` or `t:Date.Range.t/0`.

* `calendar` is any valid calendar module.

### Returns

* `{:ok, converted_date_or_range}` or

* `{:error, %Calendrical.IncompatibleCalendarError{}}` where the two
  calendars begin their days at different times.

### Examples

    iex> Calendrical.convert(~D[2024-06-01], Calendrical.Hebrew)
    {:ok, ~D[5784-09-24 Calendrical.Hebrew]}

    iex> Calendrical.convert(Date.range(~D[2024-06-01], ~D[2024-06-03]), Calendrical.Persian)
    {:ok, Date.range(~D[1403-03-12 Calendrical.Persian], ~D[1403-03-14 Calendrical.Persian])}

# `current`

```elixir
@spec current(date() | Date.Range.t(), :year | :quarter | :month | :week | :day) ::
  date() | Date.Range.t()
```

Returns the current date or date range for
a date period (year, quarter, month, week
or day).

### Arguments

* `date_or_date_range` is any `t:Calendar.date/0` or
  `t:Date.Range.t/0`.

* `period` is `:year`, `:quarter`, `:month`,
  `:week` or `:day`.

### Returns

When a `t:Calendar.date/0` is passed, a `t:Calendar.date/0` is
returned.  When a `t:Date.Range.t/0` is passed
a `t:Date.Range.t/0` is returned.

### Examples

    iex> Calendrical.current(~D[2019-01-01], :day)
    ~D[2019-01-01]

# `cyclic_year`

```elixir
@spec cyclic_year(date()) :: Calendar.year() | date_error()
```

Returns the cycle `year`
number for a `date`.

A related gregorian year is the gregorian
year that is most closely associated with a
date that is in another calendar.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or
  more of the fields `:year`, `:month`, `:day` and
  optionally `:calendar`.

### Returns

* the cyclic year as an integer.

### Examples

    iex> Calendrical.cyclic_year(~D[2019-01-01])
    2019

    iex> Calendrical.cyclic_year(Calendrical.first_day_of_year(2019, Calendrical.NRF))
    2019

    iex> Calendrical.cyclic_year(Calendrical.last_day_of_year(2019, Calendrical.NRF))
    2019

# `cyclic_years`

```elixir
@spec cyclic_years(Localize.LanguageTag.t() | String.t() | atom(), atom()) ::
  {:ok, map()} | {:error, Exception.t()}
```

Returns the cyclic year data for a locale and calendar type.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* `calendar` is a calendar type atom. The default is `:gregorian`.

### Returns

* `{:ok, map}` where the map holds the cyclic year data.

* `{:error, exception}` if the locale has no cyclic year data
  for the calendar.

### Examples

    iex> {:ok, cyclic_years} = Calendrical.cyclic_years(:en, :chinese)
    iex> cyclic_years.years.format.abbreviated[1]
    "jia-zi"

# `date_from_day_of_year`

```elixir
@spec date_from_day_of_year(Calendar.year(), pos_integer(), calendar()) ::
  Date.t() | {:error, Exception.t()}
```

Returns a `t:Calendar.date/0` from a year, day_of_year
and a calendar.

### Arguments

* `year` is any integer year that is valid in
  `calendar`.

* `day_of_year` is any valid ordinal day of
  `year`.

* `calendar` is any module implementing
  the `Calendar` and `Calendrical`
  behaviours. The default is `Calendrical.Gregorian`.

### Returns

* a `t:Calendar.date/0` or

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

### Examples

    iex> Calendrical.date_from_day_of_year(2019, 32)
    ~D[2019-02-01 Calendrical.Gregorian]

    iex> Calendrical.date_from_day_of_year(2019, 366)
    {:error, %Calendrical.InvalidDateError{calendar: Calendrical.Gregorian, value: [year: 2019, day_of_year: 366]}}

    iex> Calendrical.date_from_day_of_year(1700, 1, Calendrical.Julian.March25)
    ~D[1700-01-01 Calendrical.Julian.March25]

# `date_from_iso_days`

```elixir
@spec date_from_iso_days(Calendar.iso_days() | iso_day_number(), calendar()) ::
  Date.t() | {:error, Exception.t()}
```

Returns a date represented by a number of
days since the start of the epoch.

The start of the epoch is the date
`0000-01-01`.

### Arguments

* `iso_days` is an integer representing the
  number of days since the start of the epoch.

* `calendar` is any module that implements
  the `Calendar` and `Calendrical` behaviours.

### Returns

* A `t:Calendar.date/0`.

### Examples

    iex> Calendrical.date_from_iso_days(737425, Calendar.ISO)
    ~D[2019-01-01]

    iex> Calendrical.date_from_iso_days(366, Calendar.ISO)
    ~D[0001-01-01]

    iex> Calendrical.date_from_iso_days(0, Calendar.ISO)
    ~D[0000-01-01]

# `date_from_list`

```elixir
@spec date_from_list(Keyword.t(), calendar()) :: Date.t() | {:error, Exception.t()}
```

Returns a `t:Calendar.date/0` from a keyword list
and a calendar.

### Arguments

* `[year: year, month: month, day: day}` is a
  keyword list representing a date.

* `calendar` is any module implementing
  the `Calendar` and `Calendrical`
  behaviours. The default is `Calendrical.Gregorian`.

### Returns

* a `t:Calendar.date/0` or

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

### Examples

    iex> Calendrical.date_from_list([year: 2019, month: 3, day: 25], Calendrical.Gregorian)
    %Date{calendar: Calendrical.Gregorian, day: 25, month: 3, year: 2019}

    iex> Calendrical.date_from_list([year: 2019, month: 2, day: 29], Calendrical.Gregorian)
    {:error, %Calendrical.InvalidDateError{calendar: Calendrical.Gregorian, value: {2019, 2, 29}}}

# `date_from_tuple`

```elixir
@spec date_from_tuple({Calendar.year(), Calendar.month(), Calendar.day()}, calendar()) ::
  Date.t() | {:error, Exception.t()}
```

Returns a `t:Calendar.date/0` from a date tuple of
`{year, month, day}` and a calendar.

### Arguments

* `{year, month, day}` is a tuple
  representing a date.

* `calendar` is any module implementing
  the `Calendar` and `Calendrical`
  behaviours. The default is `Calendrical.Gregorian`.

### Returns

* a `t:Calendar.date/0`.

### Examples

    iex> Calendrical.date_from_tuple({2019, 3, 25}, Calendrical.Gregorian)
    %Date{calendar: Calendrical.Gregorian, day: 25, month: 3, year: 2019}

    iex> Calendrical.date_from_tuple({2019, 2, 29}, Calendrical.Gregorian)
    {:error, %Calendrical.InvalidDateError{calendar: Calendrical.Gregorian, value: {2019, 2, 29}}}

# `date_to_iso_days`

```elixir
@spec date_to_iso_days(Date.t()) :: iso_day_number()
```

Returns the number of days since the start
of the epoch.

The start of the epoch is the date 0000-01-01.

### Arguments

* `date` is any `t:Calendar.date/0`.

### Returns

* The integer number of days since the epoch
  for the given `date`.

### Examples

    iex> Calendrical.date_to_iso_days(~D[2019-01-01])
    737425

    iex> Calendrical.date_to_iso_days(~D[0001-01-01])
    366

    iex> Calendrical.date_to_iso_days(~D[0000-01-01])
    0

# `date_to_string`

```elixir
@spec date_to_string(Date.t()) :: String.t()
```

Formats a date into a string representation.

Note that the output is not decorated with
the calendar module name.

### Arguments

* `date` is any `t:Calendar.date/0`.

### Returns

* The date as a string, in the calendar's own format.

### Examples

    iex> Calendrical.date_to_string(~D[2019-12-04])
    "2019-12-04"

    iex> Calendrical.date_to_string(~D[2019-06-04 Calendrical.NRF])
    "2019-06-04"

# `dates_in_gregorian_year`

```elixir
@spec dates_in_gregorian_year(
  module(),
  Calendar.year(),
  Calendar.month(),
  Calendar.day()
) :: [Date.t()]
```

Returns the dates in `calendar`, of the given `month` and `day`, that fall
within the given Gregorian year.

This dispatches the calendar's own `dates_in_gregorian_year/3`, so a
calendar that overrides the default implementation answers here too; use
this arity when the calendar is chosen at runtime.

### Arguments

* `calendar` is a module implementing the `Calendrical` behaviour.

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

* `month` and `day` are a month and day in `calendar`.

### Returns

* A list of zero, one or two `t:Date.t/0` values in `calendar`, earliest
  first. A calendar date recurs once per that calendar's own year, but the
  calendar and Gregorian years drift, so a Gregorian year can hold zero,
  one or two occurrences of it.

### Examples

    iex> Calendrical.dates_in_gregorian_year(Calendrical.Islamic.Civil, 2025, 1, 1)
    [~D[1447-01-01 Calendrical.Islamic.Civil]]

    # Ramadan 29 falls twice in the Gregorian year 2000
    iex> Calendrical.dates_in_gregorian_year(Calendrical.Islamic.Civil, 2000, 9, 29)
    [~D[1420-09-29 Calendrical.Islamic.Civil], ~D[1421-09-29 Calendrical.Islamic.Civil]]

# `datetime_from_modified_julian_date`

```elixir
@spec datetime_from_modified_julian_date(number()) :: DateTime.t()
```

Returns the DateTime (defaulting to UTC timezone)
for the given Modified Julian Day.

### Arguments

* `mjd` is a number representing days passed since November 17, 1858 (Julian Calendar).

### Returns

* a `t:DateTime.t/0` at UTC timezone.

### Examples

    iex> Calendrical.datetime_from_modified_julian_date(59848)
    ~U[2022-09-26 00:00:00.000Z]

    iex> Calendrical.datetime_from_modified_julian_date(59848.75)
    ~U[2022-09-26 18:00:00.000Z]

# `day_of_era`

```elixir
@spec day_of_era(date()) :: {Calendar.day(), Calendar.era()} | date_error()
```

Returns the `{day_of_era, era}` for
a `date`.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or
  more of the fields `:year`, `:month`, `:day` and
  optionally `:calendar`.

### Returns

* The day of the era, counted from its first day, and the era of the
  date's calendar year, as a tuple. A calendar whose year 1 begins on
  another day than 1 January AD 1 counts era 1 from the day it does:
  NRF's year 1 began 34 days into AD 1.

### Examples

    iex> Calendrical.day_of_era ~D[2019-01-01]
    {737060, 1}

    iex> Calendrical.day_of_era(Calendrical.first_day_of_year(2019, Calendrical.NRF))
    {737059, 1}

    iex> Calendrical.day_of_era(Calendrical.last_day_of_year(2019, Calendrical.NRF))
    {737422, 1}

# `day_of_week`

```elixir
@spec day_of_week(date()) :: Calendar.day_of_week()
```

Returns the day of the week for a date.

Delegates to `Date.day_of_week/1`.

### Arguments

* `date` is any `t:Calendar.date/0`.

### Returns

* An integer day of the week where `1` means `Monday`
  and `7` means `Sunday`.

### Examples

    iex> Calendrical.day_of_week(~D[2026-07-05])
    7

# `day_of_week`

```elixir
@spec day_of_week(date(), atom()) :: Calendar.day_of_week()
```

Returns the day of the week for a date with the
week starting on a given day.

Delegates to `Date.day_of_week/2`.

### Arguments

* `date` is any `t:Calendar.date/0`.

* `starting_on` is `:default` or an atom day name
  such as `:monday` or `:sunday`. See `Date.day_of_week/2`.

### Returns

* An integer day of the week relative to `starting_on`.

### Examples

    iex> Calendrical.day_of_week(~D[2026-07-05], :sunday)
    1

# `day_of_year`

```elixir
@spec day_of_year(date()) :: Calendar.day() | date_error()
```

Returns the `day` of the year
for a `date`.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or
  more of the fields `:year`, `:month`, `:day` and
  optionally `:calendar`.

### Returns

* The day of the year as an integer, counting the year's first day as 1.

### Examples

    iex> Calendrical.day_of_year(~D[2019-01-01])
    1

    iex> Calendrical.day_of_year(~D[2016-12-31])
    366

    iex> Calendrical.day_of_year(~D[2019-12-31])
    365

    iex> Calendrical.day_of_year(~D[2019-W52-7 Calendrical.NRF])
    364

    iex> Calendrical.day_of_year(~D[2012-W53-7 Calendrical.NRF])
    371

# `day_periods`

```elixir
@spec day_periods(Localize.LanguageTag.t() | String.t() | atom(), atom()) ::
  {:ok, map()} | {:error, Exception.t()}
```

Returns the day period data for a locale and calendar type.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* `calendar` is a calendar type atom. The default is `:gregorian`.

### Returns

* `{:ok, map}` where the map holds the day period data.

* `{:error, exception}` if the locale has no day period data
  for the calendar.

### Examples

    iex> {:ok, day_periods} = Calendrical.day_periods(:en, :gregorian)
    iex> day_periods.format.abbreviated.noon
    "noon"

# `days`

```elixir
@spec days(Localize.LanguageTag.t() | String.t() | atom(), atom()) ::
  {:ok, map()} | {:error, Exception.t()}
```

Returns the day name data for a locale and calendar type.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* `calendar` is a calendar type atom. The default is `:gregorian`.

### Returns

* `{:ok, map}` where the map holds the day name data.

* `{:error, exception}` if the locale has no day name data
  for the calendar.

### Examples

    iex> {:ok, days} = Calendrical.days(:en, :gregorian)
    iex> days.format.wide[1]
    "Monday"

# `days_in_month`

```elixir
@spec days_in_month(date()) :: Calendar.day() | {:error, Exception.t()}
```

Returns the number of days in the month of a date.

Delegates to `Date.days_in_month/1`. A month of a calendar of weeks is four or five weeks, as its pattern of weeks gives it, and its last month has one week more in a year of 53 weeks.

### Arguments

* `date` is any `t:Calendar.date/0`.

### Returns

* The number of days in the month of `date`, or

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

### Examples

    iex> Calendrical.days_in_month(~D[2026-07-05])
    31

    iex> Calendrical.days_in_month(~D[2026-06-16 Calendrical.ISOWeek])
    28

# `default_calendar`

```elixir
@spec default_calendar() :: Calendrical.Gregorian
```

Returns the default calendar.

### Returns

* The default calendar module, `Calendrical.Gregorian`.

### Examples

    iex> Calendrical.default_calendar()
    Calendrical.Gregorian

# `diff`

```elixir
@spec diff(
  Calendar.date(),
  Calendar.date(),
  :years | :quarters | :months | :weeks | :days
) ::
  integer() | {:error, Exception.t()}
```

Returns the whole number of years, quarters, months, weeks or days
from one date to another, in the dates' own calendar.

`diff/3` is the inverse of adding periods to a date: the count is the
largest number of `date_part`s that can be added to the earlier date —
a day that a shorter month lacks becoming that month's last day, as
`Date.shift/2` does — without passing the later date, and it is negative
when `date_to` is before `date_from`. `Date.diff/2` answers the same
question in days.

### Arguments

* `date_from` and `date_to` are `t:Calendar.date/0` values in the same
  calendar. A `Calendar.ISO` date counts as a `Calendrical.Gregorian`
  one.

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

### Returns

* The whole number of `date_part`s from `date_from` to `date_to`, as an
  integer.

* `{:error, %Calendrical.IncompatibleCalendarError{}}` when the dates
  are in different calendars.

* `{:error, %Calendrical.InvalidPartError{}}` when `date_part` is not
  one of the five.

* `{:error, %Calendrical.MissingFieldsError{}}` when a date lacks a
  year, month or day, and `{:error,
  %Calendrical.InvalidCalendarModuleError{}}` when its calendar is not
  a Calendrical calendar.

### Examples

    iex> Calendrical.diff(~D[2026-01-01], ~D[2027-04-01], :months)
    15

    iex> Calendrical.diff(~D[2026-01-01], ~D[2027-04-01], :years)
    1

    iex> Calendrical.diff(~D[2027-04-01], ~D[2026-01-01], :months)
    -15

    iex> Calendrical.diff(~D[2026-01-31], ~D[2026-02-28], :months)
    1

A Hebrew leap year has thirteen months:

    iex> {:ok, from} = Date.new(5784, 1, 1, Calendrical.Hebrew)
    iex> {:ok, to} = Date.new(5786, 1, 1, Calendrical.Hebrew)
    iex> Calendrical.diff(from, to, :months)
    25

# `eras`

```elixir
@spec eras(Localize.LanguageTag.t() | String.t() | atom(), atom()) ::
  {:ok, map()} | {:error, Exception.t()}
```

Returns the era data for a locale and calendar type.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* `calendar` is a calendar type atom. The default is `:gregorian`.

### Returns

* `{:ok, map}` where the map holds the era data.

* `{:error, exception}` if the locale has no era data
  for the calendar.

### Examples

    iex> {:ok, eras} = Calendrical.eras(:en, :gregorian)
    iex> eras.wide[1]
    "Anno Domini"

# `extended_year`

```elixir
@spec extended_year(date()) :: Calendar.year() | date_error()
```

Returns the extended year of a `date`: one number for its year that runs on through every era of its calendar.

It is the year TR35's `u` format symbol writes, and is the calendar's own year in every calendar but those that count back from an era: the Julian calendar has no year 0, so its 1 BC, year -1, has the extended year 0.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or more of the fields `:year`, `:month`, `:day` and optionally `:calendar`.

### Returns

* The extended year as an integer.

### Examples

    iex> Calendrical.extended_year(~D[2019-01-01])
    2019

    iex> Calendrical.extended_year(Calendrical.last_day_of_year(2019, Calendrical.NRF))
    2019

    iex> Calendrical.extended_year(~D[-0001-06-15 Calendrical.Julian])
    0

# `first_day_for_locale`

```elixir
@spec first_day_for_locale(Localize.LanguageTag.t() | String.t() | atom()) ::
  day_of_week() | {:error, Exception.t()}
```

Returns the first day of a week for a given
locale where `1` means `Monday` and `7` means `Sunday`.

Note that the first day of the first week is commonly
not aligned with the first day of the year.

### Arguments

* `locale` is any locale or locale name validated
  by `Localize.validate_locale/1`.

### Returns

* The first day of the week for the territory
  associated with `locale` where `1` means `Monday`
  and `7` means `Sunday` or

* `{:error, exception}` where `exception` is an exception struct.

### Examples

    iex> Calendrical.first_day_for_locale(:en)
    7

    iex> Calendrical.first_day_for_locale("en-GB")
    1

# `first_day_for_territory`

```elixir
@spec first_day_for_territory(atom() | String.t()) ::
  day_of_week() | {:error, Exception.t()}
```

Returns the first day of the week for a
given territory.

### Arguments

* `territory` is any valid ISO3166-2 code.

### Returns

* The first day of the week for this territory
  where `1` means `Monday` and `7` means `Sunday` or

* `{:error, exception}` where `exception` is an exception struct.

### Examples

    iex> Calendrical.first_day_for_territory(:US)
    7

    iex> Calendrical.first_day_for_territory("GB")
    1

# `first_day_of_year`

```elixir
@spec first_day_of_year(date :: date()) :: Date.t() | {:error, Exception.t()}
```

Returns the first date of a `year`
for a `t:Calendar.date/0`.

### Arguments

* `date` is any `t:Calendar.date/0`.

### Returns

* a `t:Calendar.date/0`  or

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

### Examples

    iex>  Calendrical.first_day_of_year(~D[2019-12-01])
    ~D[2019-01-01]

# `first_day_of_year`

```elixir
@spec first_day_of_year(year :: year(), calendar :: calendar()) ::
  Date.t() | {:error, Exception.t()}
```

Returns the first date of a `year`
in a `calendar`.

### Arguments

* `year` is any year.

* `calendar` is any module that implements
  the `Calendar` and `Calendrical`
  behaviours.

### Returns

* a `t:Calendar.date/0`  or

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

### Examples

    iex> Calendrical.first_day_of_year(2019, Calendrical.Gregorian)
    %Date{calendar: Calendrical.Gregorian, day: 1, month: 1, year: 2019}

    iex> Calendrical.first_day_of_year(2019, Calendrical.NRF)
    %Date{calendar: Calendrical.NRF, day: 1, month: 1, year: 2019}

    iex> Calendrical.first_day_of_year(1700, Calendrical.Julian.March25)
    ~D[1700-01-01 Calendrical.Julian.March25]

# `first_gregorian_day_of_year`

```elixir
@spec first_gregorian_day_of_year(date()) :: Date.t() | {:error, Exception.t()}
```

Returns the gregorian date of the first day of a `year`
for a `calendar`.

### Arguments

* `year` is any integer year number.

* `calendar` is any module that implements the `Calendar` and
  `Calendrical` behaviours or `Calendar.ISO`.

### Returns

* The `t:Date.t/0` of the first day of the year: in
  `Calendrical.Gregorian` for a `year` and `calendar`, and in the
  date's own calendar for a date.

* `{:error, %Calendrical.InvalidDateError{}}` if the calendar has no such year.

### Examples

    iex> Calendrical.first_gregorian_day_of_year(2019, Calendrical.Gregorian)
    %Date{calendar: Calendrical.Gregorian, day: 1, month: 1, year: 2019}

    iex> Calendrical.first_gregorian_day_of_year(2019, Calendrical.NRF)
    %Date{calendar: Calendrical.Gregorian, day: 3, month: 2, year: 2019}

    iex> Calendrical.first_gregorian_day_of_year(~D[2019-12-01])
    ~D[2019-01-01]

# `first_gregorian_day_of_year`

```elixir
@spec first_gregorian_day_of_year(year(), calendar()) ::
  Date.t() | {:error, Exception.t()}
```

Returns the gregorian date of the first day of a `year`
for a `calendar`.

### Arguments

* `year` is any integer year number.

* `calendar` is any module that implements the `Calendar` and
  `Calendrical` behaviours or `Calendar.ISO`.

### Returns

* A `t:Date.t/0` in the `Calendrical.Gregorian` calendar or

* `{:error, %Calendrical.InvalidDateError{}}`.

### Examples

    iex> Calendrical.first_gregorian_day_of_year(2019, Calendrical.Gregorian)
    %Date{calendar: Calendrical.Gregorian, day: 1, month: 1, year: 2019}

    iex> Calendrical.first_gregorian_day_of_year(2019, Calendrical.NRF)
    %Date{calendar: Calendrical.Gregorian, day: 3, month: 2, year: 2019}

    iex> Calendrical.first_gregorian_day_of_year(5786, Calendrical.Hebrew)
    ~D[2025-09-23 Calendrical.Gregorian]

# `friday`

```elixir
@spec friday() :: 5
```

Returns the cardinal day number representing
Friday.

### Returns

* `5`.

### Examples

    iex> Calendrical.friday()
    5

# `inspect`

```elixir
@spec inspect(term(), list()) :: Inspect.Algebra.t()
```

An `inspect_fun/2` that can be configured in
`Inspect.Opts` supporting inspection of user-defined
calendars.

This function can be configured in `IEx` for Elixir version 1.9
and later by:

    IEx.configure(inspect: [inspect_fun: &Calendrical.inspect/2])
    :ok

### Arguments

* `term` is any term.

* `options` is a keyword list of options or an `t:Inspect.Opts.t/0`.

### Options

* The options of `t:Inspect.Opts.t/0`.

### Returns

* The `t:Inspect.Algebra.t/0` document for `term`, which renders a
  date or range of any calendar in its sigil form.

### Examples

    iex> ~D[2019-12-04 Calendrical.NRF]
    ...> |> Calendrical.inspect([])
    ...> |> Inspect.Algebra.format(80)
    ...> |> IO.iodata_to_binary()
    "~D[2019-12-04 Calendrical.NRF]"

# `interval`

```elixir
@spec interval(
  date_from :: Date.t(),
  date_to_or_count :: Date.t() | non_neg_integer(),
  precision()
) ::
  [Date.t()]
```

Returns an `Enumerable` list of dates of a given precision
of either `:years`, `:quarters`, `:months`, `:weeks` or
`:days`.

### Arguments

* `date_from` is a any `t:Calendar.date/0` that is the start of the
  sequence.

* `date_to_or_count` is upper bound of the sequence
  as a `t:Calendar.date/0` or the number of dates in the
  sequence to be generated.

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

The sequence is generated starting with `date_from` until the next date
in the sequence would be after `date_to`.

### Notes

The sequence can be in ascending or descending date order
based upon whether `date_from` is greater than `date_to`.

### Returns

* A list of dates.

### Examples

    iex> d = ~D[2019-01-31]
    ~D[2019-01-31]
    iex> d2 = ~D[2019-05-31]
    ~D[2019-05-31]
    iex> Calendrical.interval(d, 3, :months)
    [~D[2019-01-31], ~D[2019-02-28], ~D[2019-03-31]]
    iex> Calendrical.interval(d, d2, :months)
    [~D[2019-01-31], ~D[2019-02-28], ~D[2019-03-31],
     ~D[2019-04-30], ~D[2019-05-31]]

# `interval_stream`

```elixir
@spec interval_stream(
  date_from :: Date.t(),
  date_to_or_count :: Date.t() | non_neg_integer(),
  precision()
) :: fun()
```

Returns an a `Stream` function than can be lazily
enumerated.

This function has the same arguments and provides
the same functionality as `interval/3` except that
it is lazily evaluated.

### Arguments

* `date_from` is a any `t:Calendar.date/0` that is the start of the
  sequence.

* `date_to_or_count` is upper bound of the sequence
  as a `t:Calendar.date/0` or the number of dates in the
  sequence to be generated.

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

The sequence is generated starting with `date_from` until the next date
in the sequence would be after `date_to`.

### Notes

The sequence can be in ascending or descending date order
based upon whether `date_from` is greater than `date_to`.

### Returns

* A list of dates.

### Examples

    iex> d = ~D[2019-01-31]
    ~D[2019-01-31]
    iex> d2 = ~D[2019-05-31]
    ~D[2019-05-31]
    iex> Calendrical.interval_stream(d, 3, :months) |> Enum.to_list
    [~D[2019-01-31], ~D[2019-02-28], ~D[2019-03-31]]
    iex> Calendrical.interval_stream(d, d2, :months) |> Enum.to_list
    [~D[2019-01-31], ~D[2019-02-28], ~D[2019-03-31],
     ~D[2019-04-30], ~D[2019-05-31]]

# `iso_day_of_week`

```elixir
@spec iso_day_of_week(date()) :: Calendar.day_of_week()
```

Returns the ISO day of week for a `date`
where `1` means `Monday` and `7` means
`Sunday`.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or
  more of the fields `:year`, `:month`, `:day` and
  optionally `:calendar`.

### Returns

* An integer ISO day of week in the range
  `1..7` where `1` is `Monday` and `7` is
  `Sunday`.

### Examples

    iex> {:ok, us_calendar} = Calendrical.calendar_from_locale("en")
    iex> {:ok, us_date} = Date.new(2025, 1, 1, us_calendar)
    iex> Calendrical.iso_day_of_week(us_date)
    3

# `iso_days_to_day_of_week`

```elixir
@spec iso_days_to_day_of_week(Calendar.iso_days() | Calendar.day()) :: day_of_week()
```

Returns the day of the week for a given
`iso_day_number`

### Arguments

* `iso_day_number` is the number of days since the start
  of the epoch.  See `Calendrical.date_to_iso_days/1`.

### Returns

* An integer representing a day of the week where Monday
  is represented by `1` and Sunday is represented by `7`.

### Examples

    iex> days = Calendrical.date_to_iso_days(~D[2019-01-01])
    iex> Calendrical.iso_days_to_day_of_week(days) == Calendrical.tuesday()
    true

    iex> days = Calendrical.date_to_iso_days(~D[2026-07-05])
    iex> Calendrical.iso_days_to_day_of_week(days) == Calendrical.sunday()
    true

# `iso_week_of_year`

```elixir
@spec iso_week_of_year(date()) :: {Calendar.year(), week()} | date_error()
```

Returns the `ISO week` number for
a `date`.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or
  more of the fields `:year`, `:month`, `:day` and
  optionally `:calendar`.

### Returns

* a the ISO week of the year as an
  integer or

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

### Examples

    iex> Calendrical.iso_week_of_year(~D[2019-01-01])
    {2019, 1}
    iex> Calendrical.iso_week_of_year(~D[2019-02-01])
    {2019, 5}
    iex> Calendrical.iso_week_of_year(~D[2019-W52-1 Calendrical.NRF])
    {2020, 4}
    iex> Calendrical.iso_week_of_year(~D[2019-W26-1 Calendrical.NRF])
    {2019, 30}
    iex> Calendrical.iso_week_of_year(~D[2019-12-01 Calendrical.Julian])
    {2019, 50}

# `last_day_of_year`

```elixir
@spec last_day_of_year(date :: date()) :: Date.t() | {:error, Exception.t()}
```

Returns the last date of a `year`
for a `t:Calendar.date/0`.

### Arguments

* `date` is any `t:Calendar.date/0`.

### Returns

* a `t:Calendar.date/0`  or

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

### Examples

    iex>  Calendrical.last_day_of_year(~D[2019-01-01])
    ~D[2019-12-31]

# `last_day_of_year`

```elixir
@spec last_day_of_year(year :: year(), calendar :: calendar()) ::
  Date.t() | {:error, Exception.t()}
```

Returns the last date of a `year`
for a `calendar`.

### Arguments

* `year` is any year.

* `calendar` is any module that implements
  the `Calendar` and `Calendrical`
  behaviours.

### Returns

* a `t:Calendar.date/0`  or

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

### Examples

    iex> Calendrical.last_day_of_year(2019, Calendrical.Gregorian)
    %Date{calendar: Calendrical.Gregorian, day: 31, month: 12, year: 2019}

    iex> Calendrical.last_day_of_year(2019, Calendrical.NRF)
    %Date{calendar: Calendrical.NRF, day: 28, month: 12, year: 2019}

    iex> Calendrical.last_day_of_year(5786, Calendrical.Hebrew)
    ~D[5786-12-29 Calendrical.Hebrew]

# `last_gregorian_day_of_year`

```elixir
@spec last_gregorian_day_of_year(date()) :: Date.t() | {:error, Exception.t()}
```

Returns the gregorian date of the last day of a `year`
for a `calendar`.

### Arguments

* `year` is any integer year number or a `t:date/0`.

* `calendar` is any module that implements the `Calendar` and
  `Calendrical` behaviours or `Calendar.ISO`.

### Returns

* The `t:Date.t/0` of the last day of the year: in
  `Calendrical.Gregorian` for a `year` and `calendar`, and in the
  date's own calendar for a date.

* `{:error, %Calendrical.InvalidDateError{}}` if the calendar has no such year.

### Examples

    iex> Calendrical.last_gregorian_day_of_year(2019, Calendrical.Gregorian)
    %Date{calendar: Calendrical.Gregorian, day: 31, month: 12, year: 2019}

    iex> Calendrical.last_gregorian_day_of_year(2019, Calendrical.NRF)
    %Date{calendar: Calendrical.Gregorian, day: 1, month: 2, year: 2020}

    iex> Calendrical.last_gregorian_day_of_year(~D[2019-12-01])
    ~D[2019-12-31]

# `last_gregorian_day_of_year`

```elixir
@spec last_gregorian_day_of_year(year(), calendar()) ::
  Date.t() | {:error, Exception.t()}
```

Returns the gregorian date of the last day of a `year`
for a `calendar`.

### Arguments

* `year` is any integer year number.

* `calendar` is any module that implements the `Calendar` and
  `Calendrical` behaviours or `Calendar.ISO`.

### Returns

* A `t:Date.t/0` in the `Calendrical.Gregorian` calendar or

* `{:error, %Calendrical.InvalidDateError{}}`.

### Examples

    iex> Calendrical.last_gregorian_day_of_year(2019, Calendrical.Gregorian)
    %Date{calendar: Calendrical.Gregorian, day: 31, month: 12, year: 2019}

    iex> Calendrical.last_gregorian_day_of_year(2019, Calendrical.NRF)
    %Date{calendar: Calendrical.Gregorian, day: 1, month: 2, year: 2020}

    iex> Calendrical.last_gregorian_day_of_year(5786, Calendrical.Hebrew)
    ~D[2026-09-11 Calendrical.Gregorian]

# `localize`

```elixir
@spec localize(any_date_time()) :: {:ok, any_date_time()} | {:error, Exception.t()}
```

Localize a date by converting it to the calendar
introspected from the current process locale.

### Arguments

* `date` is any `t:Calendar.date/0`.

### Returns

* `{:ok, date}` where `date` is converted into the calendar
  associated with `Localize.get_locale/0`.

* `{:error, exception}` if the locale has no calendar.

### Examples

    iex> Localize.with_locale(:fr, fn -> Calendrical.localize(~D[2022-06-09]) end)
    {:ok, %Date{year: 2022, month: 6, day: 9, calendar: Calendrical.FR}}

# `localize`

```elixir
@spec localize(any_date_time(), Keyword.t() | atom()) ::
  {:ok, any_date_time()} | {:error, Exception.t()}
```

Localize a date by converting it to calendar
introspected from the provided or default locale.

### Arguments

* `date` is any `t:Calendar.date/0`.

* `options` is a `t:Keyword.t/0` list of options. When it is
  instead an atom naming a date part, this function returns
  `localize(date, part, [])`, see `localize/3`.

### Options

* `:locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

### Returns

* `{:ok, date}` where `date` is converted into the calendar
  associated with the current or provided locale.

* `{:error, exception}` if the locale is invalid or has no calendar.

### Examples

    iex> Calendrical.localize(~D[2022-06-09], locale: "fr")
    {:ok, %Date{year: 2022, month: 6, day: 9, calendar: Calendrical.FR}}

# `localize`

```elixir
@spec localize(any_date_time(), atom(), Keyword.t()) ::
  String.t() | {:error, Exception.t()}
@spec localize(datetime :: any_date_time(), part :: part(), options :: Keyword.t()) ::
  String.t() | {:error, Exception.t()}
```

Returns a localized string for a part of
a `t:Calendar.date/0`.

### Arguments

* `date` is any `t:Calendar.date/0`.

* `part` is one of `:era`, `:quarter`, `:month`,
  `:day_of_week` or `:days_of_week`.

* `options` is a `t:Keyword.t/0` list of options.

### Options

* `:locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* `:style` is one of `:wide`, `:abbreviated` or `:narrow`. The
  default is `:abbreviated`.

* `:era` will, if set to `:variant` localize the era using
  the variant data. In the `:en` locale, this will produce `CE` and
  `BCE` rather than the default `AD` and `BC`.

* `:day_period` will, if set to `:variant` localize the "AM"/"PM"
  time period indicator with the variant data. In the `:en` locale,
  this will produce `am` and `pm` rather than the default `AM` and `PM`.

### Returns

* A string representing the localized date part, or

* A list of strings representing the days of the week for
  when `part` is `:days_of_week`. The days are in week order for
  the given date's calendar, or

* `{:error, exception}` for a `part`, `:type` or `:style` that is not
  known, a `Calendrical.InvalidPartError`, `Calendrical.InvalidTypeError`
  or `Calendrical.InvalidStyleError`, or for a date its calendar does
  not have, a `Calendrical.InvalidDateError`.

### Examples

    iex> Calendrical.localize(~D[2019-01-01], :era)
    "AD"

    iex> Calendrical.localize(~D[2019-01-01], :era, era: :variant)
    "CE"

    iex> Calendrical.localize(~D[2019-01-01], :day_of_week)
    "Tue"

    iex> Calendrical.localize(~D[0001-01-01], :day_of_week)
    "Mon"

    iex> Calendrical.localize(~D[2019-01-01], :days_of_week)
    [{1, "Mon"}, {2, "Tue"}, {3, "Wed"}, {4, "Thu"}, {5, "Fri"}, {6, "Sat"}, {7, "Sun"}]

    iex> Calendrical.localize(~D[2019-06-01], :era)
    "AD"

    iex> Calendrical.localize(~D[2019-06-01], :quarter)
    "Q2"

    iex> Calendrical.localize(~D[2019-06-01], :month)
    "Jun"

    iex> Calendrical.localize(~D[2019-06-01], :day_of_week)
    "Sat"

    iex> Calendrical.localize(~D[2019-06-01], :day_of_week, style: :wide)
    "Saturday"

    iex> Calendrical.localize(~D[2019-06-01], :day_of_week, style: :narrow)
    "S"

    iex> Calendrical.localize(~D[2019-06-01], :day_of_week, locale: "ar")
    "السبت"

# `min_days_for_locale`

```elixir
@spec min_days_for_locale(Localize.LanguageTag.t() | String.t() | atom()) ::
  1..7 | {:error, Exception.t()}
```

Returns the minimum days in the first week of a year
for a given locale.

### Arguments

* `locale` is any locale or locale name validated
  by `Localize.validate_locale/1`.

### Returns

* The minimum number of days in the first week of the
  year for the territory associated with `locale` or

* `{:error, exception}` where `exception` is an exception struct.

### Examples

    iex> Calendrical.min_days_for_locale(:en)
    1

    iex> Calendrical.min_days_for_locale("en-GB")
    4

# `min_days_for_territory`

```elixir
@spec min_days_for_territory(atom() | String.t()) :: 1..7 | {:error, Exception.t()}
```

Returns the minimum days in the first week of
a year for a given territory.

### Arguments

* `territory` is any valid ISO3166-2 code.

### Returns

* The minimum number of days in the first week of
  the year for this territory or

* `{:error, exception}` where `exception` is an exception struct.

### Examples

    iex> Calendrical.min_days_for_territory(:US)
    1

    iex> Calendrical.min_days_for_territory(:GB)
    4

# `modified_julian_day`

```elixir
@spec modified_julian_day(Date.t() | DateTime.t()) :: float()
```

Returns the Modified Julian Day of
a `t:Calendar.date/0`.

### Arguments

* `date_or_datetime` is any `t:Calendar.date/0` or a `t:DateTime.t/0`.
  If a `t:DateTime.t/0` is given, the result will be given in
  the current timezone.

### Returns

* an number representing the
  Modified Julian Day of the `date`.

### Notes

The Modified Julian Day is the number of days
since November 17, 1858. Therefore this function
only returns valid values for dates after this
date.

### Examples

    iex> Calendrical.modified_julian_day(~D[2019-01-01])
    58484.0

    iex> Calendrical.modified_julian_day(~U[2019-01-01 12:00:00Z])
    58484.5

    iex> Calendrical.modified_julian_day(~U[2022-09-26 18:00:00.000Z])
    59848.75

    # If the given DateTime is not UTC, the result is given in
    # the local timezone. This example requires a time zone database
    # such as `tz` or `tzdata` to be configured.
    #
    #     dt = DateTime.shift_zone!(~U[2019-01-01 14:00:00Z], "America/Sao_Paulo")
    #     #=> #DateTime<2019-01-01 12:00:00-02:00 -02 America/Sao_Paulo>
    #     Calendrical.modified_julian_day(dt)
    #     #=> 58484.5

# `monday`

```elixir
@spec monday() :: 1
```

Returns the cardinal day number representing
Monday.

### Returns

* `1`.

### Examples

    iex> Calendrical.monday()
    1

# `month_names`

```elixir
@spec month_names(calendar :: calendar(), options :: Keyword.t()) ::
  [{pos_integer(), String.t()}] | {:error, Exception.t()}
```

Returns a sorted list of tuples containing ordinal months and
month names for a give calendar.

### Arguments

* `calendar` is any calendar module.

* `options` is a keyword list of options.

### Options

* `:locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* `:type` is one of `:stand_alone` or `:format`. The default
  is `:format`.

* `:style` is one of `:abbreviated`, `:wide` or `:narrow`.
  The default is `:abbreviated`.

### Returns

* A sorted list of tuples of the format `{ordinal month number, month name}`.

### Examples

    iex> Calendrical.month_names(Calendar.ISO, style: :wide)
    %{
      1 => "January",
      2 => "February",
      3 => "March",
      4 => "April",
      5 => "May",
      6 => "June",
      7 => "July",
      8 => "August",
      9 => "September",
      10 => "October",
      11 => "November",
      12 => "December"
    }

    iex> Calendrical.month_names(Calendar.ISO, locale: :de)
    %{
      1 => "Jan.",
      2 => "Feb.",
      3 => "März",
      4 => "Apr.",
      5 => "Mai",
      6 => "Juni",
      7 => "Juli",
      8 => "Aug.",
      9 => "Sept.",
      10 => "Okt.",
      11 => "Nov.",
      12 => "Dez."
    }

    iex> Calendrical.month_names(Calendrical.Gregorian, locale: :fr, style: :narrow)
    %{
      1 => "J",
      2 => "F",
      3 => "M",
      4 => "A",
      5 => "M",
      6 => "J",
      7 => "J",
      8 => "A",
      9 => "S",
      10 => "O",
      11 => "N",
      12 => "D"
    }

# `month_of_year`

```elixir
@spec month_of_year(date()) ::
  Calendar.month() | {Calendar.month(), leap_month :: :leap} | date_error()
```

Returns the `month` number for
a `date`.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or
  more of the fields `:year`, `:month`, `:day` and
  optionally `:calendar`.

### Returns

* The month of the year as an integer: the CLDR month the date's
  month is named by, which for a calendar of weeks is the Gregorian
  month its year begins in, counted on.

### Examples

    iex> Calendrical.month_of_year(~D[2019-01-01])
    1
    iex> Calendrical.month_of_year(~D[2019-12-01])
    12

The NRF year begins in February, so its twelfth month is named by
January and its sixth, which holds week 26, by July:

    iex> Calendrical.month_of_year(~D[2019-W52-1 Calendrical.NRF])
    1
    iex> Calendrical.month_of_year(~D[2019-W26-1 Calendrical.NRF])
    7

# `month_patterns`

```elixir
@spec month_patterns(Localize.LanguageTag.t() | String.t() | atom(), atom()) ::
  {:ok, map() | nil} | {:error, Exception.t()}
```

Returns the month pattern data for a locale and calendar type.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* `calendar` is a calendar type atom. The default is `:gregorian`.

### Returns

* `{:ok, map}` where the map holds the month pattern data.

* `{:error, exception}` if the calendar has no month patterns,
  as the Gregorian calendar has none.

### Examples

    iex> {:ok, patterns} = Calendrical.month_patterns(:en, :chinese)
    iex> patterns.format.wide.leap
    [0, "bis"]

    iex> {:error, %Localize.ItemNotFoundError{}} = Calendrical.month_patterns(:en, :gregorian)

# `months`

```elixir
@spec months(Localize.LanguageTag.t() | String.t() | atom(), atom()) ::
  {:ok, map()} | {:error, Exception.t()}
```

Returns the month name data for a locale and calendar type.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* `calendar` is a calendar type atom. The default is `:gregorian`.

### Returns

* `{:ok, map}` where the map holds the month name data.

* `{:error, exception}` if the locale has no month name data
  for the calendar.

### Examples

    iex> {:ok, months} = Calendrical.months(:en, :gregorian)
    iex> months.format.wide[1]
    "January"

# `months_in_year`

```elixir
@spec months_in_year(date()) :: Calendar.month() | {:error, Exception.t()}
```

Returns the number of months in the year of a date.

Delegates to `Date.months_in_year/1`. A calendar of weeks has the twelve months of its pattern of weeks; the weeks in its year are `weeks_in_year/1`.

### Arguments

* `date` is any `t:Calendar.date/0`.

### Returns

* The number of months in the year of `date`, or

* `{:error, exception}` for a date with no year.

### Examples

    iex> Calendrical.months_in_year(~D[2026-07-05])
    12

# `named_month`

```elixir
@spec named_month(Calendar.year(), Calendar.month(), calendar()) :: [Date.Range.t()]
```

Returns the days of a named month in a year, in the order of time.

A calendar that counts its months from the year's first day can
split the month that names them: `Calendrical.Julian.March25` begins
its year on 25 March, so its March is two counted months, the year's
month 1 (25-31 March) and its month 13 (1-24 March), 364 days apart.
The named month's days are returned as one `t:Date.Range.t/0` per
counted month that carries the name, earliest first.

### Arguments

* `year` is any year in `calendar`.

* `named_month` is the month that names the days: the month
  `cardinal_month/1` answers, which is the month field itself in a
  calendar whose months are their own numbering.

* `calendar` is a module implementing the `Calendrical` behaviour.
  The default is `Calendrical.Gregorian`.

### Returns

* A list of one or two `t:Date.Range.t/0` in time order, or `[]`
  when no month of the year carries the name.

### Examples

    iex> Calendrical.named_month(2026, 5)
    [Date.range(~D[2026-05-01 Calendrical.Gregorian], ~D[2026-05-31 Calendrical.Gregorian])]

    iex> Calendrical.named_month(1750, 3, Calendrical.Julian.March25)
    [
      Date.range(~D[1750-01-01 Calendrical.Julian.March25], ~D[1750-01-07 Calendrical.Julian.March25]),
      Date.range(~D[1750-13-01 Calendrical.Julian.March25], ~D[1750-13-24 Calendrical.Julian.March25])
    ]

    iex> Calendrical.named_month(2026, 14)
    []

# `new`

```elixir
@spec new(module(), calendar_type(), Keyword.t()) ::
  {:ok, calendar()} | {:error, Exception.t()}
```

Creates a new proleptic Gregorian calendar based upon the
provided configuration.

If a module exists with the `calendar_module` name then it
is returned, not recreated.

### Arguments

* `calendar_module` is an atom representing the module
  name of the created calendar.

* `calendar_type` is an atom of either `:month` or
  `:week` indicating which type of calendar is to
  be created.

* `config` is a Keyword list defining the configuration
  of the calendar.

### Options

A `:month` calendar takes the options of `Calendrical.Calendar.Shifted`:

* `:base` is the calendar of months the year is cut from, `Calendrical.Gregorian` by default.

* `:year_begins` is `{month, day}` of the base calendar the year begins on, `{1, 1}` by default.

* `:year_number` is the base year the year takes its number from: `:beginning`, `:ending` or `:majority`, the default.

* `:written_year` is the year a date is written with, `:base` by default, or `:label`.

* `:weeks` is the calendar's own week rule, `[first_day: 1, min_days_in_first_week: 1]` by default, or `:from_first_day`.

* `:cldr_calendar_type`, `:era_calendar_type`, `:parsing_calendar` and `:years_in_cycle` are facts for `c:Calendrical.info/0`.

A `:week` calendar takes the options of `Calendrical.Calendar.Weeks`:

* `:pattern` is the weeks in the three months of a quarter, `[4, 5, 4]` by default.

* `:year_begins` is `{weekday, :on_or_before, {month, day}}`, or `:year_ends` is `{weekday, :on_or_after, {month, day}}` or `{weekday, :nearest, {month, last_day}}`; the default is `{:monday, :on_or_before, {1, 1}}`.

* `:year_number` is the Gregorian year the year takes its number from, `:majority` by default.

* `:cldr_calendar_type` is the CLDR calendar that names the months, `:gregorian` by default.

### Returns

* `{:ok, module}` where `module` is the calendar module that
  conforms to the `Calendar` and `Calendrical` behaviours. The
  call is idempotent: if the module already exists it is
  returned unchanged (it is not verified to be a calendar module
  in that case).

* `{:error, exception}` if the options are not valid, or a
  `Calendrical.InvalidOptionValueError` if `calendar_type` is neither
  `:month` nor `:week`.

### Examples

The [ISO week calendar](https://en.wikipedia.org/wiki/ISO_week_date)
is a calendar of weeks whose year begins on the Monday on or before
4 January:

    iex> {:ok, calendar} =
    ...>   Calendrical.new(MyISOWeek, :week, year_begins: {:monday, :on_or_before, {1, 4}})
    iex> calendar.date_from_iso_days(Date.to_gregorian_days(~D[2026-01-01]))
    {2026, 1, 4}

A fiscal year beginning in October, numbered by the year it ends in:

    iex> {:ok, calendar} = Calendrical.new(Fiscal, :month, year_begins: {10, 1})
    iex> calendar.date_from_iso_days(Date.to_gregorian_days(~D[2025-10-01]))
    {2026, 1, 1}

Note that `Calendrical.ISOWeek` is included as part of this
library.

# `next`

```elixir
@spec next(
  date() | Date.Range.t(),
  :year | :quarter | :month | :week | :day,
  Keyword.t()
) ::
  Date.t() | Date.Range.t() | {:error, Exception.t()}
```

Returns the next date or date range for
a date period (year, quarter, month, week
or day).

### Arguments

* `date_or_date_range` is any `t:Calendar.date/0` or
  `t:Date.Range.t/0`.

* `period` is `:year`, `:quarter`, `:month`,
  `:week` or `:day`.

* `options` is a keyword list of options.

### Options

* No options are currently defined. The argument is reserved
  and ignored.

### Returns

When a `t:Calendar.date/0` is passed, a `t:Calendar.date/0` is
returned.  When a `t:Date.Range.t/0` is passed
a `t:Date.Range.t/0` is returned.

### Examples

    iex> Calendrical.next(~D[2019-01-01], :day)
    ~D[2019-01-02]

    iex> Calendrical.next(~D[2019-01-01], :month)
    ~D[2019-02-01]

    iex> Calendrical.next(~D[2019-01-01], :quarter)
    ~D[2019-04-01]

    iex> Calendrical.next(~D[2019-01-01], :year)
    ~D[2020-01-01]

# `parse`

```elixir
@spec parse(String.t(), Keyword.t()) ::
  {:ok,
   Date.t()
   | Time.t()
   | NaiveDateTime.t()
   | DateTime.t()
   | Date.Range.t()
   | map()
   | {map(), map()}}
  | {:error, Exception.t()}
```

Parses a locale-formatted string as a date, time, datetime, or date range —
whichever matches. Delegates to `Localize.DateTime.Parser.parse/2`.

Useful when the input shape is not known up-front (e.g. a single
text field that may carry any of `"2026-05-16"`,
`"14:30"`, `"May 16, 2026 2:30 PM"`, or
`"May 5 – May 10, 2026"`). The caller pattern-matches on the
returned struct to discover which kind of value was parsed.

Sub-parsers are tried in this order:

1. **Interval** (only when an interval-shaped separator is
   present) — `Calendrical.Date.parse_range/2`.

2. **Date** — `Calendrical.Date.parse/2`.

3. **Time** — `Calendrical.Time.parse/2`.

4. **DateTime** — `Calendrical.DateTime.parse/2`.

The first sub-parser to return `{:ok, _}` wins; the order runs
from the most to the least structurally distinctive input shape.

### Arguments

* `input` is the raw user input string.

* `options` is a keyword list of options.

### Options

Forwarded to each sub-parser. Notable keys:

* `:locale` — the locale to interpret the string under.
  Defaults to `Localize.get_locale/0`.

* `:calendar` — the calendar module the input is read in and the result is returned in, such as `Calendar.ISO` (the default) or `Calendrical.Hebrew`. A CLDR calendar name such as `:hebrew` returns `Localize.UnknownCalendarError`.

* `:reference_date` — the "today" anchor for two-digit-year
  pivoting and partial-date inheritance.

* `:allow_inverted` — applies to interval parsing only.

* `:as` — `:struct` (default) returns the appropriate
  struct (`Date`, `Time`, `NaiveDateTime`, `DateTime`, or
  `Date.Range`). `:map` returns a bare field map
  containing only what the input actually supplied — useful
  when a downstream library needs the unresolved partial
  rather than a struct with synthesised defaults. See the
  individual `Calendrical.Date.parse/2`,
  `Calendrical.Time.parse/2`, and
  `Calendrical.DateTime.parse/2` docs for the map shapes.

### Returns

* `{:ok, value}` where `value` is one of `t:Date.t/0`,
  `t:Time.t/0`, `t:NaiveDateTime.t/0`, `t:DateTime.t/0`, or
  `t:Date.Range.t/0` (struct mode), or a field map / a
  `{from_map, to_map}` tuple (map mode).

* `{:error, Localize.DateTimeParseError.t()}` when every sub-parser
  failed. The exception's `:attempts` field carries the
  `{kind, exception}` pairs from each attempt, in order.

* `{:error, Localize.InvalidValueError.t()}` when `input` is not a string or an option is malformed.

* `{:error, %Calendrical.RemovedOptionError{}}` for the
  `:return_calendar` option, which was removed in 2.0.

### Examples

    iex> Calendrical.parse("2026-05-16", locale: :en)
    {:ok, ~D[2026-05-16]}

    iex> Calendrical.parse("14:30", locale: :en)
    {:ok, ~T[14:30:00]}

    iex> Calendrical.parse("2026-05-16T14:30:00", locale: :en)
    {:ok, ~N[2026-05-16 14:30:00]}

    iex> {:ok, range} = Calendrical.parse("2026-05-05 – 2026-05-10", locale: :en)
    iex> {range.first, range.last}
    {~D[2026-05-05], ~D[2026-05-10]}

    iex> Calendrical.parse("May 5", locale: :en, as: :map)
    {:ok, %{calendar: Calendar.ISO, month: 5, day: 5}}

    iex> Calendrical.parse("11 am", locale: :en, as: :map)
    {:ok, %{hour: 11}}

# `previous`

```elixir
@spec previous(
  date() | Date.Range.t(),
  :year | :quarter | :month | :week | :day,
  Keyword.t()
) ::
  Date.t() | Date.Range.t() | {:error, Exception.t()}
```

Returns the previous date or date range for
a date period (year, quarter, month, week
or day).

### Arguments

* `date_or_date_range` is any `t:Calendar.date/0` or
  `t:Date.Range.t/0`.

* `period` is `:year`, `:quarter`, `:month`,
  `:week` or `:day`.

* `options` is a `t:Keyword.t/0` list of options.

### Options

* No options are currently defined. The argument is reserved
  and ignored.

### Returns

When a `t:Calendar.date/0` is passed, a `t:Calendar.date/0` is
returned.  When a `t:Date.Range.t/0` is passed
a `t:Date.Range.t/0` is returned.

### Examples

    iex> Calendrical.previous(~D[2019-01-01], :day)
    ~D[2018-12-31]

    iex> Calendrical.previous(~D[2019-01-01], :quarter)
    ~D[2018-10-01]

    iex> Calendrical.previous(~D[2019-01-01], :month)
    ~D[2018-12-01]

    iex> Calendrical.previous(~D[2019-01-01], :year)
    ~D[2018-01-01]

# `quarter_of_year`

```elixir
@spec quarter_of_year(date()) :: quarter() | date_error()
```

Returns the `quarter` number for
a `date`.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or
  more of the fields `:year`, `:month`, `:day` and
  optionally `:calendar`.

### Returns

* The quarter of the year as an integer.

### Examples

    iex> Calendrical.quarter_of_year(~D[2019-01-01])
    1

    iex> Calendrical.quarter_of_year(Calendrical.first_day_of_year(2019, Calendrical.NRF))
    1

    iex> Calendrical.quarter_of_year(Calendrical.last_day_of_year(2019, Calendrical.NRF))
    4

# `quarters`

```elixir
@spec quarters(Localize.LanguageTag.t() | String.t() | atom(), atom()) ::
  {:ok, map()} | {:error, Exception.t()}
```

Returns the quarter name data for a locale and calendar type.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* `calendar` is a calendar type atom. The default is `:gregorian`.

### Returns

* `{:ok, map}` where the map holds the quarter name data.

* `{:error, exception}` if the locale has no quarter name data
  for the calendar.

### Examples

    iex> {:ok, quarters} = Calendrical.quarters(:en, :gregorian)
    iex> quarters.format.wide[1]
    "1st quarter"

# `related_gregorian_year`

```elixir
@spec related_gregorian_year(date()) :: Calendar.year() | date_error()
```

Returns the related gregorian `year`
number for a `date`.

A related gregorian year is the gregorian
year that is most closely associated with a
date that is in another calendar.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or
  more of the fields `:year`, `:month`, `:day` and
  optionally `:calendar`.

### Returns

* the related gregorian year as an
  integer.

### Examples

    iex> Calendrical.related_gregorian_year ~D[2019-01-01]
    2019

    iex> Calendrical.related_gregorian_year(Calendrical.first_day_of_year(2019, Calendrical.NRF))
    2019

    iex> Calendrical.related_gregorian_year(Calendrical.last_day_of_year(2019, Calendrical.NRF))
    2019

# `saturday`

```elixir
@spec saturday() :: 6
```

Returns the cardinal day number representing
Saturday.

### Returns

* `6`.

### Examples

    iex> Calendrical.saturday()
    6

# `strftime`

```elixir
@spec strftime(any_date_time(), String.t(), Keyword.t()) ::
  {:ok, String.t()} | {:error, Exception.t()}
```

Formats a date, time or datetime with `Calendar.strftime/3`, naming its
month, day of the week and day period in a locale.

The month and the day of the week are named from the date, as
`Localize.Calendar.localize/3` names them, not from its fields: a
Hebrew month by its year, a Chinese leap month as a leap month, a
fiscal calendar's month by the month of the year it is, a calendar of
weeks' week by the month it falls in, and the day by the day it is,
whichever day the calendar's weeks begin on.

See `Calendar.strftime/3` for the format string.

### Arguments

* `value` is a `t:Date.t/0`, `t:Time.t/0`, `t:NaiveDateTime.t/0` or
  `t:DateTime.t/0` in any calendar.

* `format` is a `Calendar.strftime/3` format string.

* `options` is a keyword list of options.

### Options

* `:locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* Every option of `Calendar.strftime/3` (`:preferred_date`,
  `:preferred_time`, `:preferred_datetime`, `:month_names` and the
  other name callbacks). A name callback given here replaces the
  localized one.

### Returns

* `{:ok, string}`, or

* `{:error, exception}` if the locale is not valid, or `value`,
  `format` or an option cannot be formatted, or a name the format
  needs cannot be found for `value`.

### Examples

    iex> {:ok, israel} = Calendrical.calendar_for_territory(:IL)
    iex> Calendrical.strftime(Date.convert!(~D[2025-01-26], israel), "%a", locale: :he)
    {:ok, "יום א׳"}

    iex> Calendrical.strftime(Date.new!(5779, 7, 1, Calendrical.Hebrew), "%A %B", locale: :en)
    {:ok, "Friday Adar II"}

    iex> Calendrical.strftime(~D[2019-11-03], "%x", locale: :fr, preferred_date: "%A %d %B %Y")
    {:ok, "dimanche 03 novembre 2019"}

# `strftime!`

```elixir
@spec strftime!(any_date_time(), String.t(), Keyword.t()) :: String.t()
```

Formats a date, time or datetime with `Calendar.strftime/3`, naming its
month, day of the week and day period in a locale, or raises.

### Arguments

* `value` is a `t:Date.t/0`, `t:Time.t/0`, `t:NaiveDateTime.t/0` or
  `t:DateTime.t/0` in any calendar.

* `format` is a `Calendar.strftime/3` format string.

* `options` is a keyword list of options.

### Options

* The options of `strftime/3`.

### Returns

* The formatted string, or

* raises the exception `strftime/3` returns.

### Examples

    iex> {:ok, israel} = Calendrical.calendar_for_territory(:IL)
    iex> Calendrical.strftime!(Date.convert!(~D[2025-01-26], israel), "%A", locale: :en)
    "Sunday"

# `strftime_options!`

```elixir
@spec strftime_options!(Keyword.t()) :: Keyword.t()
```

Returns a keyword list of options than can be applied to
`Calendar.strftime/3`.

`strftime_options!` returns a keyword list than can be used as
options to return localised names for days, months and am/pm.

`Calendar.strftime/3` passes the name callbacks the month field and
the calendar's own number for the day of the week, so these options
name them by those numbers. That is right for a calendar whose month
field is the CLDR month and whose weeks begin on Monday, and wrong
for the Hebrew and lunisolar calendars, fiscal and week calendars,
and calendars whose weeks begin on another day. `strftime/3` names
the month and the day from the date and is right for every calendar.

### Arguments

* `options` is a keyword list of options. The default is `[]`.

### Options

* `:locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

* `:calendar` is the name of any known calendar. The default
  is `Calendrical.Gregorian`.

### Returns

* A keyword list of the functions `Calendar.strftime/3` takes for
  `:am_pm_names`, `:month_names`, `:abbreviated_month_names`,
  `:day_of_week_names` and `:abbreviated_day_of_week_names`.

Raises an exception if the locale or calendar is not known.

### Examples

    iex> options = Calendrical.strftime_options!(locale: "en")
    iex> Keyword.keys(options)
    [:am_pm_names, :month_names, :abbreviated_month_names, :day_of_week_names, :abbreviated_day_of_week_names]

    iex> Calendar.strftime(~D[2025-01-26], "%a",
    ...>   Calendrical.strftime_options!(locale: "en"))
    "Sun"

# `sunday`

```elixir
@spec sunday() :: 7
```

Returns the cardinal day number representing
Sunday.

### Returns

* `7`.

### Examples

    iex> Calendrical.sunday()
    7

# `supported_cldr_calendar_types`

```elixir
@spec supported_cldr_calendar_types() :: [atom(), ...]
```

Returns the list of CLDR calendar types supported by
Calendrical.

The returned types are the names recognised by
`Localize.validate_calendar/1` and are the valid
inputs to `calendar_from_cldr_calendar_type/1`.

### Returns

* A list of CLDR calendar type atoms.

### Examples

    iex> calendars = Calendrical.supported_cldr_calendar_types()
    iex> :gregorian in calendars and :persian in calendars and :hebrew in calendars
    true

# `thursday`

```elixir
@spec thursday() :: 4
```

Returns the cardinal day number representing
Thursday.

### Returns

* `4`.

### Examples

    iex> Calendrical.thursday()
    4

# `traditional_months`

```elixir
@spec traditional_months(date()) :: [traditional_month()]
```

Returns a year's months in order, named traditionally, with any
leap month among them.

For a lunisolar calendar the list is the year's traditional months
in the order the year holds them, with the leap month as
`{month, :leap}` after the month it follows. For every other
calendar the months are their own numbering, so the list is simply
`1` up to the year's month count. The nth element of the list names
the year's nth ordinal month — the month a date of the calendar
carries.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or more of
  the fields `:year`, `:month`, `:day` and optionally `:calendar`.

### Returns

* A list of `t:traditional_month/0` in time order.

### Examples

    iex> Calendrical.traditional_months(Date.new!(4660, 1, 1, Calendrical.Chinese))
    [1, 2, {2, :leap}, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

    iex> Calendrical.traditional_months(~D[2026-01-01])
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

# `traditional_months`

```elixir
@spec traditional_months(Calendar.year(), calendar()) :: [traditional_month()]
```

Returns a year's months in order, named traditionally, with any
leap month among them.

This is `traditional_months/1` with the year and calendar supplied
directly; use this arity when the calendar is chosen at runtime.

### Arguments

* `year` is any year in `calendar`.

* `calendar` is a module implementing the `Calendrical` behaviour.

### Returns

* A list of `t:traditional_month/0` in time order.

### Examples

    # The Hebrew year 5784 is a leap year: Adar I follows the
    # fifth traditional month
    iex> Calendrical.traditional_months(5784, Calendrical.Hebrew)
    [1, 2, 3, 4, 5, {5, :leap}, 6, 7, 8, 9, 10, 11, 12]

    iex> Calendrical.traditional_months(5785, Calendrical.Hebrew)
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

    iex> Calendrical.traditional_months(2026, Calendrical.Gregorian)
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

# `tuesday`

```elixir
@spec tuesday() :: 2
```

Returns the cardinal day number representing
Tuesday.

### Returns

* `2`.

### Examples

    iex> Calendrical.tuesday()
    2

# `validate_calendar`

```elixir
@spec validate_calendar(term()) :: {:ok, calendar()} | {:error, Exception.t()}
```

Validates if the argument is a Calendrical
calendar module.

A calendar is a module that implements Elixir's `Calendar` behaviour
and the `Calendrical` behaviour (see `calendar_module?/1`). If the
calendar is `Calendar.ISO`, which implements `Calendar` alone, then
the validated calendar is returned as `Calendrical.Gregorian`.

### Arguments

* `calendar_module` is a module that implements the `Calendar`
  and `Calendrical` behaviours.

### Returns

* `{:ok, calendar_module}` or

* `{:error, exception}` where `exception` is an exception struct.

### Examples

    iex> Calendrical.validate_calendar(Calendrical.Gregorian)
    {:ok, Calendrical.Gregorian}

    iex> Calendrical.validate_calendar(Calendar.ISO)
    {:ok, Calendrical.Gregorian}

    iex> {:error, %Calendrical.InvalidCalendarModuleError{module: :not_a_calendar}} =
    ...>   Calendrical.validate_calendar(:not_a_calendar)

# `wednesday`

```elixir
@spec wednesday() :: 3
```

Returns the cardinal day number representing
Wednesday.

### Returns

* `3`.

### Examples

    iex> Calendrical.wednesday()
    3

# `week_of_month`

```elixir
@spec week_of_month(date()) :: {Calendar.month(), week()} | date_error()
```

Returns the `{month, week_number}` for a `date`: the month the date's week belongs to and the week's number in it.

The weeks are the calendar's own, so a day near the end of a month can be in the next month's first week. `Calendar.ISO` dates are counted in `Calendrical.Gregorian`, whose weeks begin on Monday and whose week 1 of a month is the week holding the month's first day, so Monday 31 December 2018 is in week 1 of January 2019. `Calendrical.ISO` keeps ISO 8601's rule, under which a week belongs to the month holding four or more of its days.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or more of the fields `:year`, `:month`, `:day` and optionally `:calendar`.

### Returns

* a tuple of the form `{month, week}`, or

* `{:error, exception}` if the date is missing a field.

### Examples

    iex> Calendrical.week_of_month(~D[2019-01-01])
    {1, 1}
    iex> Calendrical.week_of_month(~D[2018-12-31])
    {1, 1}
    iex> Calendrical.week_of_month(~D[2021-10-01 Calendrical.ISO])
    {9, 5}
    iex> {:ok, weeks_from_first_day} = Calendrical.new(MyApp.WeeksFromFirstDay, :month, weeks: :from_first_day)
    iex> Calendrical.week_of_month(Date.convert!(~D[2019-01-01], weeks_from_first_day))
    {1, 1}
    iex> Calendrical.week_of_month(Date.convert!(~D[2018-12-31], weeks_from_first_day))
    {12, 5}
    iex> Calendrical.week_of_month(~D[2018-12-31 Calendrical.Julian])
    {12, 5}

# `week_of_year`

```elixir
@spec week_of_year(date()) :: {Calendar.year(), week()} | date_error()
```

Returns the `{year, week_number}`
for a `date`.

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or
  more of the fields `:year`, `:month`, `:day` and
  optionally `:calendar`.

### Returns

* a the week of the year as an
  integer or

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

### Examples

    iex> Calendrical.week_of_year(~D[2019-01-01])
    {2019, 1}
    iex> Calendrical.week_of_year(~D[2019-12-01])
    {2019, 48}
    iex> Calendrical.week_of_year(~D[2019-W52-1 Calendrical.NRF])
    {2019, 52}
    iex> Calendrical.week_of_year(~D[2019-W26-1 Calendrical.NRF])
    {2019, 26}
    iex> Calendrical.week_of_year(~D[2019-12-01 Calendrical.Julian])
    {2019, 48}

# `weekday?`

```elixir
@spec weekday?(date(), Keyword.t()) :: boolean() | {:error, Exception.t()}
```

Returns whether a given date is a weekday.

Weekdays are locale-specific and depend on
the policies of a given territory (region, country).

### Arguments

* `date` is any `t:Calendar.date/0`.

* `options` is a `t:Keyword.t/0` list of options.

### Options

* `:locale` is any locale or locale name validated
  by `Localize.validate_locale/1`.  The default is
  `Localize.get_locale/0` which returns the locale
  set for the current process.

* `:territory` is any valid ISO-3166-2 territory
  that is validated by `Localize.validate_territory/1`.

### Notes

When identifying which territory context within which
to determine whether a given day is a weekday or not
the following order applies:

* A territory specified by the `:territory` option.

* The territory defined as part of the `:locale` option.

* The territory defined as part of the current processes
  default locale.

### Returns

* `true` if the date is a weekday day in the territory, otherwise
  `false`.

* `{:error, exception}` if the locale or territory is not known.

### Examples

    # The default locale is `en-001` for which
    # the territory is `001` (the world). The weekdays
    # for `001` are Monday to Friday
    iex> Calendrical.weekday?(~D[2019-03-23], locale: :en)
    false

    iex> Calendrical.weekday?(~D[2019-03-23], territory: "IS")
    false

    # Saturday is a weekday in India
    iex> Calendrical.weekday?(~D[2019-03-23], locale: :"en-IN")
    true

    # Friday is not a weekday in Saudi Arabia
    iex> Calendrical.weekday?(~D[2019-03-22], locale: :"ar-SA")
    false

    # Friday is not a weekday in Israel
    iex> Calendrical.weekday?(~D[2019-03-22], locale: :he)
    false

    iex> {:ok, israel} = Calendrical.calendar_for_territory(:IL)
    iex> Calendrical.weekday?(Date.convert!(~D[2019-03-22], israel), locale: :he)
    false

# `weekdays`

```elixir
@spec weekdays(atom() | String.t()) :: [day_of_week()] | {:error, Exception.t()}
```

Returns a list of the days of the week that
are considered a weekend for a given
territory (country).

### Arguments

* `territory` is any valid ISO3166-2 code.

### Returns

* A list of integers representing the days of
  the week that are week days. Here `1` means
  `Monday` and `7` means `Sunday`.

### Notes

The list of days may not be monotonic. See
the example for Saudi Arabia below.

### Examples

    iex> Calendrical.weekdays("US")
    [1, 2, 3, 4, 5]

    iex> Calendrical.weekdays("IN")
    [1, 2, 3, 4, 5, 6]

    iex> Calendrical.weekdays("SA")
    [1, 2, 3, 4, 7]

    iex> {:error, %Localize.UnknownTerritoryError{}} = Calendrical.weekdays("yy")

# `weekend`

```elixir
@spec weekend(atom() | String.t()) :: [day_of_week()] | {:error, Exception.t()}
```

Returns a list of the days of the week that
are considered a weekend for a given
territory (region, country).

### Arguments

* `territory` is any valid ISO3166-2 code.

### Returns

* A list of integers representing the days of
  the week that are weekend days. Here `1` means
  `Monday` and `7` means `Sunday`.

### Examples

    iex> Calendrical.weekend("US")
    [6, 7]

    iex> Calendrical.weekend("IN")
    [7]

    iex> Calendrical.weekend("SA")
    [5, 6]

    iex> {:error, %Localize.UnknownTerritoryError{}} = Calendrical.weekend("yy")

# `weekend?`

```elixir
@spec weekend?(date(), Keyword.t()) :: boolean() | {:error, Exception.t()}
```

Returns whether a given date is a weekend day.

Weekend days are locale-specific and depend on
the policies of a given territory (country).

### Arguments

* `date` is any `t:Calendar.date/0`.

* `options` is a `t:Keyword.t/0` list of options.

### Options

* `:locale` is any locale or locale name validated
  by `Localize.validate_locale/1`.  The default is
  `Localize.get_locale/0` which returns the locale
  set for the current process.

* `:territory` is any valid ISO-3166-2 territory
  that is validated by `Localize.validate_territory/1`.

### Notes

When identifying which territory context within which
to determine whether a given day is a weekend or not
the following order applies:

* A territory specified by the `:territory` option.

* The territory defined as part of the `:locale` option.

* The territory defined as part of the current processes
  default locale.

### Returns

* `true` if the date is a weekend day in the territory, otherwise
  `false`.

* `{:error, exception}` if the locale or territory is not known.

### Examples

    # The default locale is `en-001` for which
    # the territory is `001` (the world). The weekend
    # for `001` is Saturday and Sunday
    iex> Calendrical.weekend? ~D[2019-03-23]
    true

    iex> Calendrical.weekend?(~D[2019-03-23], locale: :en)
    true

    iex> Calendrical.weekend?(~D[2019-03-23], territory: "IS")
    true

    # In India the official weekend is only Sunday
    iex> Calendrical.weekend?(~D[2019-03-23], locale: "en-IN")
    false

    # In Israel the weekend starts on Friday
    iex> Calendrical.weekend?(~D[2019-03-22], locale: :he)
    true

    iex> {:ok, israel} = Calendrical.calendar_for_territory(:IL)
    iex> Calendrical.weekend?(Date.convert!(~D[2019-03-22], israel), locale: :he)
    true

    # As it also does in Saudia Arabia
    iex> Calendrical.weekend?(~D[2019-03-22], locale: :"ar-SA")
    true

    # Sunday is not a weekend day in Saudi Arabia
    iex> Calendrical.weekend?(~D[2019-03-24], locale: :"ar-SA")
    false

# `weeks_in_year`

```elixir
@spec weeks_in_year(date()) :: pos_integer() | {:error, Exception.t()}
```

Returns the number of weeks in a year.

### Arguments

* `date` is any `t:Calendar.date/0` or an integer year
  or a map with one or more of the fields `:year`,
  `:month`, `:day` and optionally `:calendar`.

### Returns

* The number of weeks in the year, as `Calendrical.Week.weeks_in_year/2`
  counts them: whole weeks, week 1 holding at least the fewest days of
  the year the calendar's `info/0` states, or

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

### Examples

    # A Calendar.ISO date is handled by the default
    # Calendrical.Gregorian calendar: Monday-start weeks
    # with a one-day minimum first week (not ISO 8601 week
    # numbering — use Calendrical.ISO for that). The number
    # of weeks in a year is either 52 or 53 with each week
    # being 7 days. The first week may start in the Gregorian
    # year prior and end in the following Gregorian year.

    iex> Calendrical.weeks_in_year(~D[2022-01-01])
    52

    iex> Calendrical.weeks_in_year(~D[2023-01-01])
    53

    # For week calculations, the Calendrical.ISO and Calendrical.ISOWeek
    # have the same definition.

    iex> Calendrical.weeks_in_year(2023, Calendrical.ISO)
    52

    iex> Calendrical.weeks_in_year(2020, Calendrical.ISOWeek)
    53

    iex> Calendrical.weeks_in_year(~D[2026-W01-1 Calendrical.ISOWeek])
    53

    # A calendar whose weeks start on the first day of the year
    # has a short last week, its 53rd.

    iex> {:ok, weeks_from_first_day} = Calendrical.new(MyApp.WeeksFromFirstDay, :month, weeks: :from_first_day)
    iex> weeks_from_first_day.weeks_in_year(2023)
    53
    iex> weeks_from_first_day.weeks_in_year(2020)
    53

# `weeks_in_year`

```elixir
@spec weeks_in_year(year(), calendar()) :: pos_integer() | date_error()
```

Returns the number of weeks in a `year` for
a `calendar`.

### Arguments

* `year` is any integer year number.

* `calendar` is any module that implements the `Calendar` and
  `Calendrical` behaviours or `Calendar.ISO`. `Calendar.ISO` is
  treated as the default `Calendrical.Gregorian` calendar —
  Monday-start weeks with a one-day minimum first week — the
  same convention applied to `Calendar.ISO` dates throughout
  Calendrical, not ISO 8601 week numbering. For ISO 8601 weeks
  (four-day minimum first week) use `Calendrical.ISO` or
  `Calendrical.ISOWeek`.

### Returns

* The number of weeks in the year, or

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

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

### Examples

    iex> Calendrical.weeks_in_year(2023, Calendar.ISO)
    53

    # ISO 8601 week numbering gives 52 weeks for 2023.

    iex> Calendrical.weeks_in_year(2023, Calendrical.ISO)
    52

    iex> Calendrical.weeks_in_year(2020, Calendrical.ISOWeek)
    53

# `weeks_to_days`

```elixir
@spec weeks_to_days(number()) :: integer()
```

Returns the number of whole days in `n` weeks.

A fractional number of weeks is truncated toward zero to whole
days: one and a half weeks is 10 days.

### Arguments

* `n` is a number of weeks, an integer or a float.

### Returns

* The number of whole days in `n` weeks, as an integer.

### Examples

    iex> Calendrical.weeks_to_days(2)
    14

    iex> Calendrical.weeks_to_days(1.5)
    10

# `year_of_era`

```elixir
@spec year_of_era(date()) :: {Calendar.day(), Calendar.era()} | date_error()
```

Returns the `{year_of_era, era}` for
a `date`.

*This function differs slightly
from `Date.year_of_era/1`. See the notes
below*

### Arguments

* `date` is any `t:Calendar.date/0` or a map with one or
  more of the fields `:year`, `:month`, `:day` and
  optionally `:calendar`.

### Returns

* a the year since the start of the era and
  the era of the year as a tuple.

### Notes

1. Unlike `Date.year_of_era/1`, this function supports
  eras that change part way through the calendar
  year. This is common in the Japanese calendar where
  the eras change when a new emperor is ordained which
  can happen at any time of year. Therefore this
  function is consistent with `Date.year_of_era/1` for
  the Gregorian and related calendars, but returns a
  different (and more accurate) result for the Japanese
  calendar.

2. This is also true for fiscal year calendars that
  start on a day other than January 1st. The year of
  era will depend on whether the calendar was configured
  with `year: :beginning`, `year: :ending` or `year: :majority`.

### Examples

    iex> Calendrical.year_of_era(~D[2019-01-01])
    {2019, 1}

    iex> Calendrical.year_of_era(Calendrical.first_day_of_year(2019, Calendrical.NRF))
    {2019, 1}

    iex> Calendrical.year_of_era(Calendrical.last_day_of_year(2019, Calendrical.NRF))
    {2019, 1}

---

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