--- Egyptian and Armenian calendar conversions. -- Ported from "Calendrical Calculations" (4th edition) -- by Nachum Dershowitz and Edward M. Reingold. -- Original Lisp code (CALENDRICA 4.0) is Apache 2.0 licensed. -- @module calendrica-egyptian-armenian -- @release 0.1 2026-07-19 local M = {} local basic = require("calendrica-basic") -- === Epochs === -- Fixed date of the Egyptian (Nabonasser) epoch: February 26, 747 BCE (Julian). local EGYPTIAN_EPOCH = basic.fixed_from_jd(1448638) -- Fixed date of the Armenian epoch: July 11, 552 CE (Julian). local ARMENIAN_EPOCH = basic.rd(201443) -- === Egyptian date constructor === -- Egyptian date constructor. local function egyptian_date(year, month, day) return {year, month, day} end -- === Egyptian conversion === --- Fixed date of Egyptian date `e_date`. -- @tparam table e_date Egyptian date {year, month, day}. -- @treturn number Fixed date. function M.fixed_from_egyptian(e_date) local month = basic.standard_month(e_date) local day = basic.standard_day(e_date) local year = basic.standard_year(e_date) return EGYPTIAN_EPOCH -- Days before start of calendar. + 365 * (year - 1) -- Days in prior years. + 30 * (month - 1) -- Days in prior months this year. + day - 1 -- Days so far this month. end local fixed_from_egyptian = M.fixed_from_egyptian -- Alternative fixed date from Egyptian date using sigma. local function alt_fixed_from_egyptian(e_date) -- luacheck: ignore return EGYPTIAN_EPOCH + basic.sigma( { e_date, {365, 30, 1} }, function(e, a) return a * (e - 1) end ) end --- Egyptian date {year, month, day} equivalent to fixed `date`. -- @tparam number date Fixed date. -- @treturn table {year, month, day} function M.egyptian_from_fixed(date) local days = date - EGYPTIAN_EPOCH -- Elapsed days since epoch. local year = 1 + basic.quotient(days, 365) -- Year since epoch. local month = 1 + basic.quotient(days % 365, 30) local day = days - 365 * (year - 1) - 30 * (month - 1) + 1 return egyptian_date(year, month, day) end local egyptian_from_fixed = M.egyptian_from_fixed -- === Armenian date constructor === -- Armenian date constructor. local function armenian_date(year, month, day) -- luacheck: ignore return {year, month, day} end -- === Armenian conversion === --- Fixed date of Armenian date `a_date`. -- Same structure as the Egyptian calendar with a different epoch. -- @tparam table a_date Armenian date {year, month, day}. -- @treturn number Fixed date. function M.fixed_from_armenian(a_date) local month = basic.standard_month(a_date) local day = basic.standard_day(a_date) local year = basic.standard_year(a_date) return ARMENIAN_EPOCH + fixed_from_egyptian(egyptian_date(year, month, day)) - EGYPTIAN_EPOCH end --- Armenian date {year, month, day} equivalent to fixed `date`. -- @tparam number date Fixed date. -- @treturn table {year, month, day} function M.armenian_from_fixed(date) return egyptian_from_fixed(date + EGYPTIAN_EPOCH - ARMENIAN_EPOCH) end return M