Module:Age: Difference between revisions

472 bytes added ,  6 years ago
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
local show = stripToNil(args.show) or 'dmy'
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
local join = options.range == 'dash' and '–' or ' or '
vstr = fmt(v[1]) .. rangeJoin(options.range) .. fmt(v[2])
vstr = fmt(v[1]) .. join .. fmt(v[2])
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 == 'dash' and '–' or ' or ') ..
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 fix = getopt.fix and 'fix' or ''
local partial = getopt.partial and 'partial' 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, partial, y, m, d)
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, partial, fields[1] or 'currentdate')
dates[1] = Date(fix, partialText, fields[1] or 'currentdate')
if not getopt.single then
if not getopt.single then
dates[2] = Date(fix, partial, fields[2] or 'currentdate')
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").
--    Above gives a good result with age in years, but is probably unhelpful for other cases.
--    ("on" is equivalent to "yes", and "off" is equivalent to "no").
--    {{age in years|year1=1900|year2=1910|range=no}} → 10
--    {{age in days|year1=1900|year2=1910|range=no}}  → 4016 (from 1900-01-01 to 1910-12-31)
-- "|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 - date1,
diff = date2:subtract(date1, { fill = autofill }),
wantDuration = spec.duration or yes(args.duration),
wantDuration = spec.duration or yes(args.duration),
range = range,
range = range,
Anonymous user