Module:Age: Difference between revisions
update from sandbox: dates can be "partial" consisting of ymd, ym or y (but yd is invalid); with an invalid date, show=format gives 'error' rather than a run-time error
(update from sandbox: sortable=table; ranges of more time units; no default sort key in Template:Age in years and days; implement Template:Birth date and age; experimental range=no) |
(update from sandbox: dates can be "partial" consisting of ymd, ym or y (but yd is invalid); with an invalid date, show=format gives 'error' rather than a run-time error) |
||
Line 206: | Line 206: | ||
table.insert(parms, 'partial') | table.insert(parms, 'partial') | ||
end | end | ||
local show = stripToNil(args.show) or 'dmy' | |||
local date = Date(unpack(parms)) | local date = Date(unpack(parms)) | ||
if not date then | if not date then | ||
if show == 'format' then | |||
return 'error' | |||
end | |||
return message('Need valid date') | return message('Need valid date') | ||
end | end | ||
Line 225: | Line 229: | ||
prefix = makeSort(value, sortable) | prefix = makeSort(value, sortable) | ||
end | end | ||
if show ~= 'hide' then | if show ~= 'hide' then | ||
result = date[show] | result = date[show] | ||
Line 237: | Line 240: | ||
end | end | ||
return (prefix or '') .. (result or '') | return (prefix or '') .. (result or '') | ||
end | |||
local function rangeJoin(range) | |||
-- Return text to be used between a range of ages. | |||
return range == 'dash' and '–' or ' or ' | |||
end | end | ||
Line 256: | Line 264: | ||
end | end | ||
if islist then | if islist then | ||
vstr = fmt(v[1]) .. rangeJoin(options.range) .. fmt(v[2]) | |||
vstr = fmt(v[1]) .. | |||
else | else | ||
vstr = fmt(v) | vstr = fmt(v) | ||
Line 417: | Line 424: | ||
(textOptions.prefix or '') .. | (textOptions.prefix or '') .. | ||
makeText({ diff.partial.mindiff:age(show.id, diffOptions) }, show, names[abbr], opt) .. | makeText({ diff.partial.mindiff:age(show.id, diffOptions) }, show, names[abbr], opt) .. | ||
(textOptions.range | rangeJoin(textOptions.range) .. | ||
makeText({ diff.partial.maxdiff:age(show.id, diffOptions) }, show, names[abbr], opt) .. | makeText({ diff.partial.maxdiff:age(show.id, diffOptions) }, show, names[abbr], opt) .. | ||
(textOptions.suffix or '') | (textOptions.suffix or '') | ||
Line 429: | Line 436: | ||
-- * date1, date2 (two date tables, if not single) | -- * date1, date2 (two date tables, if not single) | ||
-- * text (a string error message) | -- * text (a string error message) | ||
-- A missing date is replaced with the current date. | -- A missing date is optionally replaced with the current date. | ||
-- If wantMixture is true, a missing date component is replaced | -- If wantMixture is true, a missing date component is replaced | ||
-- from the current date, so can get a bizarre mixture of | -- from the current date, so can get a bizarre mixture of | ||
Line 436: | Line 443: | ||
local Date, currentDate = getExports(frame) | local Date, currentDate = getExports(frame) | ||
getopt = getopt or {} | getopt = getopt or {} | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
local fields = {} | local fields = {} | ||
Line 462: | Line 467: | ||
end | end | ||
end | end | ||
local fix = getopt.fix and 'fix' or '' | |||
local noDefault = imax == 0 and getopt.noMissing | local noDefault = imax == 0 and getopt.noMissing | ||
local partialText = getopt.partial and 'partial' or '' | |||
local dates = {} | local dates = {} | ||
if isNamed or imax >= 3 then | if isNamed or imax >= 3 then | ||
Line 477: | Line 484: | ||
end | end | ||
else | else | ||
-- If partial dates are allowed, accept | |||
-- year only, or | |||
-- year and month only | |||
-- Do not accept year and day without a month because that makes no sense | |||
-- (and because, for example, Date('partial', 2001, nil, 12) sets day = nil, not 12). | |||
for i = 1, nrDates do | for i = 1, nrDates do | ||
local index = i == 1 and 1 or 4 | local index = i == 1 and 1 or 4 | ||
local y, m, d = fields[index], fields[index+1], fields[index+2] | local y, m, d = fields[index], fields[index+1], fields[index+2] | ||
if (partial and y) or (y and m and d) then | if (getopt.partial and y and (m or not d)) or (y and m and d) then | ||
dates[i] = Date(fix, | dates[i] = Date(fix, partialText, y, m, d) | ||
elseif not y and not m and not d and not noDefault then | elseif not y and not m and not d and not noDefault then | ||
dates[i] = Date('currentdate') | dates[i] = Date('currentdate') | ||
Line 489: | Line 501: | ||
elseif not noDefault then | elseif not noDefault then | ||
getopt.textdates = true -- have parsed each date from a single text field | getopt.textdates = true -- have parsed each date from a single text field | ||
dates[1] = Date(fix, | dates[1] = Date(fix, partialText, fields[1] or 'currentdate') | ||
if not getopt.single then | if not getopt.single then | ||
dates[2] = Date(fix, | dates[2] = Date(fix, partialText, fields[2] or 'currentdate') | ||
end | end | ||
end | end | ||
Line 617: | Line 629: | ||
end | end | ||
end | end | ||
local partial | local partial, autofill | ||
local range = stripToNil(args.range) or spec.range | local range = stripToNil(args.range) or spec.range | ||
if range then | if range then | ||
Line 623: | Line 635: | ||
-- "|range=" (empty value) has no effect (spec is used). | -- "|range=" (empty value) has no effect (spec is used). | ||
-- "|range=yes" or spec.range == true sets range = true (gives "11 or 12") | -- "|range=yes" or spec.range == true sets range = true (gives "11 or 12") | ||
-- "|range=dash" sets range = 'dash' (gives "11–12"). | -- "|range=dash" or spec.range == 'dash' sets range = 'dash' (gives "11–12"). | ||
-- "|range=no" sets range = nil (gives "12"). | -- "|range=no" or spec.range == 'no' sets range = nil and fills each date in the diff (gives "12"). | ||
-- | -- ("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', 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 | ||
if range == 'no' then | if range == 'no' then | ||
autofill = true -- missing month/day in first or second date are filled from other date or 1 | |||
range = nil | range = nil | ||
end | end | ||
Line 653: | Line 664: | ||
end | end | ||
local parms = { | local parms = { | ||
diff = date2 | diff = date2:subtract(date1, { fill = autofill }), | ||
wantDuration = spec.duration or yes(args.duration), | wantDuration = spec.duration or yes(args.duration), | ||
range = range, | range = range, |