Module:IriniaCalendar
From DSRPG
Documentation for this module may be created at Module:IriniaCalendar/doc
-- Module:IriniaCalendar
-- A module for handling the custom calendar of Irinia
local p = {}
-- Configurable calendar variables
local calendar = {
current = { day = 4, month = 5, year = 1236 },
months = {
[1] = "Frost Moon", [2] = "Shadow Moon", [3] = "Storm Moon",
[4] = "Mist Moon", [5] = "Bloom Moon", [6] = "Sun Moon",
[7] = "Thunder Moon", [8] = "Harvest Moon",[9] = "Ember Moon",
[10] = "Frost Moon", [11] = "Twilight Moon",[12] = "Star Moon"
},
days_in_month = {
[1] = 30, [2] = 28, [3] = 30, [4] = 29,
[5] = 31, [6] = 31, [7] = 30, [8] = 31,
[9] = 30,[10] = 31,[11] = 28,[12] = 30
},
weekdays = {
[1] = "Silverday", [2] = "Brassday", [3] = "Woodday",
[4] = "Stoneday", [5] = "Glassday", [6] = "Steamday",
[7] = "Gearsday"
},
seasons = {
[1] = "Winter", [2] = "Winter", [3] = "Spring",
[4] = "Spring", [5] = "Spring", [6] = "Summer",
[7] = "Summer", [8] = "Summer", [9] = "Autumn",
[10] = "Autumn",[11] = "Autumn",[12] = "Winter"
},
era = "AE",
days_in_year = 359
}
-- Format a date via #invoke args: day, month, year, format
function p.formatDate(frame)
local args = frame.args or {}
local day = tonumber(args.day) or calendar.current.day
local month = tonumber(args.month) or calendar.current.month
local year = tonumber(args.year) or calendar.current.year
local fmt = args.format or "full"
if month < 1 or month > #calendar.months then
month = ((month - 1) % #calendar.months) + 1
end
local monthName = calendar.months[month]
if fmt == "full" then
return day .. " " .. monthName .. ", " .. year .. " " .. calendar.era
elseif fmt == "short" then
return day .. " " .. monthName .. ", " .. year
elseif fmt == "month-year" then
return monthName .. ", " .. year .. " " .. calendar.era
elseif fmt == "day-month" then
return day .. " " .. monthName
elseif fmt == "numeric" then
return day .. "/" .. month .. "/" .. year .. " " .. calendar.era
else
-- fallback for unknown formats
return day .. " " .. monthName .. ", " .. year .. " " .. calendar.era
end
end
-- Total days since year 0
function p.totalDays(date)
if not date or not date.day or not date.month or not date.year then return 0 end
local total = date.year * calendar.days_in_year
for i = 1, date.month - 1 do
total = total + calendar.days_in_month[i]
end
total = total + date.day
return total
end
-- Compare two dates: returns -1, 0, or 1
function p.compareDate(a, b)
if a.year < b.year then return -1 elseif a.year > b.year then return 1 end
if a.month < b.month then return -1 elseif a.month > b.month then return 1 end
if a.day < b.day then return -1 elseif a.day > b.day then return 1 end
return 0
end
-- Calculate difference between two dates as a string
function p.dateDifference(d1, d2)
local negative = false
if p.compareDate(d1, d2) > 0 then d1, d2 = d2, d1; negative = true end
local years = d2.year - d1.year
local months = 0
local days = 0
if d2.month >= d1.month then
months = d2.month - d1.month
else
years = years - 1
months = 12 - d1.month + d2.month
end
if d2.day >= d1.day then
days = d2.day - d1.day
else
if months > 0 then
months = months - 1
else
years = years - 1
months = 11
end
local prev = d2.month - 1
if prev < 1 then prev = 12 end
days = calendar.days_in_month[prev] - d1.day + d2.day
end
local parts = {}
if years ~= 0 then table.insert(parts, years .. " year" .. (years ~= 1 and "s" or "")) end
if months ~= 0 then table.insert(parts, months.. " month" .. (months ~= 1 and "s" or "")) end
if days ~= 0 or #parts == 0 then table.insert(parts, days .. " day" .. (days ~= 1 and "s" or "")) end
local result = table.concat(parts, ", ")
if #parts > 1 then
result = string.gsub(result, ", ([^,]*)$", " and %1")
end
if negative then result = result .. " ago" end
return result
end
-- How long since a given date
function p.timeSince(frame)
local args = frame.args or {}
local d = {
day = tonumber(args.day) or 1,
month = tonumber(args.month) or 1,
year = tonumber(args.year) or 0
}
return p.dateDifference(d, calendar.current)
end
-- How long until a given date
function p.timeUntil(frame)
local args = frame.args or {}
local d = {
day = tonumber(args.day) or 1,
month = tonumber(args.month) or 1,
year = tonumber(args.year) or 0
}
return p.dateDifference(calendar.current, d)
end
-- Calculate age in years given birth date
function p.calculateAge(frame)
local args = frame.args or {}
local d = {
day = tonumber(args.day) or 1,
month = tonumber(args.month) or 1,
year = tonumber(args.year) or 0
}
local diff = p.dateDifference(d, calendar.current)
local y = string.match(diff, "^(%d+) years?")
return y or "0"
end
return p