<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://geometrydashwiki.com/index.php?action=history&amp;feed=atom&amp;title=Module%3AExpanded_dates</id>
	<title>Module:Expanded dates - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://geometrydashwiki.com/index.php?action=history&amp;feed=atom&amp;title=Module%3AExpanded_dates"/>
	<link rel="alternate" type="text/html" href="https://geometrydashwiki.com/wiki/Module:Expanded_dates?action=history"/>
	<updated>2026-10-14T10:35:01Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://geometrydashwiki.com/wiki/Module:Expanded_dates?diff=122006&amp;oldid=prev</id>
		<title>Bot994: Fix date formatting, validate calendar dates and calculate completed age</title>
		<link rel="alternate" type="text/html" href="https://geometrydashwiki.com/wiki/Module:Expanded_dates?diff=122006&amp;oldid=prev"/>
		<updated>2026-10-12T07:03:09Z</updated>

		<summary type="html">&lt;p&gt;Fix date formatting, validate calendar dates and calculate completed age&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local p = {}&lt;br /&gt;
local months = {&amp;#039;January&amp;#039;,&amp;#039;February&amp;#039;,&amp;#039;March&amp;#039;,&amp;#039;April&amp;#039;,&amp;#039;May&amp;#039;,&amp;#039;June&amp;#039;,&amp;#039;July&amp;#039;,&amp;#039;August&amp;#039;,&amp;#039;September&amp;#039;,&amp;#039;October&amp;#039;,&amp;#039;November&amp;#039;,&amp;#039;December&amp;#039;}&lt;br /&gt;
local monthNames = {}&lt;br /&gt;
for i, name in ipairs(months) do&lt;br /&gt;
    monthNames[string.lower(name)] = i&lt;br /&gt;
    monthNames[string.lower(string.sub(name, 1, 3))] = i&lt;br /&gt;
end&lt;br /&gt;
monthNames.sept = 9&lt;br /&gt;
local function args(frame)&lt;br /&gt;
    local a = {}&lt;br /&gt;
    if frame:getParent() then&lt;br /&gt;
        for k, v in pairs(frame:getParent().args) do a[k] = mw.text.trim(v) end&lt;br /&gt;
    end&lt;br /&gt;
    for k, v in pairs(frame.args) do a[k] = mw.text.trim(v) end&lt;br /&gt;
    return a&lt;br /&gt;
end&lt;br /&gt;
local function pick(a, index, named)&lt;br /&gt;
    local v = a[index]&lt;br /&gt;
    if v == nil or v == &amp;#039;&amp;#039; then v = a[named] end&lt;br /&gt;
    return v&lt;br /&gt;
end&lt;br /&gt;
local function integer(value)&lt;br /&gt;
    local n = tonumber(value)&lt;br /&gt;
    if n and n == math.floor(n) then return n end&lt;br /&gt;
end&lt;br /&gt;
local function month(value)&lt;br /&gt;
    local n = integer(value)&lt;br /&gt;
    if n then&lt;br /&gt;
        if n &amp;gt;= 1 and n &amp;lt;= 12 then return n end&lt;br /&gt;
        return nil&lt;br /&gt;
    end&lt;br /&gt;
    return monthNames[string.lower(value or &amp;#039;&amp;#039;)]&lt;br /&gt;
end&lt;br /&gt;
local function date(y, m, d)&lt;br /&gt;
    y, m, d = integer(y), month(m), integer(d)&lt;br /&gt;
    if not y or y &amp;lt; 1 or y &amp;gt; 9999 or not m or not d then return nil end&lt;br /&gt;
    local leap = y % 4 == 0 and (y % 100 ~= 0 or y % 400 == 0)&lt;br /&gt;
    local days = {31, leap and 29 or 28, 31,30,31,30,31,31,30,31,30,31}&lt;br /&gt;
    if d &amp;lt; 1 or d &amp;gt; days[m] then return nil end&lt;br /&gt;
    return {year=y, month=m, day=d}&lt;br /&gt;
end&lt;br /&gt;
local function errorMessage(message)&lt;br /&gt;
    return tostring(mw.html.create(&amp;#039;span&amp;#039;):addClass(&amp;#039;error&amp;#039;):wikitext(message))&lt;br /&gt;
end&lt;br /&gt;
local function today(frame)&lt;br /&gt;
    return date(frame:preprocess(&amp;#039;{{CURRENTYEAR}}&amp;#039;), frame:preprocess(&amp;#039;{{CURRENTMONTH}}&amp;#039;), frame:preprocess(&amp;#039;{{CURRENTDAY}}&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
local function ageAt(birth, reference)&lt;br /&gt;
    local age = reference.year - birth.year&lt;br /&gt;
    if reference.month &amp;lt; birth.month or (reference.month == birth.month and reference.day &amp;lt; birth.day) then age = age - 1 end&lt;br /&gt;
    if age &amp;lt; 0 then return nil end&lt;br /&gt;
    return age&lt;br /&gt;
end&lt;br /&gt;
function p.monthnumber(frame)&lt;br /&gt;
    local a = args(frame)&lt;br /&gt;
    local n = month(pick(a, 1, &amp;#039;month&amp;#039;))&lt;br /&gt;
    if not n then return errorMessage(&amp;#039;MONTHNUMBER: enter a month from 1 to 12 or an English month name.&amp;#039;) end&lt;br /&gt;
    return tostring(n)&lt;br /&gt;
end&lt;br /&gt;
function p.monthname(frame)&lt;br /&gt;
    local a = args(frame)&lt;br /&gt;
    local n = month(pick(a, 1, &amp;#039;month&amp;#039;))&lt;br /&gt;
    if not n then return errorMessage(&amp;#039;MONTHNAME: enter a month from 1 to 12 or an English month name.&amp;#039;) end&lt;br /&gt;
    return months[n]&lt;br /&gt;
end&lt;br /&gt;
function p.age(frame)&lt;br /&gt;
    local a = args(frame)&lt;br /&gt;
    local birth = date(pick(a,1,&amp;#039;year&amp;#039;), pick(a,2,&amp;#039;month&amp;#039;), pick(a,3,&amp;#039;day&amp;#039;))&lt;br /&gt;
    if not birth then return errorMessage(&amp;#039;Age: enter a valid birth date as year, month, day.&amp;#039;) end&lt;br /&gt;
    local current = today(frame)&lt;br /&gt;
    local reference = date(pick(a,4,&amp;#039;endyear&amp;#039;) or current.year, pick(a,5,&amp;#039;endmonth&amp;#039;) or current.month, pick(a,6,&amp;#039;endday&amp;#039;) or current.day)&lt;br /&gt;
    if not reference then return errorMessage(&amp;#039;Age: enter a valid reference date.&amp;#039;) end&lt;br /&gt;
    local value = ageAt(birth,reference)&lt;br /&gt;
    if not value then return errorMessage(&amp;#039;Age: the reference date is before the birth date.&amp;#039;) end&lt;br /&gt;
    return tostring(value)&lt;br /&gt;
end&lt;br /&gt;
function p.birthdate(frame)&lt;br /&gt;
    local a = args(frame)&lt;br /&gt;
    local birth = date(pick(a,1,&amp;#039;year&amp;#039;), pick(a,2,&amp;#039;month&amp;#039;), pick(a,3,&amp;#039;day&amp;#039;))&lt;br /&gt;
    if not birth then return errorMessage(&amp;#039;Birth date and age: enter a valid birth date as year, month, day.&amp;#039;) end&lt;br /&gt;
    local value = ageAt(birth,today(frame))&lt;br /&gt;
    if not value then return errorMessage(&amp;#039;Birth date and age: the birth date is in the future.&amp;#039;) end&lt;br /&gt;
    return string.format(&amp;#039;%d %s %d (age %d)&amp;#039;,birth.day,months[birth.month],birth.year,value)&lt;br /&gt;
end&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Bot994</name></author>
	</entry>
</feed>