Documentation for this module may be created at Module:Age/doc
-- Scribunto Lua plugin to convert an ISO date-time (1970-01-01T00:00:00Z) or
-- date (1970-01-01) to an English human-readable date (1 January 1970) and
-- age (50 years old).
local function parse_iso(iso)
local year, month, day, hour, minute, second =
iso:match('^(%d%d%d%d)-(%d%d)-(%d%d)T(%d%d):(%d%d):(%d%d)Z$')
if not year then
year, month, day = iso:match('^(%d%d%d%d)-(%d%d)-(%d%d)$')
if not year then
return nil
end
hour, minute, second = 0, 0, 0
end
return {
year = tonumber(year),
month = tonumber(month),
day = tonumber(day),
hour = tonumber(hour),
minute = tonumber(minute),
second = tonumber(second),
}
end
-- Automatically return a timestamp some number of years in the past.
local function retro(offset)
local now = os.time()
local then_ = now - (offset * 365 * 24 * 60 * 60)
return os.date('!%Y-%m-%dT%H:%M:%SZ', then_)
end
local function age(iso_then, iso_now)
local then_parts = parse_iso(iso_then)
if not then_parts then
return nil
end
local now
local now_parts
if iso_now then
now_parts = parse_iso(iso_now)
if not now_parts then
return nil
end
now = os.time(now_parts)
else
now = os.time()
end
local then_ = os.time(then_parts)
local diff = now - then_
local seconds = diff % 60
diff = math.floor(diff / 60)
local minutes = diff % 60
diff = math.floor(diff / 60)
local hours = diff % 24
diff = math.floor(diff / 24)
local days = diff % 30
diff = math.floor(diff / 30)
--local months = diff % 12
--diff = math.floor(diff / 12)
--local years = diff
local months = now_parts.month - then_parts.month
local years = now_parts.year - then_parts.year
if months < 0 then
months = months + 12
years = years - 1
end
return {
years = years,
months = months,
days = days,
hours = hours,
minutes = minutes,
seconds = seconds,
}
end
local function format_date(iso)
local parsed = parse_iso(iso)
if not parsed then
return nil
end
return os.date('%e %B %Y', os.time(parsed))
end
local precision_levels = {
years = 1,
months = 2,
days = 3,
hours = 4,
minutes = 5,
seconds = 6,
}
local precision_index = {}
for k, v in pairs(precision_levels) do
precision_index[v] = k
end
local plurals = {
years = { one = 'year', other = 'years' },
months = { one = 'month', other = 'months' },
days = { one = 'day', other = 'days' },
hours = { one = 'hour', other = 'hours' },
minutes = { one = 'minute', other = 'minutes' },
seconds = { one = 'second', other = 'seconds' },
}
local function format_age(iso, iso_now, precision)
local prec_int = precision_levels[precision]
if not prec_int then
if not precision then
prec_int = 6
else
return nil
end
end
local parts = age(iso, iso_now)
if not parts then
return nil
end
local strs = {}
for i = 1, prec_int do
local part = parts[precision_index[i]]
if part > 0 then
local plural = plurals[precision_index[i]]
strs[#strs + 1] = tostring(part)
.. ' '
.. plural[part == 1 and 'one' or 'other']
end
end
return table.concat(strs, ', ')
end
local function age_mw(frame)
local args = frame.args
local iso = args[1]
local iso_now = args[2]
local precision = args[3]
return format_age(iso, iso_now, precision)
end
local function date_mw(frame)
local args = frame.args
local iso = args[1]
return format_date(iso)
end
local function retro_mw(frame)
local args = frame.args
local offset = tonumber(args[1])
return retro(offset)
end
return {
format_age = age_mw,
format_date = date_mw,
retro = retro_mw,
age = age,
}