Jump to content

Module:Calendar

From Adaris
Revision as of 19:46, 16 October 2026 by Oros (talk | contribs) (Created page with " 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 tabl...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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