# `Calendrical.Week`

The weeks of any calendar, computed once for every calendar from its
kernel.

Every calendar's weeks follow one rule, TR35's: a week is seven days
and begins on the day the calendar's `c:Calendrical.info/0` names
(`info().weeks.first_day`, 1 for Monday to 7 for Sunday); week 1 of a
year is the first week holding at least the fewest days of the year the
same facts state (`info().weeks.min_days_in_first_week`); the days
before week 1 are the last week of the year before, and the days of the
old year inside week 1 are week 1 of the new. A month's weeks are
numbered the same way over the month. A calendar whose weeks are
counted from the year's first day whatever its weekday
(`first_day: :first_day_of_year`) begins week 1 with the year, so its
last week is short.

Every function takes the calendar as its first argument and answers for
every calendar Calendrical builds. The calendar modules carry a
delegation to each for Localize, which reaches a calendar through its
module alone.

# `calendar`

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

A calendar module.

# `date_from_week_date`

```elixir
@spec date_from_week_date(
  calendar(),
  Calendar.year(),
  Calendrical.week(),
  Calendar.day_of_week()
) ::
  Date.t() | {:error, Exception.t()}
```

Returns the date of a day of a week of a week-year: the inverse of
`week_date_from_date/4`.

### Arguments

* `calendar` is a calendar module.

* `week_year` and `week` are a week of the calendar.

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

### Returns

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

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

### Examples

    iex> Calendrical.Week.date_from_week_date(Calendrical.ISOWeek, 2026, 25, 2)
    ~D[2026-06-16 Calendrical.ISOWeek]

    # Week 1 of 5786 begins on the Sunday before 1 Tishri, 28 Elul 5785
    iex> Calendrical.Week.date_from_week_date(Calendrical.Hebrew, 5786, 1, 1)
    ~D[5785-12-28 Calendrical.Hebrew]

# `day_of_week`

```elixir
@spec day_of_week(
  calendar(),
  Calendar.year(),
  Calendar.month(),
  Calendar.day(),
  :default | atom()
) :: {Calendar.day_of_week(), 1, 7} | {:error, Exception.t()}
```

Returns the day of the week of a date, as `c:Calendar.day_of_week/4`
answers it: the day's number from the day weeks begin on, with the first
and the last day of the week.

### Arguments

* `calendar` is a calendar module.

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

* `starting_on` is `:default` for the day the calendar's own weeks begin
  on (`info().weeks.first_day`, or the weekday of the year's first day
  where its weeks are counted from it), or the name of a weekday,
  `:monday` to `:sunday`.

### Returns

* `{day_of_week, 1, 7}`, or `{:error, %Calendrical.InvalidDateError{}}` for a date the
  calendar does not have, or `{:error, Calendrical.MissingFieldsError.t()}`
  for a missing field.

Raises `Calendrical.InvalidOptionValueError` for a `starting_on` that is
neither `:default` nor a weekday, as `Date.day_of_week/2` expects.

### Examples

    iex> Calendrical.Week.day_of_week(Calendrical.Gregorian, 2026, 1, 1, :default)
    {4, 1, 7}

    iex> Calendrical.Week.day_of_week(Calendrical.Gregorian, 2026, 1, 1, :sunday)
    {5, 1, 7}

# `iso_week_of_year`

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

Returns the ISO 8601 week-year and week of the day a date names,
whichever calendar names it: the week of the Gregorian year, from
Monday, holding at least four days of it.

### Arguments

* `calendar` is a calendar module.

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

### Returns

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

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

### Examples

    iex> Calendrical.Week.iso_week_of_year(Calendrical.Hebrew, 5786, 7, 15)
    {2026, 14}

# `week`

```elixir
@spec week(calendar(), Calendar.year(), Calendrical.week()) ::
  Date.Range.t() | {:error, Exception.t()}
```

Returns the days of a week of a year of the calendar.

### Arguments

* `calendar` is a calendar module.

* `year` is a year of the calendar.

* `week` is a week of that year.

### Returns

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

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

### Examples

    iex> Calendrical.Week.week(Calendrical.ISOWeek, 2026, 25)
    Date.range(~D[2026-06-15 Calendrical.ISOWeek], ~D[2026-06-21 Calendrical.ISOWeek])

    iex> Calendrical.Week.week(Calendrical.Gregorian, 2025, 1)
    Date.range(~D[2024-12-30 Calendrical.Gregorian], ~D[2025-01-05 Calendrical.Gregorian])

# `week_date_from_date`

```elixir
@spec week_date_from_date(
  calendar(),
  Calendar.year(),
  Calendar.month(),
  Calendar.day()
) ::
  {Calendar.year(), Calendrical.week(), Calendar.day_of_week()}
  | {:error, Exception.t()}
```

Returns the week-year, the week and the day of the week of a date.

### Arguments

* `calendar` is a calendar module.

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

### Returns

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

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

### Examples

    iex> Calendrical.Week.week_date_from_date(Calendrical.ISOWeek, 2026, 6, 16)
    {2026, 25, 2}

# `week_of_month`

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

Returns the month and the week of the month a date is in.

### Arguments

* `calendar` is a calendar module.

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

### Returns

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

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

### Examples

    iex> Calendrical.Week.week_of_month(Calendrical.Gregorian, 2026, 1, 15)
    {1, 3}

    # The week holding 1 February is February's week 1
    iex> Calendrical.Week.week_of_month(Calendrical.Gregorian, 2026, 1, 31)
    {2, 1}

# `week_of_year`

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

Returns the week-year and the week of the year a date is in.

### Arguments

* `calendar` is a calendar module.

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

### Returns

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

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

### Examples

    iex> Calendrical.Week.week_of_year(Calendrical.Gregorian, 2025, 12, 31)
    {2026, 1}

    iex> Calendrical.Week.week_of_year(Calendrical.Hebrew, 5786, 7, 15)
    {5786, 28}

    # 29 Elul 5786 is in week 1 of 5787, which begins on the Sunday before 1 Tishri
    iex> Calendrical.Week.week_of_year(Calendrical.Hebrew, 5786, 12, 29)
    {5787, 1}

# `weeks_in_week_year`

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

Returns the number of weeks in a week-year, as `date_from_week_date/4`
counts them: as many as the year has.

### Arguments

* `calendar` is a calendar module.

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

### Returns

* The number of weeks, or

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

### Examples

    iex> Calendrical.Week.weeks_in_week_year(Calendrical.ISOWeek, 2026)
    53

# `weeks_in_year`

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

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

### Arguments

* `calendar` is a calendar module.

* `year` is a year of the calendar.

### Returns

* The number of weeks, or

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

### Examples

    iex> Calendrical.Week.weeks_in_year(Calendrical.Gregorian, 2026)
    52

    iex> Calendrical.Week.weeks_in_year(Calendrical.ISO, 2026)
    53

    iex> Calendrical.Week.weeks_in_year(Calendrical.Hebrew, 5787)
    55

# `weeks_of_month`

```elixir
@spec weeks_of_month(calendar(), Calendar.year(), Calendar.month()) ::
  [Date.Range.t()] | {:error, Exception.t()}
```

Returns the weeks of a month of a year of the calendar, in order.

### Arguments

* `calendar` is a calendar module.

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

### Returns

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

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

### Examples

    iex> Calendrical.Week.weeks_of_month(Calendrical.Gregorian, 2026, 2) |> length()
    4

    iex> Calendrical.Week.weeks_of_month(Calendrical.Gregorian, 2026, 2) |> hd()
    Date.range(~D[2026-01-26 Calendrical.Gregorian], ~D[2026-02-01 Calendrical.Gregorian])

---

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