Module:Age
- Description
- This module calculates age information from given years, with support for approximate years (using
c.
or {{circa}}). - It provides five functions:
age
– returns only the age range (e.g. "63–64").ageInYears
– returns the age as a single value with "years" (e.g. "64 years" or "approx. 64 years"). Can take one parameter (birth year) or two parameters (birth year and reference year).birthDateAndAge
– returns the birth year (orc. year
) followed by the age in parentheses.deathDateAndAge
– returns the death year (orc. year
) followed by the age at death in parentheses.startDateAndAge
– returns the start year (orc. year
) followed by how many years ago in parentheses.
- Usage
{{#invoke:Age|age|YEAR}}
{{#invoke:Age|ageInYears|BIRTH_YEAR}}
{{#invoke:Age|ageInYears|BIRTH_YEAR|REFERENCE_YEAR}}
{{#invoke:Age|birthDateAndAge|YEAR}}
{{#invoke:Age|deathDateAndAge|BIRTH|DEATH}}
{{#invoke:Age|startDateAndAge|YEAR}}
- Sample output
Age
{{#invoke:Age|age|4500}}
→ approx. 64
{{#invoke:Age|age|c. 4500}}
→ approx. 64
{{#invoke:Age|age|{{circa}} 4500}}
→ approx. 64
Age in years
{{#invoke:Age|ageInYears|4500}}
→ approx. 64 years
{{#invoke:Age|ageInYears|c. 4500}}
→ approx. 64 years
{{#invoke:Age|ageInYears|4500|4560}}
→ 60 years
{{#invoke:Age|ageInYears|c. 4500|4560}}
→ approx. 60 years
{{#invoke:Age|ageInYears|4500|c. 4560}}
→ approx. 60 years
Birth date and age
{{#invoke:Age|birthDateAndAge|4500}}
→ 4500 AR (age approx. 64)
{{#invoke:Age|birthDateAndAge|c. 4500}}
→ c. 4500 AR (age approx. 64)
{{#invoke:Age|birthDateAndAge|{{circa}} 4500}}
→ c. 4500 AR (age approx. 64)
Death date and age
{{#invoke:Age|deathDateAndAge|100|200}}
→ 200 AR (aged 99–100)
{{#invoke:Age|deathDateAndAge|c. 100|200}}
→ 200 AR (aged approx. 100)
{{#invoke:Age|deathDateAndAge|100|c. 200}}
→ c. 200 AR (aged approx. 100)
Start date and age
{{#invoke:Age|startDateAndAge|1000}}
→ 1000 AR (approx. 3564 years ago)
{{#invoke:Age|startDateAndAge|c. 1000}}
→ c. 1000 AR (approx. 3564 years ago)
{{#invoke:Age|startDateAndAge|{{circa}} 1000}}
→ c. 1000 AR (approx. 3564 years ago)
-- Module:Age
local p = {}
-- Safely fetch a frame argument. Returns nil if missing or blank (after trim).
local function argTrim(frame, key)
local v = frame.args[key]
if v == nil then return nil end
v = mw.text.trim(tostring(v))
if v == "" then return nil end
return v
end
-- Helper: strip "c." or {{circa}} markup and return (isApprox, number)
local function parseYear(input)
if not input then return false, nil end
input = mw.text.trim(tostring(input))
if input == "" then return false, nil end
-- Strip HTML tags (e.g. from {{circa}})
local clean = mw.ustring.gsub(input, "<.->", "")
clean = mw.text.trim(clean)
-- Does it start with "c." ?
if mw.ustring.match(clean, "^c%.") then
local numstr = mw.ustring.gsub(clean, "^c%.%s*", "")
local num = tonumber(numstr)
return true, num
end
-- Otherwise try to parse a plain number
return false, tonumber(clean)
end
-- Helper: default Year expansion (trimmed); returns a string or nil
local function defaultYear(frame)
local y = frame:expandTemplate{ title = "Year" }
y = mw.text.trim(tostring(y or ""))
if y == "" then return nil end
return y
end
-- Age-only output (for {{Age}})
function p.age(frame)
local birthInput = argTrim(frame, 1) or argTrim(frame, "birth_year")
local yearInput = argTrim(frame, 2) or argTrim(frame, "year") or defaultYear(frame)
local birthApprox, birthYear = parseYear(birthInput)
local yearApprox, yearNum = parseYear(yearInput)
if not birthYear or not yearNum then
return "?"
end
if birthApprox or yearApprox then
local age = yearNum - birthYear
return frame:expandTemplate{title = "approx"} .. " " .. tostring(age)
end
local minAge = yearNum - birthYear - 1
local maxAge = yearNum - birthYear
return tostring(minAge) .. "–" .. tostring(maxAge)
end
-- Age in years (for {{Age in years}})
function p.ageInYears(frame)
local birthInput = argTrim(frame, 1) or argTrim(frame, "birth_year")
local yearInput = argTrim(frame, 2) or argTrim(frame, "year") or defaultYear(frame)
local birthApprox, birthYear = parseYear(birthInput)
local yearApprox, yearNum = parseYear(yearInput)
if not birthYear or not yearNum then
return "?"
end
local age = yearNum - birthYear
if birthApprox or yearApprox then
return frame:expandTemplate{title = "approx"} .. " " .. tostring(age) .. " years"
end
return tostring(age) .. " years"
end
-- Birth year + age output (for {{Birth date and age}})
function p.birthDateAndAge(frame)
local birthInput = argTrim(frame, 1) or argTrim(frame, "birth_year")
local yearInput = argTrim(frame, 2) or argTrim(frame, "year") or defaultYear(frame)
local birthApprox, birthYear = parseYear(birthInput)
local yearApprox, yearNum = parseYear(yearInput)
if not birthYear or not yearNum then
return "?"
end
-- Approximate case
if birthApprox or yearApprox then
local age = yearNum - birthYear
local yearText
if birthApprox then
yearText = frame:expandTemplate{title = "circa"} .. " " .. tostring(birthYear) .. " [[AR]]"
else
yearText = tostring(birthYear) .. " [[AR]]"
end
local ageText = frame:expandTemplate{title = "approx"} .. " " .. tostring(age)
return yearText .. " (age " .. ageText .. ")"
end
-- Exact case
local minAge = yearNum - birthYear - 1
local maxAge = yearNum - birthYear
return tostring(birthYear) .. " [[AR]] (age " .. tostring(minAge) .. "–" .. tostring(maxAge) .. ")"
end
-- Death year + age at death output (for {{Death date and age}})
function p.deathDateAndAge(frame)
local birthInput = argTrim(frame, 1) or argTrim(frame, "birth_year")
local deathInput = argTrim(frame, 2) or argTrim(frame, "death_year")
local birthApprox, birthYear = parseYear(birthInput)
local deathApprox, deathYear = parseYear(deathInput)
if not birthYear or not deathYear then
return "?"
end
-- Approximate case if either is approximate
if birthApprox or deathApprox then
local age = deathYear - birthYear
local deathText
if deathApprox then
deathText = frame:expandTemplate{title = "circa"} .. " " .. tostring(deathYear) .. " [[AR]]"
else
deathText = tostring(deathYear) .. " [[AR]]"
end
local ageText = frame:expandTemplate{title = "approx"} .. " " .. tostring(age)
return deathText .. " (aged " .. ageText .. ")"
end
-- Exact case
local minAge = deathYear - birthYear - 1
local maxAge = deathYear - birthYear
return tostring(deathYear) .. " [[AR]] (aged " .. tostring(minAge) .. "–" .. tostring(maxAge) .. ")"
end
-- Start year + years ago output (for {{Start date and age}})
function p.startDateAndAge(frame)
local startInput = argTrim(frame, 1) or argTrim(frame, "start_year")
local yearInput = argTrim(frame, 2) or argTrim(frame, "year") or defaultYear(frame)
local startApprox, startYear = parseYear(startInput)
local yearApprox, yearNum = parseYear(yearInput)
if not startYear or not yearNum then
return "?"
end
-- Approximate case
if startApprox or yearApprox then
local yearsAgo = yearNum - startYear
local yearsText = frame:expandTemplate{title = "approx"} .. " " .. tostring(yearsAgo)
local startText
if startApprox then
startText = frame:expandTemplate{title = "circa"} .. " " .. tostring(startYear) .. " [[AR]]"
else
startText = tostring(startYear) .. " [[AR]]"
end
return startText .. " (" .. yearsText .. " years ago)"
end
-- Exact case
local minYears = yearNum - startYear - 1
local maxYears = yearNum - startYear
return tostring(startYear) .. " [[AR]] (" .. tostring(minYears) .. "–" .. tostring(maxYears) .. " years ago)"
end
return p