Calendrical.Month (Calendrical v2.2.0)

Copy Markdown

The months of any calendar, computed once for every calendar from its kernel: how a month is named and numbered, which months a year has and which days a month has, and the lengths a month can have.

A date's month is its position in the year. A calendar names that position in two ways. Its traditional number is the number the culture gives the month, n, or {n, :leap} for an intercalary month that follows month n: in a Chinese year whose leap month follows month 2, position 3 is {2, :leap} and position 4 is 3, and in a Hebrew leap year position 6, Adar I, is {5, :leap}. It follows from one fact the calendar states, the position of its leap month (Calendrical.leap_month/1). Its CLDR month is the index of its name in the calendar's CLDR data, which is the month a date is written with (Calendrical.written_date/3) in every CLDR calendar but the Hebrew, where CLDR gives Adar I a number of its own, so that from Adar on a month of an ordinary year is named one more than its place.

Every function here takes the calendar as its first argument and answers for every calendar Calendrical builds. The calendar modules carry a delegation to each.

Summary

Types

A calendar module.

The lengths a month can have, by month: a count of days, a range of them, or a list of them (Calendrical.Info.month_lengths/0).

A month as a culture names it: its number, or {number, :leap} for a leap month.

Functions

Returns the CLDR month a month of the year names without a year: the name the month carries in the year that holds 1 January 2000, which is every year's in a calendar whose months are named alike in every year. A Hebrew month is its own number, since which name a place carries there depends on the year.

Returns the CLDR month of a month of a year: the index of its name in the calendar's CLDR data, with {month, :leap} where the name has a leap form.

Returns the days a month of a year has, as runs of their numbers in order.

Returns the number of days a month of the calendar has without a year: a count where the month has as many in every year, and {:ambiguous, range} where its length depends on the year.

Returns the fewest and the most days a month of the calendar has in any year.

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

Returns the lengths the months of the calendar can have, by month: the lengths its Calendrical.info/0 states, or those found by sampling its years, once, over one cycle of its years where it has one and otherwise over thirty years from the year that holds 1 January 2000.

Returns the position in a year of a month the calendar's culture names: the inverse of traditional_month/3.

Returns the months a year has, as runs of their numbers in order.

Returns the fewest and the most months a year of the calendar has.

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

Returns the traditional number of the month a year's leap month follows, or nil where the year has none.

Returns a month of a year as the calendar's culture names it: its traditional number, or {month, :leap} for a leap month.

Returns a year's months in order, as the calendar's culture names them.

Returns the month a CLDR month is written with in a year: the inverse of cldr_month/3 for the figures a date is written with.

Types

calendar()

@type calendar() :: module()

A calendar module.

lengths()

@type lengths() :: Calendrical.Info.month_lengths()

The lengths a month can have, by month: a count of days, a range of them, or a list of them (Calendrical.Info.month_lengths/0).

traditional_month()

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

A month as a culture names it: its number, or {number, :leap} for a leap month.

Functions

cldr_month(calendar, month)

@spec cldr_month(calendar(), Calendar.month()) :: traditional_month()

Returns the CLDR month a month of the year names without a year: the name the month carries in the year that holds 1 January 2000, which is every year's in a calendar whose months are named alike in every year. A Hebrew month is its own number, since which name a place carries there depends on the year.

Arguments

  • calendar is a calendar module.

  • month is a month of the calendar.

Returns

  • A CLDR month number, or the month itself where the calendar has no such month in the reference year.

Examples

iex> {:ok, us} = Calendrical.FiscalYear.calendar_for(:US)
iex> Calendrical.Month.cldr_month(us, 1)
10

iex> Calendrical.Month.cldr_month(Calendrical.Gregorian, 7)
7

cldr_month(calendar, year, month)

@spec cldr_month(calendar(), Calendar.year(), Calendar.month()) ::
  traditional_month() | {:error, Exception.t()}

Returns the CLDR month of a month of a year: the index of its name in the calendar's CLDR data, with {month, :leap} where the name has a leap form.

Arguments

  • calendar is a calendar module.

  • year and month are a month of the calendar.

Returns

  • A CLDR month number, or {month, :leap}, or

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

Examples

# Nisan, the seventh month of an ordinary Hebrew year, is CLDR's month 8
iex> Calendrical.Month.cldr_month(Calendrical.Hebrew, 5786, 7)
8

