Module:Age: Difference between revisions

2,423 bytes added ,  5 years ago
(update from sandbox: implement Template:Death date and age)
Line 1: Line 1:
-- Implement various "age of" and other date-related templates.
-- Implement various "age of" and other date-related templates.
local mtext = {
-- Message and other text that should be localized.
['mt-bad-param1'] =            'Invalid parameter $1',
['mt-bad-param2'] =            'Parameter $1=$2 is invalid',
['mt-bad-show'] =              'Parameter show=$1 is not supported here',
['mt-cannot-add'] =            'Cannot add "$1"',
['mt-conflicting-show'] =      'Parameter show=$1 conflicts with round=$2',
['mt-date-wrong-order'] =      'The second date must be later in time than the first date',
['mt-dd-wrong-order'] =        'Death date (first date) must be later in time than the birth date (second date)',
['mt-invalid-bd-age'] =        'Invalid birth date for calculating age',
['mt-invalid-dates-age'] =      'Invalid dates for calculating age',
['mt-invalid-end'] =            'Invalid end date in second parameter',
['mt-invalid-start'] =          'Invalid start date in first parameter',
['mt-need-jdn'] =              'Need valid Julian date number',
['mt-need-valid-bd'] =          'Need valid birth date: year, month, day',
['mt-need-valid-bd2'] =        'Need valid birth date (second date): year, month, day',
['mt-need-valid-date'] =        'Need valid date',
['mt-need-valid-dd'] =          'Need valid death date (first date): year, month, day',
['mt-need-valid-ymd'] =        'Need valid year, month, day',
['mt-need-valid-ymd-current'] = 'Need valid year|month|day or "currentdate"',
['mt-need-valid-ymd2'] =        'Second date should be year, month, day',
['mt-template-bad-name'] =      'The specified template name is not valid',
['mt-template-x'] =            'The template invoking this must have "|template=x" where x is the wanted operation',
['txt-age'] =                  '(age ',
['txt-aged'] =                  ' (aged ',
['txt-and'] =                  ' and ',
['txt-comma-and'] =            ', and ',
['txt-error'] =                'Error: ',
['txt-or'] =                    ' or ',
}
local translate, from_en, to_en, isZero
if translate then
-- Functions to translate from en to local language and reverse go here.
-- See example at [[:bn:Module:বয়স]].
else
from_en = function (text)
return text
end
isZero = function (text)
return tonumber(text) == 0
end
end


