Module:Age: Difference between revisions

Created page with "-- Implement various "age of" and other date-related templates. local mtext = { -- Message and other text that should be localized. -- Also need to localize text in table names in function dateDifference. ['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-s..."
 
No edit summary
 
(One intermediate revision by the same user not shown)
Line 4: Line 4:
-- Message and other text that should be localized.
-- Message and other text that should be localized.
-- Also need to localize text in table names in function dateDifference.
-- Also need to localize text in table names in function dateDifference.
['mt-bad-param1'] =            'Invalid parameter $1',
['mt-bad-param2'] =            'Parameter $1=$2 is invalid',
['mt-bad-param2'] =            'Parameter $1=$2 is invalid',
['mt-bad-show'] =              'Parameter show=$1 is not supported here',
['mt-bad-show'] =              'Parameter show=$1 is not supported here',
Line 26: Line 25:
['mt-template-bad-name'] =      'The specified template name is not valid',
['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',
['mt-template-x'] =            'The template invoking this must have "|template=x" where x is the wanted operation',
['mt-warn-param1'] =            'Invalid parameter $1',
['mt-warn-param2'] =            'Parameter $1=$2 is invalid',
['txt-affirmative'] =          { y = true, yes = true, Y = true, Yes = true, YES = true },  -- valid values for df + mf parameters
['txt-yes'] =                  { y = true, yes = true, on = true },  -- valid values for parameters introduced with this module
['txt-and'] =                  ' and ',
['txt-and'] =                  ' and ',
['txt-or'] =                    ' or ',
['txt-or'] =                    ' or ',
['txt-category'] =              'Category:Age error',
['txt-category'] =              'Category:Pages using age template with invalid date',
['txt-comma-and'] =            ', and ',
['txt-comma-and'] =            ', and ',
['txt-error'] =                'Error: ',
['txt-error'] =                'Error: ',
Line 44: Line 47:


local isWarning = {
local isWarning = {
['mt-bad-param1'] = true,
['mt-warn-param1'] = true,
['mt-warn-param2'] = true,
}
}
-- yes[parameter] is true if parameter should be interpreted as "yes".
-- Do not want to accept mixed upper/lowercase unless done by previously used templates.
-- Need to accept "on" because "round=on" is wanted.
local yes = mtext['txt-yes']
-- Max valid age.
local MAX_AGE = 130


local translate, from_en, to_en, isZero
local translate, from_en, to_en, isZero
Line 116: Line 128:
end
end
return text
return text
end
local function dateFormat(args)
-- Return string for wanted date format.
local default = mtext['txt-format-default']
local other = default == 'df' and 'mf' or 'df'
local wanted = stripToNil(args[other]) and other or default
return wanted == 'df' and mtext['txt-dmy'] or mtext['txt-mdy']
end
end


Line 129: Line 133:
-- Return text after substituting any given parameters for $1, $2, etc.
-- Return text after substituting any given parameters for $1, $2, etc.
return mw.message.newRawMessage(text, ...):plain()
return mw.message.newRawMessage(text, ...):plain()
end
local function yes(parameter)
-- Return true if parameter should be interpreted as "yes".
-- Do not want to accept mixed upper/lowercase unless done by current templates.
-- Need to accept "on" because "round=on" is wanted.
return ({ y = true, yes = true, on = true })[parameter]
end
end


Line 167: Line 164:
b ..
b ..
(category or '')
(category or '')
end
local function dateFormat(args, options)
-- Return
--    nil, f if parameter is valid
--      m, f    otherwise
-- where
--      m = string for warning message with category
--      f = string for wanted date format
local wanted
if options.suppliedformat == 'dmy' then
wanted = 'df'
elseif options.suppliedformat == 'mdy' then
wanted = 'mf'
else
wanted = mtext['txt-format-default']
end
local problem
local other = wanted == 'df' and 'mf' or 'df'
local parm = args[other] or ''
if mtext['txt-affirmative'][parm] then
wanted = other
elseif parm ~= '' then
problem = message('mt-warn-param2', other, parm)
end
return problem, wanted == 'df' and mtext['txt-dmy'] or mtext['txt-mdy']
end
end


Line 331: Line 354:
parms[i] = v
parms[i] = v
end
end
if yes(args.fix) then
if yes[args.fix] then
table.insert(parms, 'fix')
table.insert(parms, 'fix')
end
end
if yes(args.partial) then
if yes[args.partial] then
table.insert(parms, 'partial')
table.insert(parms, 'partial')
end
end
Line 682: Line 705:
if not dates[1] then
if not dates[1] then
return message(getopt.missing1 or 'mt-need-valid-ymd')
return message(getopt.missing1 or 'mt-need-valid-ymd')
end
if getopt.textdates then
getopt.suppliedformat = dates[1].format
end
end
if getopt.single then
if getopt.single then
Line 729: Line 755:
flag = 'usesCurrent',
flag = 'usesCurrent',
omitZero = true,
omitZero = true,
range = 'no',
range = 'dash',
},
},
age_full_years_nts = {      -- {{age nts}}
age_full_years_nts = {      -- {{age nts}}
Line 753: Line 779:
age_infant = {              -- {{age for infant}}
age_infant = {              -- {{age for infant}}
-- Do not set show because special processing is done later.
-- Do not set show because special processing is done later.
abbr = yes(args.abbr) and 'abbr_infant' or 'abbr_off',
abbr = yes[args.abbr] and 'abbr_infant' or 'abbr_off',
disp = 'disp_age',
disp = 'disp_age',
sep = 'sep_space',
sep = 'sep_space',
Line 816: Line 842:
--    ("on" is equivalent to "yes", and "off" is equivalent to "no").
--    ("on" is equivalent to "yes", and "off" is equivalent to "no").
-- "|range=OTHER" sets range = nil and rejects partial dates.
-- "|range=OTHER" sets range = nil and rejects partial dates.
range = ({ dash = 'dash', off = 'no', no = 'no', [true] = true })[range] or yes(range)
range = ({ dash = 'dash', off = 'no', no = 'no', [true] = true })[range] or yes[range]
if range then
if range then
partial = true  -- accept partial dates with a possible age range for the result
partial = true  -- accept partial dates with a possible age range for the result
Line 826: Line 852:
end
end
local getopt = {
local getopt = {
fix = yes(args.fix),
fix = yes[args.fix],
flag = stripToNil(args.flag) or spec.flag,
flag = stripToNil(args.flag) or spec.flag,
omitZero = spec.omitZero,
omitZero = spec.omitZero,
Line 845: Line 871:
local parms = {
local parms = {
diff = date2:subtract(date1, { fill = autofill }),
diff = date2:subtract(date1, { fill = autofill }),
wantDuration = spec.duration or yes(args.duration),
wantDuration = spec.duration or yes[args.duration],
range = range,
range = range,
wantSc = yes(args.sc),
wantSc = yes[args.sc],
show = args.show == 'hide' and 'hide' or spec.show,
show = args.show == 'hide' and 'hide' or spec.show,
abbr = spec.abbr,
abbr = spec.abbr,
Line 853: Line 879:
extra = makeExtra(args, getopt.usesCurrent and format ~= 'format_raw'),
extra = makeExtra(args, getopt.usesCurrent and format ~= 'format_raw'),
format = format or spec.format,
format = format or spec.format,
round = yes(args.round),
round = yes[args.round],
sep = spec.sep,
sep = spec.sep,
sortable = translateParameters.sortable[args.sortable or spec.sortable],
sortable = translateParameters.sortable[args.sortable or spec.sortable],
Line 862: Line 888:
end
end
return from_en(dateDifference(parms))
return from_en(dateDifference(parms))
end
local function isFake(args)
-- Some templates have TemplateData with an auto value like "{{Birth date and age|YYYY|MM|DD}}".
-- Return true if that appears to be the case so the caller can output nothing rather than an error.
return args[1] == 'YYYY'
end
end


Line 867: Line 899:
-- Implement [[Template:Birth date and age]].
-- Implement [[Template:Birth date and age]].
local args = frame:getParent().args
local args = frame:getParent().args
if isFake(args) then
return ''
end
local options = {
local options = {
missing1 = 'mt-need-valid-bd',
missing1 = 'mt-need-valid-bd',
Line 878: Line 913:
local Date = getExports(frame)
local Date = getExports(frame)
local diff = Date('currentdate') - date
local diff = Date('currentdate') - date
if diff.isnegative or diff.years > 150 then
if diff.isnegative or diff.years > MAX_AGE then
return message('mt-invalid-bd-age')
return message('mt-invalid-bd-age')
end
end
Line 891: Line 926:
end
end
end
end
local problem, format = dateFormat(args, options)
local result = substituteParameters(
local result = substituteParameters(
mtext['txt-bda'],
mtext['txt-bda'],
date:text('%-Y-%m-%d'),
date:text('%-Y-%m-%d'),
from_en(date:text(dateFormat(args))),
from_en(date:text(format)),
from_en(dateDifference({
from_en(dateDifference({
diff = diff,
diff = diff,
Line 902: Line 938:
sep = 'sep_space',
sep = 'sep_space',
}))
}))
)
) .. (problem or '')
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 931: Line 967:
end
end
if invalid then
if invalid then
result = result .. message('mt-bad-param1', invalid)
result = result .. message('mt-warn-param1', invalid)
end
end
end
end
Line 940: Line 976:
-- Implement [[Template:Death date and age]].
-- Implement [[Template:Death date and age]].
local args = frame:getParent().args
local args = frame:getParent().args
if isFake(args) then
return ''
end
local options = {
local options = {
missing1 = 'mt-need-valid-dd',
missing1 = 'mt-need-valid-dd',
Line 966: Line 1,005:
years = diff.years
years = diff.years
end
end
if years > 150 then
if years > MAX_AGE then
return message('mt-invalid-dates-age')
return message('mt-invalid-dates-age')
end
end
local fmt_date, fmt_ymd
local fmt_date, fmt_ymd, problem
if date1.day then  -- y, m, d known
if date1.day then  -- y, m, d known
fmt_date = dateFormat(args)
problem, fmt_date = dateFormat(args, options)
fmt_ymd = '%-Y-%m-%d'
fmt_ymd = '%-Y-%m-%d'
elseif date1.month then  -- y, m known; d unknown
elseif date1.month then  -- y, m known; d unknown
Line 998: Line 1,037:
sep = 'sep_space',
sep = 'sep_space',
}))
}))
)
) .. (problem or '')
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 1,021: Line 1,060:
end
end
if invalid then
if invalid then
result = result .. message('mt-bad-param1', invalid)
result = result .. message('mt-warn-param1', invalid)
end
end
end
end
Line 1,074: Line 1,113:
local parms = {
local parms = {
extra = makeExtra(args),
extra = makeExtra(args),
wantDuration = yes(args.duration),
wantDuration = yes[args.duration],
range = yes(args.range) or (args.range == 'dash' and 'dash' or nil),
range = yes[args.range] or (args.range == 'dash' and 'dash' or nil),
wantSc = yes(args.sc),
wantSc = yes[args.sc],
}
}
local fix = yes(args.fix) and 'fix' or ''
local fix = yes[args.fix] and 'fix' or ''
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
Line 1,113: Line 1,152:
end
end
return from_en(dateDifference(parms))
return from_en(dateDifference(parms))
end
local function templateGeneric(frame)
-- Example: {{#invoke:age||template=age_days|1 Apr 1980|1 Apr 2080|format=raw}} → 36525
local name = frame.args.template
if not name then
return message('mt-template-x')
end
return ageGeneric(frame:newChild({title = mw.title.new(name, 10), args = frame.args}))
end
end


Line 1,124: Line 1,172:
JULIANDAY = dateToJd,              -- Template:JULIANDAY
JULIANDAY = dateToJd,              -- Template:JULIANDAY
time_interval = timeInterval,      -- Template:Time_interval
time_interval = timeInterval,      -- Template:Time_interval
[''] = templateGeneric,            -- same as age_generic, but can be invoked directly
}
}