# The leap month after the second month of a Chinese year
iex> Calendrical.Month.cldr_month(Calendrical.Chinese, 4660, 3)
{2, :leap}

# The first month of a fiscal year that begins in October is named October
iex> {:ok, us} = Calendrical.FiscalYear.calendar_for(:US)
iex> Calendrical.Month.cldr_month(us, 2026, 1)
10

day_numbers(calendar, year, month)

@spec day_numbers(calendar(), Calendar.year(), Calendar.month()) :: [Range.t()]

Returns the days a month of a year has, as runs of their numbers in order.

Arguments

  • calendar is a calendar module.

  • year and month are a month of the calendar.

Returns

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

Examples

iex> Calendrical.Month.day_numbers(Calendrical.Gregorian, 2026, 2)
[1..28]

# England dropped 3 to 13 September 1752
iex> Calendrical.Month.day_numbers(Calendrical.Reform.England, 1752, 9)
[1..2, 14..30]

days_in_month(calendar, month)

@spec days_in_month(calendar(), Calendar.month()) ::
  Calendar.day()
  | {:ambiguous, Range.t() | [Calendar.day(), ...]}
  | {:error, Exception.t()}

Returns the number of days a month of the calendar has without a year: a count where the month has as many in every year, and {:ambiguous, range} where its length depends on the year.

Arguments

  • calendar is a calendar module.

  • month is a month of the calendar.

Returns

  • A count, {:ambiguous, range}, or

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

Examples

iex> Calendrical.Month.days_in_month(Calendrical.Gregorian, 1)
31

iex> Calendrical.Month.days_in_month(Calendrical.Gregorian, 2)
{:ambiguous, 28..29}

days_in_month_bounds(calendar, month)

@spec days_in_month_bounds(calendar(), Calendar.month()) ::
  {Calendar.day(), Calendar.day()} | {:error, Exception.t()}

Returns the fewest and the most days a month of the calendar has in any year.

Arguments

  • calendar is a calendar module.

  • month is a month of the calendar.

Returns

  • {fewest, most}, or

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

Examples

iex> Calendrical.Month.days_in_month_bounds(Calendrical.Gregorian, 2)
{28, 29}

iex> Calendrical.Month.days_in_month_bounds(Calendrical.Reform.England, 9)
{19, 30}

leap_month(calendar, year)

@spec leap_month(calendar(), Calendar.year()) :: Calendar.month() | nil

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

Arguments

  • calendar is a calendar module.

  • year is a year of the calendar.

Returns

  • The leap month's position in the year, or nil.

Examples

iex> Calendrical.Month.leap_month(Calendrical.Hebrew, 5787)
6

iex> Calendrical.Month.leap_month(Calendrical.Hebrew, 5786)
nil

iex> Calendrical.Month.leap_month(Calendrical.Gregorian, 2026)
nil

lengths(calendar)

@spec lengths(calendar()) :: lengths()

Returns the lengths the months of the calendar can have, by month: the lengths its Calendrical.info/0 states, or those found by sampling its years, once, over one cycle of its years where it has one and otherwise over thirty years from the year that holds 1 January 2000.

Arguments

  • calendar is a calendar module.

Returns

Examples

iex> Calendrical.Month.lengths(Calendrical.Hebrew) |> Map.take([1, 2, 4])
%{1 => 30, 2 => 29..30, 4 => 29}

month_from_traditional(calendar, year, traditional_month)

@spec month_from_traditional(calendar(), Calendar.year(), traditional_month()) ::
  Calendar.month() | {:error, Exception.t()}

Returns the position in a year of a month the calendar's culture names: the inverse of traditional_month/3.

Arguments

  • calendar is a calendar module.

  • year is a year of the calendar.

  • traditional_month is a traditional_month/0.

Returns

  • The month's position in the year, or

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

Examples

iex> Calendrical.Month.month_from_traditional(Calendrical.Hebrew, 5787, {5, :leap})
6

iex> Calendrical.Month.month_from_traditional(Calendrical.Hebrew, 5786, 6)
6

month_numbers(calendar, year)

@spec month_numbers(calendar(), Calendar.year()) :: [Range.t()]

Returns the months a year has, as runs of their numbers in order.