local _Date, _currentDate
local _Date, _currentDate
Line 7: Line 51:
local sandbox = frame:getTitle():find('sandbox', 1, true) and '/sandbox' or ''
local sandbox = frame:getTitle():find('sandbox', 1, true) and '/sandbox' or ''
local datemod = require('Module:Date' .. sandbox)
local datemod = require('Module:Date' .. sandbox)
_Date = datemod._Date
local realDate = datemod._Date
_currentDate = datemod._current
_currentDate = datemod._current
if to_en then
_Date = function (...)
local args = {}
for i, v in ipairs({...}) do
args[i] = to_en(v)
end
return realDate(unpack(args))
end
else
_Date = realDate
end
end
end
return _Date, _currentDate
return _Date, _currentDate
Line 57: Line 112:
local function message(msg, id)
local function message(msg, id)
-- Return formatted message text for an error or warning.
-- Return formatted message text for an error or warning.
local function getText(msg)
return mtext[msg] or error('Bug: message "' .. tostring(msg) .. '" not defined')
end
local text
if type(msg) == 'table' then
text = getText(msg[1])
local rep = {}
for i, v in ipairs(msg) do
if i > 1 then
rep['$' .. (i - 1)] = v
end
end
text = text:gsub('$%d+', rep)
else
text = getText(msg)
end
local categories = {
local categories = {
error = '[[Category:Age error]]',
error = '[[Category:Age error]]',
Line 66: Line 137:
b = '</i>]</sup>'
b = '</i>]</sup>'
else
else
a = '<strong class="error">Error: '
a = '<strong class="error">' .. getText('txt-error')
b = '</strong>'
b = '</strong>'
end
end
Line 75: Line 146:
return
return
a ..
a ..
mw.text.nowiki(msg) ..
mw.text.nowiki(text) ..
b ..
b ..
(category or '')
(category or '')
Line 252: Line 323:
return 'error'
return 'error'
end
end
return message('Need valid date')
return message('mt-need-valid-date')
end
end
local add = stripToNil(args.add)
local add = stripToNil(args.add)
Line 259: Line 330:
date = date + item
date = date + item
if not date then
if not date then
return message('Cannot add "' .. item .. '"')
return message({ 'mt-cannot-add', item })
end
end
end
end
Line 272: Line 343:
result = date[show]
result = date[show]
if result == nil then
if result == nil then
result = date:text(show)
result = from_en(date:text(show))
elseif type(result) == 'boolean' then
elseif type(result) == 'boolean' then
result = result and '1' or '0'
result = result and '1' or '0'
else
else
result = tostring(result)
result = from_en(tostring(result))
end
end
end
end
Line 284: Line 355:
local function rangeJoin(range)
local function rangeJoin(range)
-- Return text to be used between a range of ages.
-- Return text to be used between a range of ages.
return range == 'dash' and '–' or '&nbsp;or '
return range == 'dash' and '–' or mtext['txt-or']
end
end


Line 335: Line 406:
elseif options.join == 'sep_serialcomma' and text.n > 2 then
elseif options.join == 'sep_serialcomma' and text.n > 2 then
first = ', '
first = ', '
last = ', and '
last = mtext['txt-comma-and']
else
else
first = ', '
first = ', '
last = ' and '
last = mtext['txt-and']
end
end
for i, v in ipairs(text) do
for i, v in ipairs(text) do
Line 478: Line 549:
(textOptions.suffix or '')
(textOptions.suffix or '')
end
end
return message('Parameter show=' .. show.id .. ' is not supported here')
return message({ 'mt-bad-show', show.id })
end
end


Line 533: Line 604:
end
end
if getopt.omitZero and i % 3 ~= 1 then  -- omit zero months and days as unknown values but keep year 0 which is 1 BCE
if getopt.omitZero and i % 3 ~= 1 then  -- omit zero months and days as unknown values but keep year 0 which is 1 BCE
if tonumber(fields[i]) == 0 then
if isZero(fields[i]) then
fields[i] = nil
fields[i] = nil
getopt.partial = true
getopt.partial = true
Line 578: Line 649:
end
end
if not dates[1] then
if not dates[1] then
return message(getopt.missing1 or 'Need valid year, month, day')
return message(getopt.missing1 or 'mt-need-valid-ymd')
end
end
if getopt.single then
if getopt.single then
Line 584: Line 655:
end
end
if not dates[2] then
if not dates[2] then
return message(getopt.missing2 or 'Second date should be year, month, day')
return message(getopt.missing2 or 'mt-need-valid-ymd2')
end
end
return dates[1], dates[2]
return dates[1], dates[2]
Line 595: Line 666:
local name = frame.args.template
local name = frame.args.template
if not name then
if not name then
return message('The template invoking this must have "|template=x" where x is the wanted operation')
return message('mt-template-x')
end
end
local args = frame:getParent().args
local args = frame:getParent().args
Line 692: Line 763:
local spec = specs[name]
local spec = specs[name]
if not spec then
if not spec then
return message('The specified template name is not valid')
return message('mt-template-bad-name')
end
end
if name == 'age_days' then
if name == 'age_days' then
Line 756: Line 827:
}
}
if (spec.negative or frame.args.negative) == 'error' and parms.diff.isnegative then
if (spec.negative or frame.args.negative) == 'error' and parms.diff.isnegative then
return message('The second date should not be before the first date')
return message('mt-date-wrong-order')
end
end
return dateDifference(parms)
return from_en(dateDifference(parms))
end
end


