Module:Calendar/adirni: Difference between revisions
Jump to navigation
Jump to search
todo: month names |
No edit summary |
||
| (5 intermediate revisions by the same user not shown) | |||
| Line 6: | Line 6: | ||
local equinoxes = require "Module:Calendar/data/equinox_northwards" | local equinoxes = require "Module:Calendar/data/equinox_northwards" | ||
local weekdays = {[0] = 1, 2, 3, 4, 5, 6, 7, 1} | local weekdays = { [0] = 1, 2, 3, 4, 5, 6, 7, 1 } | ||
-- 1/1/63374 was on odumso; this is pretty much arbitrary | -- 1/1/63374 was on odumso; this is pretty much arbitrary | ||
local month_names = { | local month_names = { | ||
en = {'Rebirth', 'Blooming', ' | en = { 'Rebirth', 'Blooming', 'Rains', 'Storms', 'Fog', | ||
' | 'Drying', 'Gathering', 'Grazing', 'Breezes', 'Freezing', | ||
'Darkness', ' | 'Darkness', 'Antlers', 'Lanterns', 'Unveiling' }, | ||
ad_latin = {'1', 'Ḑekḑiņț', ' | ad_latin = { '1', 'Ḑekḑiņț', '-ré', '-ré', '-ré', | ||
'6', '7', '8', '-ré', '10', | |||
'Sorénta', '–ré', '-ré', '14' } | |||
} | } | ||
local day_names = { | local day_names = { | ||
en = {'Odumso', 'Dénéso', 'Koșțîșo', 'Malîso', 'Mahnés', 'Heņșîșo', | en = { | ||
' | long = { 'Odumso', 'Dénéso', 'Koșțîșo', 'Malîso', 'Mahnés', 'Heņșîșo', | ||
ad_latin = {'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 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 | end | ||
local function o(n) | 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 | else | ||
return string.format("-%o", n) | return string.format("-%o", n) | ||
| Line 50: | Line 56: | ||
local function melting_length(year) | 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 | local gyear = year - 61408 + 1 | ||
-- what gregorian year does | -- what gregorian year does February happen in? | ||
local gleap = (gyear % 4 == 0 and gyear % 100 ~= 0) or gyear % 400 == 0 | local gleap = (gyear % 4 == 0 and gyear % 100 ~= 0) or gyear % 400 == 0 | ||
local delta = equinox_date(gyear) - equinox_date(gyear - 1) | local delta = equinox_date(gyear) - equinox_date(gyear - 1) | ||
-- difference between equinox dates | -- difference between equinox dates | ||
return gleap and 21 + delta or 20 + delta | |||
end | end | ||
| Line 64: | Line 73: | ||
local function month_len(month, year) | 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 | end | ||
| Line 93: | Line 104: | ||
while m > 1 do | while m > 1 do | ||
m = m - 1 | m = m - 1 | ||
date = date + month_len(m, date_info.year) | |||
end | end | ||
date = date + date_info.day - 1 | date = date + date_info.day - 1 | ||
else | |||
date = date - (1 + month_len(date_info.month, date_info.year) | date = date - (1 + month_len(date_info.month, date_info.year) | ||
- date_info.day) | |||
local m = date_info.month + 1 | local m = date_info.month + 1 | ||
local y = date_info.year | local y = date_info.year | ||
| Line 119: | Line 130: | ||
datestamp = datestamp - 78 | datestamp = datestamp - 78 | ||
if datestamp >= 0 then | if datestamp >= 0 then | ||
while datestamp > year_len(y) do | while datestamp >= year_len(y) do | ||
datestamp = datestamp - year_len(y) | datestamp = datestamp - year_len(y) | ||
y = y + 1 | y = y + 1 | ||
end | end | ||
while datestamp > month_len(m, y) do | while datestamp >= month_len(m, y) do | ||
datestamp = datestamp - month_len(m, y) | datestamp = datestamp - month_len(m, y) | ||
m = m + 1 | m = m + 1 | ||
| Line 145: | Line 156: | ||
end | end | ||
return {year = y, month = m, day = d, weekday = dow} | return { year = y, month = m, day = d, weekday = dow } | ||
end | end | ||
| Line 152: | Line 163: | ||
-- ad-latin: Ursnés 12 Ḑekḑiņț 173706 | -- ad-latin: Ursnés 12 Ḑekḑiņț 173706 | ||
-- ad: 12 ... 173706 | -- ad: 12 ... 173706 | ||
opts = opts or | -- 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 date = calendar.to(datestamp) | ||
return string.format("%s %s %s %s", | local dow = opts.length ~= "none" and | ||
day_names[opts.lang][opts.length][date.weekday] | |||
-- local d = opts. | |||
if dow then | |||
return string.format("%s %s %s %s", dow, | |||
date.day, month_names[opts.lang][date.month], date.year) | |||
else | |||
return string.format("%s %s %s", date.day, | |||
month_names[opts.lang][date.month], date.year) | |||
end | |||
end | end | ||
return calendar | return calendar | ||
Latest revision as of 08:18, 24 May 2026
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', 'Fog',
'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" and
day_names[opts.lang][opts.length][date.weekday]
-- local d = opts.
if dow then
return string.format("%s %s %s %s", dow,
date.day, month_names[opts.lang][date.month], date.year)
else
return string.format("%s %s %s", date.day,
month_names[opts.lang][date.month], date.year)
end
end
return calendar