# lua-calendrica 0.2 2026-10-13 Lua port of the calendrical algorithms from [Calendrical Calculations (4th edition)](https://www.cambridge.org/9781107683167) by Nachum Dershowitz and Edward M. Reingold. Covers a wide range of calendars including Gregorian, Hebrew, Islamic, Persian, Chinese, Hindu (modern and old), Tibetan, Balinese, Mayan, Julian, Coptic, Ethiopic, French Revolutionary, Icelandic, Akan, Bahá'í, and more, along with astronomical calculations for sunrise, sunset, lunar phases, and solar terms. ## Requirements - Lua 5.3 or later ## Usage ### High-level API #### Dates Dates are immutable value objects, tied to a calendar: a built-in one by name (see `calendrica.calendars()` for the full list), or a calendar object, e.g. one of your own made with `calendrica.calendar{...}`. The built-in names are fixed; nothing is registered under a name, so they cannot clash. ```lua local calendrica = require("calendrica") -- Create a date on one calendar and convert to another local d = calendrica.date({year=2024, month=1, day=1}, "gregorian") print(d) -- gregorian(year=2024, month=1, day=1, rd=738886) -- Convert with date(...) or the :to / :as / :date methods (all equivalent) local h = calendrica.date(d, "hebrew") local h2 = d:to("hebrew") print(h) -- hebrew(year=5784, month=10, day=20, rd=738886) print(h.year, h.month, h.day) -- 5784 10 20 -- Every date exposes .rd (its fixed Rata Die integer) and .calendar (an object) print(d.rd, d.calendar.name) -- 738886 gregorian -- A date can also be built directly from an RD integer (the inverse of .rd) print(calendrica.date(738886, "gregorian")) ``` #### Holidays `holiday` and `holidays` take an optional trailing calendar (name or object) for the returned dates (default `"gregorian"`). ```lua -- Occurrences of a named holiday in a Gregorian year print(calendrica.holiday("shavuot", 2026)[1]) -- gregorian(year=2026, month=5, day=22, rd=739758) -- ...expressed in another calendar (same underlying day) print(calendrica.holiday("shavuot", 2026, "hebrew")[1]) -- hebrew(year=5786, month=3, day=6, rd=739758) -- All holidays in a year, sorted by date for _, hol in ipairs(calendrica.holidays(2026)) do print(hol.name, hol.dates[1]) end ``` #### Astronomy A location takes its time zone in hours from UTC. `sunrise`, `sunset`, `moonrise` and `moonset` return a **moment**: a date object that also carries a time-of-day (`.hour`, `.minute`, `.second`, `.zone`, and the fractional `.moment`). ```lua local jerusalem = calendrica.location(31.78, 35.24, 754, 2) -- lat, lon, elevation (m), UTC+2 print(jerusalem) -- location(latitude=31.78, longitude=35.24, elevation=754, zone=UTC+2) local sr = calendrica.sunrise(d, jerusalem) print(sr) -- gregorian(year=2024, month=1, day=1, rd=738886, 06:33:32 UTC+2) print(sr.hour, sr.minute) -- 6 33 print(sr:to("hebrew")) -- same moment, Hebrew calendar (time preserved) -- These (and lunar_phase) also accept a plain RD integer print(calendrica.sunrise(738886, jerusalem)) print(calendrica.lunar_phase(738886)) -- lunar phase in degrees (0 new, 180 full) -- Dates of a lunar phase across a Gregorian year; optional calendar for the result local full_moons = calendrica.lunar_phases(180, 2026) -- Gregorian local full_moons_hijri = calendrica.lunar_phases(180, 2026, "islamic") ``` ### Low-level API Each calendar is also available as a standalone module: ```lua local gregorian = require("calendrica-gregorian") local hebrew = require("calendrica-hebrew") local fixed = gregorian.fixed_from_gregorian({2024, 1, 1}) local h = hebrew.hebrew_from_fixed(fixed) print(h[1], h[2], h[3]) -- year, month, day ``` The standalone modules sometimes have more functionality, such as leap year predicate. ## Modules Each module name links to its page in the API documentation. | Module | Description | |--------|-------------| | [`calendrica`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica.html) | High-level API: date objects, calendar conversion, calendar objects, holidays | | [`calendrica-akan`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-akan.html) | Akan day-name calendar | | [`calendrica-astro`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-astro.html) | Astronomical calculations (solar, lunar, location) | | [`calendrica-astronomical-lunar`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-astronomical-lunar.html) | Observational lunar calendars (Babylonian, Samaritan, observational Islamic and Hebrew) | | [`calendrica-bahai`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-bahai.html) | Bahá'í calendar (arithmetic and astronomical) | | [`calendrica-balinese`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-balinese.html) | Balinese Pawukon calendar | | [`calendrica-basic`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-basic.html) | Core arithmetic and utility functions | | [`calendrica-chinese`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-chinese.html) | Chinese, Japanese, Korean, and Vietnamese calendars | | [`calendrica-coptic-ethiopic`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-coptic-ethiopic.html) | Coptic and Ethiopic calendars | | [`calendrica-ecclesiastical`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-ecclesiastical.html) | Easter and Christian holidays | | [`calendrica-egyptian-armenian`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-egyptian-armenian.html) | Egyptian and Armenian calendars | | [`calendrica-french-revolutionary`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-french-revolutionary.html) | French Revolutionary calendar | | [`calendrica-gregorian`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-gregorian.html) | Gregorian calendar | | [`calendrica-hebrew`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-hebrew.html) | Hebrew calendar | | [`calendrica-icelandic`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-icelandic.html) | Icelandic calendar | | [`calendrica-islamic`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-islamic.html) | Arithmetic Islamic calendars and tabular variants (TBLA, Umm al-Qura, Turkish/Diyanet) | | [`calendrica-iso`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-iso.html) | ISO week calendar | | [`calendrica-julian`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-julian.html) | Julian calendar and Roman dates | | [`calendrica-mayan`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-mayan.html) | Mayan and Aztec calendars | | [`calendrica-modern-civil`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-modern-civil.html) | Modern civil calendars not in the book: Indian National (reformed Śaka), Minguo/ROC, Thai solar (Buddhist Era), revised Bengali, Nanakshahi, Amazigh (Berber), Japanese era (nengō) | | [`calendrica-modern-hindu`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-modern-hindu.html) | Modern Hindu solar and lunar calendars | | [`calendrica-old-hindu`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-old-hindu.html) | Old Hindu solar and lunar calendars | | [`calendrica-persian`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-persian.html) | Astronomical and arithmetic Persian calendars | | [`calendrica-tibetan`](https://polyglossia.codeberg.page/lua-calendrica/modules/calendrica-tibetan.html) | Tibetan calendar | ## Testing The tests run with [l3build](https://ctan.org/pkg/l3build) in plain LuaTeX and compare the results with values computed by the book's own code, the authors' `calendar.l` (from [calendar-code2](https://github.com/EdReingold/calendar-code2)), with the corrections of the book's errata list applied. These values are not in the repository; compute them first (needs [SBCL](https://www.sbcl.org/) and curl): ```sh l3build reference # writes testfiles/support/reference.lua l3build check ``` `l3build reference` downloads `calendar.l` into `build/` and runs `reference.lisp` on it; run it again only after changing `reference.lisp`. ## Documentation API documentation is available at https://polyglossia.codeberg.page/lua-calendrica/topics/manual.md.html# The site also has Calendars and Holidays pages listing all built-in calendars and holidays. ## Repository - Source code: https://codeberg.org/polyglossia/lua-calendrica - Issue tracker: https://codeberg.org/polyglossia/lua-calendrica/issues ## Maintainer Udi Fogiel ## License The algorithms are ported from CALENDRICA 4.0, which is licensed under the Apache License 2.0. See the source files for details. .