Module:Expanded dates
Jump to navigation
Jump to search
Documentation for this module may be created at Module:Expanded dates/doc
local p = {}
local months = {'January','February','March','April','May','June','July','August','September','October','November','December'}
local monthNames = {}
for i, name in ipairs(months) do
monthNames[string.lower(name)] = i
monthNames[string.lower(string.sub(name, 1, 3))] = i
end
monthNames.sept = 9
local function args(frame)
local a = {}
if frame:getParent() then
for k, v in pairs(frame:getParent().args) do a[k] = mw.text.trim(v) end
end
for k, v in pairs(frame.args) do a[k] = mw.text.trim(v) end
return a
end
local function pick(a, index, named)
local v = a[index]
if v == nil or v == '' then v = a[named] end
return v
end
local function integer(value)
local n = tonumber(value)
if n and n == math.floor(n) then return n end
end
local function month(value)
local n = integer(value)
if n then
if n >= 1 and n <= 12 then return n end
return nil
end
return monthNames[string.lower(value or '')]
end
local function date(y, m, d)
y, m, d = integer(y), month(m), integer(d)
if not y or y < 1 or y > 9999 or not m or not d then return nil end
local leap = y % 4 == 0 and (y % 100 ~= 0 or y % 400 == 0)
local days = {31, leap and 29 or 28, 31,30,31,30,31,31,30,31,30,31}
if d < 1 or d > days[m] then return nil end
return {year=y, month=m, day=d}
end
local function errorMessage(message)
return tostring(mw.html.create('span'):addClass('error'):wikitext(message))
end
local function today(frame)
return date(frame:preprocess('{{CURRENTYEAR}}'), frame:preprocess('{{CURRENTMONTH}}'), frame:preprocess('{{CURRENTDAY}}'))
end
local function ageAt(birth, reference)
local age = reference.year - birth.year
if reference.month < birth.month or (reference.month == birth.month and reference.day < birth.day) then age = age - 1 end
if age < 0 then return nil end
return age
end
function p.monthnumber(frame)
local a = args(frame)
local n = month(pick(a, 1, 'month'))
if not n then return errorMessage('MONTHNUMBER: enter a month from 1 to 12 or an English month name.') end
return tostring(n)
end
function p.monthname(frame)
local a = args(frame)
local n = month(pick(a, 1, 'month'))
if not n then return errorMessage('MONTHNAME: enter a month from 1 to 12 or an English month name.') end
return months[n]
end
function p.age(frame)
local a = args(frame)
local birth = date(pick(a,1,'year'), pick(a,2,'month'), pick(a,3,'day'))
if not birth then return errorMessage('Age: enter a valid birth date as year, month, day.') end
local current = today(frame)
local reference = date(pick(a,4,'endyear') or current.year, pick(a,5,'endmonth') or current.month, pick(a,6,'endday') or current.day)
if not reference then return errorMessage('Age: enter a valid reference date.') end
local value = ageAt(birth,reference)
if not value then return errorMessage('Age: the reference date is before the birth date.') end
return tostring(value)
end
function p.birthdate(frame)
local a = args(frame)
local birth = date(pick(a,1,'year'), pick(a,2,'month'), pick(a,3,'day'))
if not birth then return errorMessage('Birth date and age: enter a valid birth date as year, month, day.') end
local value = ageAt(birth,today(frame))
if not value then return errorMessage('Birth date and age: the birth date is in the future.') end
return string.format('%d %s %d (age %d)',birth.day,months[birth.month],birth.year,value)
end
return p