Dayoff.Calendar.Tables (Dayoff v0.2.0)

Copy Markdown View Source

The calendars that ship as lookup tables generated by mix dayoff.sync: Hijri and Hebrew (from the reference parser's own tables), the Chinese, Korean and Vietnamese lunisolar calendars with their solar terms, and the equinox and solstice dates. Each file is decoded once into :persistent_term.

Outside a table's range a lookup returns no dates and logs a warning once, where the reference implementation stays silent.

Summary

Functions

The local calendar date of an equinox or solstice in a timezone, as "MM-DD". Fixed offsets ("+09:00") and the named zones the rules use are precomputed by the sync.

The Gregorian date of a lunar date in the lunar year that starts in the Gregorian year, as the reference date-chinese computes it: a leap month request takes the month after the regular one, and day may run past the month (day 0 is the eve of the month). The table also carries the days where the reference's own round trip through its lunar labeling lands a day off from "day 1 plus the offset" (a handful per year, 2033 among them), so those match too.

The dates of day of month in a mapped calendar that fall in the Gregorian year, the way the reference CalEventMap.inYear finds them: scanning the month's first days in the neighbouring Gregorian years, keeping the ones that land in year, and only the given calendar year when one is asked for. A month can start twice in one Gregorian year.

The Gregorian date of day of solar term term (1 is Lichun at 315°, 5 is Qingming) as solarTerm(term, year) in date-chinese gives it.

Types

lunisolar()

@type lunisolar() :: :chinese | :korean | :vietnamese

mapped()

@type mapped() :: :hijri | :hebrew

Functions

equinox(season, year, timezone)

@spec equinox(:march | :june | :september | :december, integer(), String.t()) ::
  Date.t() | nil

The local calendar date of an equinox or solstice in a timezone, as "MM-DD". Fixed offsets ("+09:00") and the named zones the rules use are precomputed by the sync.

iex> Dayoff.Calendar.Tables.equinox(:march, 2026, "+09:00")
~D[2026-03-20]

iex> Dayoff.Calendar.Tables.equinox(:september, 2026, "America/Santiago")
~D[2026-09-22]

lunar_date(calendar, year, month, leap?, day)

@spec lunar_date(lunisolar(), integer(), 1..12, boolean(), integer()) ::
  Date.t() | nil

The Gregorian date of a lunar date in the lunar year that starts in the Gregorian year, as the reference date-chinese computes it: a leap month request takes the month after the regular one, and day may run past the month (day 0 is the eve of the month). The table also carries the days where the reference's own round trip through its lunar labeling lands a day off from "day 1 plus the offset" (a handful per year, 2033 among them), so those match too.

iex> Dayoff.Calendar.Tables.lunar_date(:chinese, 2026, 1, false, 1)
~D[2026-02-17]

iex> Dayoff.Calendar.Tables.lunar_date(:chinese, 2026, 1, false, 0)
~D[2026-02-16]

mapped_dates(calendar, year, month, day, calendar_year)

@spec mapped_dates(mapped(), integer(), pos_integer(), integer(), integer() | nil) ::
  [Date.t()]

The dates of day of month in a mapped calendar that fall in the Gregorian year, the way the reference CalEventMap.inYear finds them: scanning the month's first days in the neighbouring Gregorian years, keeping the ones that land in year, and only the given calendar year when one is asked for. A month can start twice in one Gregorian year.

iex> Dayoff.Calendar.Tables.mapped_dates(:hijri, 2026, 10, 1, nil)
[~D[2026-03-20]]

iex> Dayoff.Calendar.Tables.mapped_dates(:hebrew, 2026, 13, 14, nil)
[~D[2026-03-03]]

solar_term(calendar, year, term, day)

@spec solar_term(lunisolar(), integer(), 1..24, integer()) :: Date.t() | nil

The Gregorian date of day of solar term term (1 is Lichun at 315°, 5 is Qingming) as solarTerm(term, year) in date-chinese gives it.

iex> Dayoff.Calendar.Tables.solar_term(:chinese, 2026, 5, 1)
~D[2026-04-05]