Module:Keppel date
More actions
Converts the current (or provided) date to a Keppel date. Used by Template:Keppel date.
Formula
\begin{aligned} y_\oplus &= \text{Earth year} \\ d_\oplus &= \text{Earth day of year (fractional)} \\ d_{\oplus_\text{max}}(y_\oplus) &= \begin{cases} 366 & (y_\oplus = 0 \pmod{4} \text{ and } y_\oplus \neq 0 \pmod{100}) \text{ or } y_\oplus = 0 \pmod{400} \\ 365 & \text{otherwise} \end{cases} \\ \text{offset}(y_\oplus) &= d_{\oplus_\text{max}}(y_\oplus) - 287 \\ d_{\text{K}_\text{max}}(y_\text{K}) &= \begin{cases} 391 & y_\text{K} = 65 \pmod{239} \text{ and } y_\text{K} = 2 \pmod{4} \\ 390 & y_\text{K} = 65 \pmod{239} \text{ or } y_\text{K} = 2 \pmod{4} \\ 389 & \text{otherwise} \end{cases} \\ y_\text{K}(y_\oplus) &= y_\oplus - 892 \\ y_\text{K} &= \begin{cases} y_\text{K}(y_\oplus) & d_\oplus - \text{offset}(y_\oplus) \geq \frac{d_{\oplus_\text{max}}(y_\oplus)}{d_{\text{K}_\text{max}}(y_\text{K}(y_\oplus))} \\ y_\text{K}(y_\oplus) - 1 & d_\oplus - \text{offset}(y_\oplus) < \frac{d_{\oplus_\text{max}}(y_\oplus)}{d_{\text{K}_\text{max}}(y_\text{K}(y_\oplus))} \end{cases} \\ d_\text{K} &= (\frac{d_\oplus - \text{offset}(y_\oplus)}{d_{\oplus_\text{max}}(y_\oplus)} \times d_{\text{K}_\text{max}}(y_\text{K}) - 1) \bmod{d_{\text{K}_\text{max}}(y_\text{K})} + 1 \\ L_\text{K} &= \lfloor \frac{d_\text{K} - 1}{32} \rfloor + 1 \\ d_{\text{K}_L} &= \lfloor (d_\text{K} - 1) \bmod{32} \rfloor + 1 \end{aligned}
local p = {}
-- libraries
local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
-- year calculations
local function isEarthLeapYear(year)
-- every 4 years
-- except for every 100 years
-- except for every 400 years
return (year % 400 == 0) or (year % 100 ~= 0 and year % 4 == 0)
end
local function getEarthYearLength(year)
local yearLength = 365
if isEarthLeapYear(year) then yearLength = yearLength + 1 end
return yearLength
end
local function isLeapYear1(year)
-- every 4 years (offset 2)
return year % 4 == 2
end
local function isLeapYear2(year)
-- every 239 years (offset 65)
return year % 239 == 65
end
local function getYearLength(year)
local yearLength = 389
if isLeapYear1(year) then yearLength = yearLength + 1 end
if isLeapYear2(year) then yearLength = yearLength + 1 end
return yearLength
end
local function getYdayOffset(earthYear)
local ydayOffset = 78
if isEarthLeapYear(earthYear) then ydayOffset = ydayOffset + 1 end -- February 29
return ydayOffset
end
-- lythryds
local lythryds = {
'Liliyogh',
'Avonslau',
'Bovvilag',
'Haelaidhe',
'Gildorne',
'Auvhlaus',
'Ludervinn',
'Glausonn',
'Yahataidh',
'Serelakkan',
'Frosma',
'Tegeirukk',
'Intercal'
}
-- ochtdays
local ochtdays = {
'Astresday',
'Solsday',
'Embresday',
'Jadesday',
'Ryvysday',
'Tyrrhsday',
'Lysisday',
'Octresday'
}
-- https://amaranth-legacy.community/Seventeen_Suns
local sun_signs = {
'[[File:Keppel-astrology-Alcaernon.png|32px|alt=]] Alcaernon',
'[[File:Keppel-astrology-Eumrakh.png|32px|alt=]] Eumrakh',
'[[File:Keppel-astrology-Aureolin.png|32px|alt=]] Aureolin',
'[[File:Keppel-astrology-Pereptia.png|32px|alt=]] Pereptia',
'[[File:Keppel-astrology-Sechmas.png|32px|alt=]] Sechmas',
'[[File:Keppel-astrology-Mananakus.png|32px|alt=]] Mananakus',
'[[File:Keppel-astrology-Luxor.png|32px|alt=]] Luxor',
'[[File:Keppel-astrology-Illyre.png|32px|alt=]] Illyre',
'[[File:Keppel-astrology-Glauryuz.png|32px|alt=]] Glauryuz',
'[[File:Keppel-astrology-Schismata.png|32px|alt=]] Schismata',
'[[File:Keppel-astrology-Annrava.png|32px|alt=]] Annrava',
'[[File:Keppel-astrology-Yahasain.png|32px|alt=]] Yahasain',
'[[File:Keppel-astrology-Regalion.png|32px|alt=]] Regalion',
'[[File:Keppel-astrology-Vaalgrota.png|32px|alt=]] Vaalgrota',
'[[File:Keppel-astrology-Cancrus.png|32px|alt=]] Cancrus',
'[[File:Keppel-astrology-Eremoor.png|32px|alt=]] Eremoor',
'[[File:Keppel-astrology-Haerox.png|32px|alt=]] Haerox'
}
-- date converter
function p.convert(time)
-- get the current date
local date = os.date('*t', time)
-- add the time to yday
date.yday = date.yday + (date.hour / 24) + (date.min / (24 * 60)) + (date.sec / (24 * 60 * 60))
-- year is Earth year minus 892
local year = date.year - 892
local yearLength = getYearLength(year)
-- if yday is before the start, it's the previous year
local yday = date.yday - getYdayOffset(date.year)
if yday < 1 then
year = year - 1
yearLength = getYearLength(year)
end
-- calculate the yday
yday = yday / getEarthYearLength(year) * yearLength
-- if yday is before the start, it's an offset from tne end of the previous year
if yday < 1 then
yday = yearLength + yday
end
-- a lythryd is 32 days
local lythryd = math.ceil(yday / 32)
-- to get the day of the lythryd, subtract the days in previous lythryds
local day = math.floor(yday) - ((lythryd - 1) * 32)
-- get the time as well
local ydayTime = select(2, math.modf(yday))
local seconds = select(1, math.modf(ydayTime * 86400))
local minutes = select(1, math.modf(seconds / 60))
local hour = select(1, math.modf(minutes / 60))
local minute = minutes % 60
local second = seconds % 60
return {
year = year,
yday = yday,
lythryd = lythryd,
day = day,
hour = hour,
minute = minute,
second = second
}
end
function p.invoke(frame)
local args = getArgs(frame)
local time
if args['year'] and args['month'] and args['day'] then
time = os.time{
year = args['year'],
month = args['month'],
day = args['day'],
hour = args['hour'] or 0,
minute = args['minute'] or 0,
second = args['second'] or 0
}
elseif args['time'] then
time = args['time']
elseif args[1] then
time = args[1]
else
time = os.time()
end
return p.convert(time)
end
function p.main(frame)
local args = getArgs(frame)
local result = p.invoke(frame)
local year
if result.year <= 0 then
year = (math.abs(result.year) + 1) .. ' AT'
else
year = result.year .. ' LE'
end
if yesno(args['year_only'] or false) then
return year
elseif yesno(args['month_day_only'] or false) then
return string.format(
'%s %d',
lythryds[result.lythryd],
result.day
)
else
local formatted = string.format(
'%s %d, %s',
lythryds[result.lythryd],
result.day,
year
)
if yesno(args['show_ochtday'] or false) then
formatted = string.format(
'%s, %s',
ochtdays[(result.day - 1) % 8 + 1],
formatted
)
end
if yesno(args['show_time'] or false) then
formatted = string.format(
'%s %02d:%02d:%02d',
formatted,
result.hour,
result.minute,
result.second
)
end
if yesno(args['show_sun_sign'] or false) then
formatted = string.format(
'%s (%s)',
formatted,
sun_signs[math.floor(result.yday / 24) + 1]
)
end
return formatted
end
end
return p