Module:Calendar
Fantasy Calendar
The Calendar module generates a customizable fantasy calendar using a six-day week, five-week month, and three-month season.
Calendar Structure
| Unit | Length |
|---|---|
| Week | 6 days |
| Month | 5 weeks (30 days) |
| Season | 3 months (90 days) |
| Year | 4 seasons (360 days) |
Each month begins on the first day of the week. Because all months are exactly 30 days long, the same dates always fall on the same weekdays.
Basic Usage
To display the calendar with default settings:
{{#invoke:Calendar|main
|year=1042
}}
This displays all twelve months, organized into four seasons.
Complete Example
The following example demonstrates all the principal customization options.
{{#invoke:Calendar|main
|year=1042
|view=year
|seasons=Spring,Summer,Autumn,Winter
|months=Aren,Belar,Cerin,Doran,Elmar,Ferin,Galan,Haran,Irin,Joran,Kelar,Loran
|days=First,Second,Third,Fourth,Fifth,Sixth
|mark=5-14
}}
Parameter Reference
| Parameter | Description | Default |
|---|---|---|
| year | The year displayed above the calendar. This is a label only and does not change the calendar's date calculations. | None |
| view | Determines how much of the calendar is displayed. Accepted values are year, season, and month. | year |
| seasons | A comma-separated list of four season names, in chronological order. | Spring, Summer, Autumn, Winter |
| months | A comma-separated list of twelve month names, in chronological order. The first three belong to the first season, the next three to the second, and so forth. | Month 1 through Month 12 |
| days | A comma-separated list of six weekday names, in order. | Day 1 through Day 6 |
| mark | Highlights a particular calendar date. The format is MONTH-DAY, such as 5-14 for the 14th day of the fifth month. | None |
| season | Selects a particular season (1–4) when view=season. | 1 |
| month | Selects a particular month (1–12) when view=month. | 1 |
Display Options
Full Year
Displays all four seasons and twelve months.
{{#invoke:Calendar|main
|year=1042
|view=year
}}
Single Season
Displays one season consisting of three months.
{{#invoke:Calendar|main
|year=1042
|view=season
|season=2
}}
The season parameter determines which season appears:
- 1 = First season (months 1–3)
- 2 = Second season (months 4–6)
- 3 = Third season (months 7–9)
- 4 = Fourth season (months 10–12)
Single Month
Displays one month containing five weeks of six days each.
{{#invoke:Calendar|main
|year=1042
|view=month
|month=5
}}
The month parameter accepts values from 1 to 12.
Custom Names
Seasons
Season names can be replaced with any four names.
|seasons=Spring,Summer,Autumn,Winter
Months
Supply twelve comma-separated month names.
|months=Aren,Belar,Cerin,Doran,Elmar,Ferin,Galan,Haran,Irin,Joran,Kelar,Loran
These names are assigned sequentially across the year:
| Season | Months |
|---|---|
| Spring | Aren, Belar, Cerin |
| Summer | Doran, Elmar, Ferin |
| Autumn | Galan, Haran, Irin |
| Winter | Joran, Kelar, Loran |
Weekdays
Supply six comma-separated weekday names.
|days=First,Second,Third,Fourth,Fifth,Sixth
Every month uses the same six-day sequence, repeated five times.
Highlighting Dates
The mark parameter highlights one date.
|mark=5-14
In this example:
- 5 represents the fifth month.
- 14 represents the fourteenth day.
Only the specified date is highlighted.
The highlighted date must be included in the current calendar view to appear.
Calendar Mathematics
The calendar follows a fixed structure:
- 6 days × 5 weeks = 30 days per month.
- 30 days × 3 months = 90 days per season.
- 90 days × 4 seasons = 360 days per year.
Because every month contains exactly five complete weeks, there are no partial weeks or weekday offsets between months.
The calendar does not currently implement leap days, date conversion, or automatic tracking of the current fictional date.
Installation
The calendar requires:
- Module:Calendar — Contains the Lua code that generates the calendar.
- MediaWiki:Common.css — Contains the calendar's visual styling.
To use the module, insert the relevant #invoke code into any wiki page.
local p = {}
local defaultSeasons = {
"Spring", "Summer", "Autumn", "Winter"
}
local defaultMonths = {}
local defaultDays = {}
for i = 1, 12 do
defaultMonths[i] = "Month " .. i
end
for i = 1, 6 do
defaultDays[i] = "Day " .. i
end
-- Read comma-separated custom names
local function getNames(value, defaults)
local names = {}
local parts = {}
if value and value ~= "" then
for part in mw.text.gsplit(value, ",", true) do
table.insert(parts, mw.text.trim(part))
end
end
for i = 1, #defaults do
names[i] = (parts[i] and parts[i] ~= "")
and parts[i] or defaults[i]
end
return names
end
-- Build a six-day, five-week month
local function drawMonth(parent, number, months, days, markM, markD)
local box = parent:tag("div"):addClass("fc-month")
box:tag("div")
:addClass("fc-month-name")
:wikitext(mw.text.encode(months[number]))
local calendar = box:tag("table"):addClass("fc-grid")
local header = calendar:tag("tr")
for d = 1, 6 do
header:tag("th")
:attr("scope", "col")
:wikitext(mw.text.encode(days[d]))
end
local body = calendar
for week = 0, 4 do
local row = body:tag("tr")
for d = 1, 6 do
local date = week * 6 + d
local cell = row:tag("td")
if number == markM and date == markD then
cell:addClass("fc-marked")
end
cell:wikitext(tostring(date))
end
end
end
-- Draw a season containing three months
local function drawSeason(parent, season, seasons, months, days,
selectedMonth, markM, markD)
local section = parent:tag("div"):addClass("fc-season")
section:tag("h3")
:addClass("fc-season-name")
:wikitext(mw.text.encode(seasons[season]))
local monthGrid = section:tag("div"):addClass("fc-months")
local first = (season - 1) * 3 + 1
local last = first + 2
for m = first, last do
if not selectedMonth or selectedMonth == m then
drawMonth(monthGrid, m, months, days, markM, markD)
end
end
end
function p.main(frame)
local args = frame.args
local seasons = getNames(args.seasons, defaultSeasons)
local months = getNames(args.months, defaultMonths)
local days = getNames(args.days, defaultDays)
local view = mw.text.trim(args.view or "year"):lower()
local year = mw.text.trim(args.year or "")
local month = tonumber(args.month) or 1
local season = tonumber(args.season) or 1
if view ~= "year" and view ~= "season" and view ~= "month" then
return "Calendar error: view must be year, season, or month."
end
if view == "month" and
(month < 1 or month > 12 or month % 1 ~= 0) then
return "Calendar error: month must be 1–12."
end
if view == "season" and
(season < 1 or season > 4 or season % 1 ~= 0) then
return "Calendar error: season must be 1–4."
end
-- Optional highlighted date: mark=5-14
local markM, markD = (args.mark or ""):match("^(%d+)%-(%d+)$")
markM = tonumber(markM)
markD = tonumber(markD)
local root = mw.html.create("div"):addClass("fc-calendar")
if year ~= "" then
root:tag("h2")
:addClass("fc-year-name")
:wikitext("Year " .. mw.text.encode(year))
end
if view == "month" then
local seasonIndex = math.ceil(month / 3)
drawSeason(root, seasonIndex, seasons, months, days,
month, markM, markD)
elseif view == "season" then
drawSeason(root, season, seasons, months, days,
nil, markM, markD)
else
for s = 1, 4 do
drawSeason(root, s, seasons, months, days,
nil, markM, markD)
end
end
return tostring(root)
end
return p