Line 765: Line 836:
local args = frame:getParent().args
local args = frame:getParent().args
local options = {
local options = {
missing1 = 'Need valid birth date: year, month, day',
missing1 = 'mt-need-valid-bd',
noMissing = true,
noMissing = true,
single = true,
single = true,
Line 776: Line 847:
local diff = Date('currentdate') - date
local diff = Date('currentdate') - date
if diff.isnegative or diff.years > 150 then
if diff.isnegative or diff.years > 150 then
return message('Invalid birth date for calculating age')
return message('mt-invalid-bd-age')
end
end
local disp, show = 'disp_raw', 'y'
local disp, show = 'disp_raw', 'y'
Line 788: Line 859:
end
end
local df = stripToNil(args.df)  -- day first (dmy); default is month first (mdy)
local df = stripToNil(args.df)  -- day first (dmy); default is month first (mdy)
local result = df and
local result = '(<span class="bday">%-Y-%m-%d</span>) </span>' ..
'%-d %B %-Y' or
(df and '%-d %B %-Y' or '%B %-d, %-Y')
'%B %-d, %-Y'
result = from_en('<span style="display:none"> ' ..
result = '(<span class="bday">%-Y-%m-%d</span>) </span>' .. result
result = '<span style="display:none"> ' ..
date:text(result) ..
date:text(result) ..
'<span class="noprint ForceAgeToShow"> ' ..
'<span class="noprint ForceAgeToShow"> ' ..
'(age&nbsp;' ..
mtext['txt-age'] ..
dateDifference({
dateDifference({
diff = diff,
diff = diff,
Line 803: Line 872:
sep = 'sep_space',
sep = 'sep_space',
}) ..
}) ..
')</span>'
')</span>')
local warnings = tonumber(frame.args.warnings)
local warnings = tonumber(frame.args.warnings)
if warnings and warnings > 0 then
if warnings and warnings > 0 then
Line 832: Line 901:
end
end
if invalid then
if invalid then
result = result .. message('invalid parameter ' .. invalid, 'warning')
result = result .. message({ 'mt-bad-param1', invalid }, 'warning')
end
end
end
end
Line 842: Line 911:
local args = frame:getParent().args
local args = frame:getParent().args
local options = {
local options = {
missing1 = 'Need valid death date (first date): year, month, day',
missing1 = 'mt-need-valid-dd',
missing2 = 'Need valid birth date (second date): year, month, day',
missing2 = 'mt-need-valid-bd2',
noMissing = true,
noMissing = true,
partial = true,
partial = true,
Line 853: Line 922:
local diff = date1 - date2
local diff = date1 - date2
if diff.isnegative then
if diff.isnegative then
return message('Death date (first date) must occur after birth date (second date)')
return message('mt-dd-wrong-order')
end
end
local years
local years
Line 863: Line 932:
end
end
if years > 150 then
if years > 150 then
return message('Invalid dates for calculating age')
return message('mt-invalid-dates-age')
end
end
local df = stripToNil(args.df)  -- day first (dmy); default is month first (mdy)
local df = stripToNil(args.df)  -- day first (dmy); default is month first (mdy)
Line 881: Line 950:
'<span style="display:none">(%-Y-00-00)</span>'
'<span style="display:none">(%-Y-00-00)</span>'
end
end
result = date1:text(result) ..
result = from_en(date1:text(result) ..
' (aged&nbsp;' ..
mtext['txt-aged'] ..
dateDifference({
dateDifference({
diff = diff,
diff = diff,
Line 891: Line 960:
sep = 'sep_space',
sep = 'sep_space',
}) ..
}) ..
')'
')')
local warnings = tonumber(frame.args.warnings)
local warnings = tonumber(frame.args.warnings)
if warnings and warnings > 0 then
if warnings and warnings > 0 then
Line 914: Line 983:
end
end
if invalid then
if invalid then
result = result .. message('invalid parameter ' .. invalid, 'warning')
result = result .. message({ 'mt-bad-param1', invalid }, 'warning')
end
end
end
end
Line 940: Line 1,009:
local date = Date('juliandate', args[1], args[2])
local date = Date('juliandate', args[1], args[2])
if date then
if date then
return date:text()
return from_en(date:text())
end
end
return message('Need valid Julian date number')
return message('mt-need-jdn')
end
end


Line 955: Line 1,024:
return tostring(date.jd)
return tostring(date.jd)
end
end
return message('Need valid year/month/day or "currentdate"')
return message('mt-need-valid-ymd-current')
end
end


Line 974: Line 1,043:
local date1 = Date(fix, 'partial', stripToNil(args[1]) or 'currentdatetime')
local date1 = Date(fix, 'partial', stripToNil(args[1]) or 'currentdatetime')
if not date1 then
if not date1 then
return message('Invalid start date in first parameter')
return message('mt-invalid-start')
end
end
local date2 = Date(fix, 'partial', stripToNil(args[2]) or 'currentdatetime')
local date2 = Date(fix, 'partial', stripToNil(args[2]) or 'currentdatetime')
if not date2 then
if not date2 then
return message('Invalid end date in second parameter')
return message('mt-invalid-end')
end
end
parms.diff = date2 - date1
parms.diff = date2 - date1
Line 986: Line 1,055:
parm = translate[parm]
parm = translate[parm]
if parm == nil then  -- test for nil because false is a valid setting
if parm == nil then  -- test for nil because false is a valid setting
return message('Parameter ' .. argname .. '=' .. args[argname] .. ' is invalid')
return message({ 'mt-bad-param2', argname, args[argname] })
end
end
parms[argname] = parm
parms[argname] = parm
Line 997: Line 1,066:
if show then
if show then
if show.id ~= round then
if show.id ~= round then
return message('Parameter show=' .. args.show .. ' conflicts with round=' .. args.round)
return message({ 'mt-conflicting-show', args.show, args.round })
end
end
else
else
Line 1,005: Line 1,074:
parms.round = true
parms.round = true
end
end
return dateDifference(parms)
return from_en(dateDifference(parms))
end
end


Anonymous user