# `Calendrical.Period`

The periods of a calendar's year, computed for every calendar from its
kernel: the days of a year and of a month, the quarters, quadrimesters
and semesters, the day of the year and the days a year has.

A quarter, quadrimester or semester is a run of 3, 4 or 6 of the twelve
traditional months, each ending where the next begins. A calendar with
leap months places them through `Calendrical.Month.month_from_traditional/3`,
so a leap month falls in the period of the month it repeats (the Hebrew
Adar I in the second quarter, beside Adar II), and a month beyond the
twelfth (the Coptic and Ethiopic epagomenal month) falls in the last
period. Each period spans the calendar's own months, so a week-based
calendar's periods are its months' weeks.

# `calendar`

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

A calendar module.

# `day_of_year`

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

Returns the day of the year of a date: 1 on the first day the year has.

### Arguments

* `calendar` is a calendar module.

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

### Returns

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

### Examples

    iex> Calendrical.Period.day_of_year(Calendrical.Gregorian, 2026, 3, 1)
    60

    # England's 1751 began on 25 March
    iex> Calendrical.Period.day_of_year(Calendrical.Reform.England, 1751, 4, 1)
    8

# `days_in_year`

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

Returns the number of days a year has: the days from its first to its
last, so a year that drops days in a change of calendar counts the days
it has.

### Arguments

* `calendar` is a calendar module.

* `year` is a year of the calendar.

### Returns

* A positive integer, or `{:error, %Calendrical.InvalidDateError{}}` for a year the
  calendar does not have, or `{:error, Calendrical.MissingFieldsError.t()}`
  for no year.

### Examples

    iex> Calendrical.Period.days_in_year(Calendrical.Gregorian, 2024)
    366

    # England dropped eleven days in 1752
    iex> Calendrical.Period.days_in_year(Calendrical.Reform.England, 1752)
    355

# `month`

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

Returns the days of a month of a year as a `t:Date.Range.t/0`: from the
first day the month has to the last.

### Arguments

* `calendar` is a calendar module.

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

### Returns

* A `t:Date.Range.t/0`, or `{:error, %Calendrical.InvalidDateError{}}` for a month the
  year does not have, or `{:error, Calendrical.MissingFieldsError.t()}`
  for a missing year or month.

### Examples

    iex> Calendrical.Period.month(Calendrical.Gregorian, 2026, 2)
    Date.range(~D[2026-02-01 Calendrical.Gregorian], ~D[2026-02-28 Calendrical.Gregorian])

    iex> Calendrical.Period.month(Calendrical.Gregorian, 2026, 13)
    {:error, %Calendrical.InvalidDateError{calendar: Calendrical.Gregorian, value: [year: 2026, month: 13]}}

# `quadrimester`

```elixir
@spec quadrimester(calendar(), Calendar.year(), 1..3) ::
  Date.Range.t() | Calendrical.date_error()
```

Returns the days of a quadrimester of a year, four months each, as a
`t:Date.Range.t/0` (see `quarter/3`).

### Arguments

* `calendar` is a calendar module.

* `year` is a year of the calendar.

* `quadrimester` is 1 to 3.

### Returns

* A `t:Date.Range.t/0`, or `{:error, %Calendrical.InvalidDateError{}}`, or

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

### Examples

    iex> Calendrical.Period.quadrimester(Calendrical.Gregorian, 2026, 3)
    Date.range(~D[2026-09-01 Calendrical.Gregorian], ~D[2026-12-31 Calendrical.Gregorian])

# `quarter`

```elixir
@spec quarter(calendar(), Calendar.year(), 1..4) ::
  Date.Range.t() | Calendrical.date_error()
```

Returns the days of a quarter of a year, three months each, as a
`t:Date.Range.t/0`: a leap month falls in the quarter of the month it
repeats, and a month beyond the twelfth in the last.

### Arguments

* `calendar` is a calendar module.

* `year` is a year of the calendar.

* `quarter` is 1 to 4.

### Returns

* A `t:Date.Range.t/0`, or `{:error, %Calendrical.InvalidDateError{}}` for a quarter or a
  year the calendar does not have, or

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

### Examples

    iex> Calendrical.Period.quarter(Calendrical.Gregorian, 2026, 4)
    Date.range(~D[2026-10-01 Calendrical.Gregorian], ~D[2026-12-31 Calendrical.Gregorian])

# `quarter_of_year`

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

Returns the quarter of the year a date falls in: the quarter of its
month (see `quarter/3`), which needs no day beyond one the month reaches.

### Arguments

* `calendar` is a calendar module.

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

### Returns

* 1 to 4, or `{:error, %Calendrical.InvalidDateError{}}` for a month the year does not
  have, or `{:error, Calendrical.MissingFieldsError.t()}` for a missing
  year or month.

### Examples

    iex> Calendrical.Period.quarter_of_year(Calendrical.Gregorian, 2026, 11, 15)
    4

    iex> Calendrical.Period.quarter_of_year(Calendrical.Hebrew, 5784, 7, 1)
    2

# `semester`

```elixir
@spec semester(calendar(), Calendar.year(), 1..2) ::
  Date.Range.t() | Calendrical.date_error()
```

Returns the days of a semester of a year, six months each, as a
`t:Date.Range.t/0` (see `quarter/3`).

### Arguments

* `calendar` is a calendar module.

* `year` is a year of the calendar.

* `semester` is 1 or 2.

### Returns

* A `t:Date.Range.t/0`, or `{:error, %Calendrical.InvalidDateError{}}`, or

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

### Examples

    iex> Calendrical.Period.semester(Calendrical.Gregorian, 2026, 2)
    Date.range(~D[2026-07-01 Calendrical.Gregorian], ~D[2026-12-31 Calendrical.Gregorian])

# `year`

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

Returns the days of a year as a `t:Date.Range.t/0`: from the first day
the year has to the last, so a composite calendar's year that begins or
ends with a change of calendar is the days it has of its own.

### Arguments

* `calendar` is a calendar module.

* `year` is a year of the calendar.

### Returns

* A `t:Date.Range.t/0`, or `{:error, %Calendrical.InvalidDateError{}}` for a year the
  calendar does not have, or `{:error, Calendrical.MissingFieldsError.t()}`
  for no year.

### Examples

    iex> Calendrical.Period.year(Calendrical.Gregorian, 2026)
    Date.range(~D[2026-01-01 Calendrical.Gregorian], ~D[2026-12-31 Calendrical.Gregorian])

    iex> Calendrical.Period.year(Calendrical.Reform.England, 1751)
    Date.range(~D[1751-03-25 Calendrical.Reform.England], ~D[1751-12-31 Calendrical.Reform.England])

    iex> Calendrical.Period.year(Calendrical.Julian, 0)
    {:error, %Calendrical.InvalidDateError{calendar: Calendrical.Julian, value: [year: 0]}}

---

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