Module:Calendar/adirni
Jump to navigation
Jump to search
Documentation for this module may be created at Module:Calendar/adirni/doc
-- if editing this file to fix an error, please keep the maximum line length to
-- strictly 80 characters, even in comments; I edit on small terminals often
local calendar = {}
local equinoxes = require "Module:Calendar/data/equinox_northwards"
local weekdays = { [0] = 1, 2, 3, 4, 5, 6, 7, 1 }
-- 1/1/63374 was on odumso; this is pretty much arbitrary
local month_names = {
en = { 'Rebirth', 'Blooming', 'Rains', 'Storms', 'Mist',
'Drying', 'Gathering', 'Grazing', 'Breezes', 'Freezing',
'Darkness', 'Antlers', 'Lanterns', 'Unveiling' },
ad_latin = { '1', 'Ḑekḑiņț', '-ré', '-ré', '-ré',
'6', '7', '8', '-ré', '10',
'Sorénta', '–ré', '-ré', '14' }
}
local day_names = {
en = {
long = { 'Odumso', 'Dénéso', 'Koșțîșo', 'Malîso', 'Mahnés', 'Heņșîșo',
'Ursnés' },
short = { '1ᵒ', '2ᵒ', '3ᵒ', '4ᵒ', '5ˢ', '6ᵒ', '7ˢ' }
},
ad_latin = {
long = { 'Odumso', 'Dénéso', 'Koșțîșo', 'Malîso', 'Mahnés', 'Heņșîșo',
'Ursnés' },
short = { 'I', 'De', 'Ko', 'Na', 'Ma', 'He', 'U' }
}
}
local function equinox_date(year)
local datetime = equinoxes[year - 1451]
-- this would be so much easier if it was indexed with the year
if not datetime then
error("northward equinox data for the year " .. year ..
" doesn't exist")
end
assert(datetime.year == year)
return datetime.hour >= 6 and datetime.day or (datetime.day - 1)
end
local function o(n)
-- this exists because %o returns *unsigned* octal, which breaks with negative
-- years (year -1 is outputted as 1777777777777777777777)
-- with the current breadth of equinox data, though, this probably won't be a
-- practical issue
if n >= 0 then
return string.format("%o", n)
else
return string.format("-%o", n)
end
end
local function melting_length(year)
-- 1 Rebirth always occurs on the northwards equinox, so we adjust
-- the length of the month of Melting to make this correspondence true
local gyear = year - 61408 + 1
-- what gregorian year does February happen in?
local gleap = (gyear % 4 == 0 and gyear % 100 ~= 0) or gyear % 400 == 0
local delta = equinox_date(gyear) - equinox_date(gyear - 1)
-- difference between equinox dates
return gleap and 21 + delta or 20 + delta
end
local function year_len(year)
return 345 + melting_length(year)
end
local function month_len(month, year)
if month == 1 or month == 4 or month == 6 or month == 9 or month == 11
or month == 13 then
return 26
elseif month == 2 or month == 3 or month == 5 or month == 7 or month == 8
or month == 10 or month == 12 then
return 27
elseif month == 14 then
return melting_length(year)
else
error(tostring(month) .. "is not a valid Adirni month")
end
end
calendar.from = function(date_info)
assert(date_info.year and date_info.month and date_info.day)
local date = 78
-- we choose the fixed point to be the northwards equinox of 1970,
-- which was 21 March; this is the new year of 63374.
-- 21/03/1970 has datestamp 79, but the equinox time is before 06:00 utc,
-- so the actual date in the Adirni calendar is one day earlier.
if date_info.year >= 63374 then
local y = date_info.year
while y > 63374 do
y = y - 1
date = date + year_len(y)
end
local m = date_info.month
while m > 1 do
m = m - 1
date = date + month_len(m, date_info.year)
end
date = date + date_info.day - 1
else
date = date - (1 + month_len(date_info.month, date_info.year)
- date_info.day)
local m = date_info.month + 1
local y = date_info.year
while m <= 14 do
date = date - month_len(m, y)
m = m + 1
end
while y < 63374 do
date = date - year_len(y)
y = y + 1
end
end
return date
end
calendar.to = function(datestamp)
local dow = weekdays[datestamp % 7]
local y, m, d = 63374, 1, 1
datestamp = datestamp - 78
if datestamp >= 0 then
while datestamp >= year_len(y) do
datestamp = datestamp - year_len(y)
y = y + 1
end
while datestamp >= month_len(m, y) do
datestamp = datestamp - month_len(m, y)
m = m + 1
end
d = d + datestamp
else
y, m, d = 63373, 14, 20
-- the 1969 equinox was on 20/3, while the 1970 equinox was on 21/3
-- but before 06:00, so the year 63373 is the ordinary 365 days long.
datestamp = -(datestamp + 1)
while datestamp >= year_len(y) do
datestamp = datestamp - year_len(y);
y = y - 1
end
while datestamp >= month_len(m, y) do
datestamp = datestamp - month_len(m, y)
m = m - 1
d = month_len(m, y)
end
d = d - datestamp
end
return { year = y, month = m, day = d, weekday = dow }
end
calendar.to_formatted = function(datestamp, opts)
-- en: Ursnés 10 Ḑekḑiņț 63430
-- ad-latin: Ursnés 12 Ḑekḑiņț 173706
-- ad: 12 ... 173706
-- length: "short" is short weekdays, "none" is none, "long" is default
-- todo: implement languages other than english
-- opts = opts or {}
-- opts.lang = opts.lang or "en"
-- opts.length = opts.length or "long"
-- local date = calendar.to(datestamp)
-- local dow = opts.length ~= "none" or
-- day_names[opts.lang][opts.length][date.weekday]
-- local d = opts.
return string.format("%s %s %s %s", dow,
date.day, month_names.en[date.month], date.year)
end
return calendar