Arguments

  • calendar is a calendar module.

  • year is a year of the calendar.

Returns

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

Examples

iex> Calendrical.Month.month_numbers(Calendrical.Hebrew, 5787)
[1..13]

# England's 1751 began on 25 March and ended on 31 December
iex> Calendrical.Month.month_numbers(Calendrical.Reform.England, 1751)
[3..12]

months_in_year_bounds(calendar)

@spec months_in_year_bounds(calendar()) :: {Calendar.month(), Calendar.month()}

Returns the fewest and the most months a year of the calendar has.

Arguments

  • calendar is a calendar module.

Returns

  • {fewest, most}.

Examples

iex> Calendrical.Month.months_in_year_bounds(Calendrical.Hebrew)
{12, 13}

iex> Calendrical.Month.months_in_year_bounds(Calendrical.Reform.England)
{10, 13}

named_month(calendar, year, named_month)

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

Returns the days of a named month of 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.

Arguments

  • calendar is a calendar module.

  • year is a year of the calendar.

  • named_month is the CLDR month that names the month.

Returns

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

Examples

iex> Calendrical.Month.named_month(Calendrical.Julian.March25, 1750, 3) |> length()
2

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

traditional_leap_month(calendar, year)

@spec traditional_leap_month(calendar(), Calendar.year()) :: Calendar.month() | nil

Returns the traditional number of the month a year's leap month follows, or nil where the year has none.

Arguments

  • calendar is a calendar module.

  • year is a year of the calendar.

Returns

  • A month number, or nil.

Examples

iex> Calendrical.Month.traditional_leap_month(Calendrical.Hebrew, 5787)
5

iex> Calendrical.Month.traditional_leap_month(Calendrical.Chinese, 4660)
2

traditional_month(calendar, year, month)

@spec traditional_month(calendar(), Calendar.year(), Calendar.month()) ::
  traditional_month() | {:error, Exception.t()}

Returns a month of a year as the calendar's culture names it: its traditional number, or {month, :leap} for a leap month.

Arguments

  • calendar is a calendar module.

  • year and month are a month of the calendar.

Returns

Examples

# Adar I, the sixth month of the Hebrew leap year 5787, follows Shevat, month 5
iex> Calendrical.Month.traditional_month(Calendrical.Hebrew, 5787, 6)
{5, :leap}

iex> Calendrical.Month.traditional_month(Calendrical.Hebrew, 5787, 7)
6

traditional_months(calendar, year)

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

Returns a year's months in order, as the calendar's culture names them.

Arguments

  • calendar is a calendar module.

  • year is a year of the calendar.

Returns

  • A list of traditional_month/0, the nth naming the year's nth month, and [] for a year the calendar does not have.

Examples

iex> Calendrical.Month.traditional_months(Calendrical.Hebrew, 5787)
[1, 2, 3, 4, 5, {5, :leap}, 6, 7, 8, 9, 10, 11, 12]

written_month_from_cldr_month(calendar, year, cldr_month)

@spec written_month_from_cldr_month(calendar(), Calendar.year(), traditional_month()) ::
  traditional_month() | {:error, Exception.t()}

Returns the month a CLDR month is written with in a year: the inverse of cldr_month/3 for the figures a date is written with.

A month's name and its figure are one number in every calendar but the Hebrew, where CLDR numbers Nisan 8 in every year and a date writes it by its place, 7 in an ordinary year.

Arguments

  • calendar is a calendar module.

  • year is a year of the calendar.

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

Returns

  • The month as Calendrical.written_date/3 writes it, or

  • {:error, %Calendrical.InvalidMonthError{}} where the year has no month of that name.

Examples

iex> Calendrical.Month.written_month_from_cldr_month(Calendrical.Hebrew, 5786, 8)
7

iex> Calendrical.Month.written_month_from_cldr_month(Calendrical.Hebrew, 5787, 8)
8

iex> Calendrical.Month.written_month_from_cldr_month(Calendrical.Chinese, 4660, {2, :leap})
{2, :leap}

iex> Calendrical.Month.written_month_from_cldr_month(Calendrical.Hebrew, 5786, 6)
{:error, %Calendrical.InvalidMonthError{calendar: Calendrical.Hebrew, year: 5786, month: 6}}