Editing Module:Age
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
-- Implement various "age of" and other date-related templates. | -- Implement various "age of" and other date-related templates. | ||
local _Date, _current_date | |||
local function get_exports(frame) | |||
local _Date, | |||
local function | |||
-- Return objects exported from the date module or its sandbox. | -- Return objects exported from the date module or its sandbox. | ||
if not _Date then | if not _Date then | ||
local sandbox = frame:getTitle():find( | local sandbox = frame:getTitle():find('sandbox', 1, true) and '/sandbox' or '' | ||
local datemod = require( | local datemod = require('Module:Date' .. sandbox) | ||
_Date = datemod._Date | |||
_current_date = datemod._current | |||
end | end | ||
return _Date, | return _Date, _current_date | ||
end | end | ||
local | local function collection() | ||
-- Return a table to hold items. | |||
return { | |||
n = 0, | |||
add = function (self, item) | |||
self.n = self.n + 1 | self.n = self.n + 1 | ||
self[self.n] = item | self[self.n] = item | ||
end, | |||
join = function (self, sep) | |||
return table.concat(self, sep) | |||
end, | |||
} | |||
end | |||
local function | local function strip_to_nil(text) | ||
-- If text is a string, return its trimmed content, or nil if empty. | -- If text is a string, return its trimmed content, or nil if empty. | ||
-- Otherwise return text (which may, for example, be nil). | -- Otherwise return text (which may, for example, be nil). | ||
Line 116: | Line 34: | ||
end | end | ||
return text | return text | ||
end | end | ||
Line 138: | Line 43: | ||
end | end | ||
local function message(msg, | local function message(msg, nocat) | ||
-- Return formatted message text for an error | -- Return formatted message text for an error. | ||
-- Can append "#FormattingError" to URL of a page with a problem to find it. | |||
local anchor = '<span id="FormattingError"></span>' | |||
local category | |||
local | if not nocat and mw.title.getCurrentTitle():inNamespaces(0, 10) then | ||
-- Category only in namespaces: 0=article, 10=template. | |||
category = '[[Category:Age error]]' | |||
local | |||
else | else | ||
category = '' | |||
end | end | ||
return anchor .. | |||
'<strong class="error">Error: ' .. | |||
mw.text.nowiki(msg) .. | |||
'</strong>' .. | |||
category | |||
mw.text.nowiki( | |||
end | end | ||
local function | local function formatnumber(number) | ||
-- Return the given number formatted with commas as group separators, | -- Return the given number formatted with commas as group separators, | ||
-- given that the number is an integer. | -- given that the number is an integer. | ||
local numstr = tostring(number) | local numstr = tostring(number) | ||
local length = #numstr | local length = #numstr | ||
local places = | local places = collection() | ||
local pos = 0 | local pos = 0 | ||
repeat | repeat | ||
Line 181: | Line 73: | ||
until pos >= length | until pos >= length | ||
places:add(length) | places:add(length) | ||
local groups = | local groups = collection() | ||
for i = places.n, 2, -1 do | for i = places.n, 2, -1 do | ||
local p1 = length - places[i] + 1 | local p1 = length - places[i] + 1 | ||
Line 190: | Line 82: | ||
end | end | ||
local function | local function make_sort(value, sortable) | ||
-- Return a sort key in a span if specified. | |||
-- Return a sort key if | |||
-- Assume value is a valid number which has not overflowed. | -- Assume value is a valid number which has not overflowed. | ||
if | if sortable == 'sortable_on' or sortable == 'sortable_debug' then | ||
local | local sortkey | ||
if value == 0 then | if value == 0 then | ||
sortkey = '5000000000000000000' | |||
else | else | ||
local mag = math.floor(math.log10(math.abs(value)) + 1e-14) | local mag = math.floor(math.log10(math.abs(value)) + 1e-14) | ||
local prefix | |||
if value > 0 then | if value > 0 then | ||
prefix = 7000 + mag | |||
else | else | ||
prefix = 2999 - mag | |||
value = value + 10^(mag+1) | value = value + 10^(mag+1) | ||
end | end | ||
sortkey = string.format('%d', prefix) .. string.format('%015.0f', math.floor(value * 10^(14-mag))) | |||
end | end | ||
local | local lhs = sortable == 'sortable_debug' and | ||
'<span style="border:1px solid;display:inline;" class="sortkey">' or | |||
'<span style="display:none" class="sortkey">' | |||
return lhs .. sortkey .. '♠</span>' | |||
return | |||
end | end | ||
end | end | ||
local | local translate_parameters = { | ||
abbr = { | abbr = { | ||
off = 'abbr_off', | off = 'abbr_off', | ||
Line 285: | Line 141: | ||
ymw = { 'y', 'm', 'w', id = 'ymw' }, | ymw = { 'y', 'm', 'w', id = 'ymw' }, | ||
ymwd = { 'y', 'm', 'w', 'd', id = 'ymwd' }, | ymwd = { 'y', 'm', 'w', 'd', id = 'ymwd' }, | ||
yd = { 'y', 'd', id = 'yd', | yd = { 'y', 'd', id = 'yd', keepzero = true }, | ||
m = { 'm', id = 'm' }, | m = { 'm', id = 'm' }, | ||
md = { 'm', 'd', id = 'md' }, | md = { 'm', 'd', id = 'md' }, | ||
Line 292: | Line 148: | ||
h = { 'H', id = 'h' }, | h = { 'H', id = 'h' }, | ||
hm = { 'H', 'M', id = 'hm' }, | hm = { 'H', 'M', id = 'hm' }, | ||
d = { 'd', id = 'd' }, | d = { 'd', id = 'd' }, | ||
dh = { 'd', 'H', id = 'dh' }, | dh = { 'd', 'H', id = 'dh' }, | ||
dhm = { 'd', 'H', 'M', id = 'dhm' }, | dhm = { 'd', 'H', 'M', id = 'dhm' }, | ||
ymdh = { 'y', 'm', 'd', 'H', id = 'ymdh' }, | ymdh = { 'y', 'm', 'd', 'H', id = 'ymdh' }, | ||
ymdhm = { 'y', 'm', 'd', 'H', 'M', id = 'ymdhm' }, | ymdhm = { 'y', 'm', 'd', 'H', 'M', id = 'ymdhm' }, | ||
Line 307: | Line 159: | ||
off = false, | off = false, | ||
on = 'sortable_on', | on = 'sortable_on', | ||
debug = 'sortable_debug', | debug = 'sortable_debug', | ||
}, | }, | ||
} | } | ||
local function date_extract(frame) | |||
local function | |||
-- Return part of a date after performing an optional operation. | -- Return part of a date after performing an optional operation. | ||
local Date = | local Date = get_exports(frame) | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
local parms = {} | local parms = {} | ||
Line 337: | Line 177: | ||
table.insert(parms, 'partial') | table.insert(parms, 'partial') | ||
end | end | ||
local date = Date(unpack(parms)) | local date = Date(unpack(parms)) | ||
if not date then | if not date then | ||
return message('Need valid date') | |||
return message(' | |||
end | end | ||
local add = | local add = strip_to_nil(args.add) | ||
if add then | if add then | ||
for item in add:gmatch('%S+') do | for item in add:gmatch('%S+') do | ||
date = date + item | date = date + item | ||
if not date then | if not date then | ||
return message(' | return message('Cannot add "' .. item .. '"') | ||
end | end | ||
end | end | ||
end | end | ||
local | local prefix, result | ||
local sortable = | local sortable = translate_parameters.sortable[args.sortable] | ||
if sortable then | if sortable then | ||
local value = (date.partial and date.partial.first or date).jdz | local value = (date.partial and date.partial.first or date).jdz | ||
prefix = make_sort(value, sortable) | |||
end | end | ||
local show = strip_to_nil(args.show) or 'dmy' | |||
if show ~= 'hide' then | if show ~= 'hide' then | ||
result = date[show] | result = date[show] | ||
if result == nil then | if result == nil then | ||
result = | result = 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 = | result = tostring(result) | ||
end | end | ||
end | end | ||
return ( | return (prefix or '') .. (result or '') | ||
end | end | ||
local function | local function make_text(values, components, names, options) | ||
-- Return wikitext representing an age or duration. | -- Return wikitext representing an age or duration. | ||
local text = | local text = collection() | ||
local count = #values | local count = #values | ||
local sep = names.sep or '' | local sep = names.sep or '' | ||
Line 386: | Line 218: | ||
-- v is a number (say 4 for 4 years), or a table ({4,5} for 4 or 5 years). | -- v is a number (say 4 for 4 years), or a table ({4,5} for 4 or 5 years). | ||
local islist = type(v) == 'table' | local islist = type(v) == 'table' | ||
if (islist or v > 0) or (text.n == 0 and i == count) or (text.n > 0 and components. | if (islist or v > 0) or (text.n == 0 and i == count) or (text.n > 0 and components.keepzero) then | ||
local fmt, vstr | local fmt, vstr | ||
if | if i == 1 and options.format == 'format_commas' then | ||
-- Numbers after the first should be small and not need formatting. | -- Numbers after the first should be small and not need formatting. | ||
fmt = | fmt = formatnumber | ||
else | else | ||
fmt = tostring | fmt = tostring | ||
end | end | ||
if islist then | if islist then | ||
vstr = fmt(v[1]) .. | local join = options.range == 'dash' and '–' or ' or ' | ||
vstr = fmt(v[1]) .. join .. fmt(v[2]) | |||
else | else | ||
vstr = fmt(v) | vstr = fmt(v) | ||
Line 407: | Line 234: | ||
local name = names[components[i]] | local name = names[components[i]] | ||
if name then | if name then | ||
local plural = names.plural | |||
if not plural or (islist and v[2] or v) == 1 then | |||
plural = '' | |||
end | end | ||
text:add(vstr .. sep .. name) | text:add(vstr .. sep .. name .. plural) | ||
else | else | ||
text:add(vstr) | text:add(vstr) | ||
Line 425: | Line 253: | ||
elseif options.join == 'sep_serialcomma' and text.n > 2 then | elseif options.join == 'sep_serialcomma' and text.n > 2 then | ||
first = ', ' | first = ', ' | ||
last = | last = ', and ' | ||
else | else | ||
first = ', ' | first = ', ' | ||
last = | last = ' and ' | ||
end | end | ||
for i, v in ipairs(text) do | for i, v in ipairs(text) do | ||
Line 447: | Line 275: | ||
end | end | ||
return | return | ||
(options. | (options.prefix or '') .. | ||
sign .. | sign .. | ||
text:join() .. | text:join() .. | ||
Line 454: | Line 281: | ||
end | end | ||
local function | local function date_difference(parms) | ||
-- Return a formatted date difference using the given parameters | -- Return a formatted date difference using the given parameters | ||
-- which have been validated. | -- which have been validated. | ||
local names = { | local names = { | ||
abbr_off = { | abbr_off = { | ||
plural = 's', | |||
sep = ' ', | sep = ' ', | ||
y = | y = 'year', | ||
m = | m = 'month', | ||
w = | w = 'week', | ||
d = | d = 'day', | ||
H = | H = 'hour', | ||
M = | M = 'minute', | ||
}, | }, | ||
abbr_on = { | abbr_on = { | ||
Line 479: | Line 302: | ||
H = 'h', | H = 'h', | ||
M = 'm', | M = 'm', | ||
}, | }, | ||
abbr_infant = { -- for {{age for infant}} | abbr_infant = { -- for {{age for infant}} | ||
plural = 's', | |||
sep = ' ', | sep = ' ', | ||
y = | y = 'yr', | ||
m = | m = 'mo', | ||
w = | w = 'wk', | ||
d = | d = 'day', | ||
H = | H = 'hr', | ||
M = | M = 'min', | ||
}, | }, | ||
abbr_raw = {}, | abbr_raw = {}, | ||
Line 496: | Line 318: | ||
local show = parms.show -- may be nil; default is set below | local show = parms.show -- may be nil; default is set below | ||
local abbr = parms.abbr or 'abbr_off' | local abbr = parms.abbr or 'abbr_off' | ||
local | local default_join | ||
if abbr ~= 'abbr_off' then | if abbr ~= 'abbr_off' then | ||
default_join = 'sep_space' | |||
end | end | ||
if not show then | if not show then | ||
Line 504: | Line 326: | ||
if parms.disp == 'disp_age' then | if parms.disp == 'disp_age' then | ||
if diff.years < 3 then | if diff.years < 3 then | ||
default_join = 'sep_space' | |||
if diff.years >= 1 then | if diff.years >= 1 then | ||
show = 'ym' | show = 'ym' | ||
Line 516: | Line 338: | ||
end | end | ||
if type(show) ~= 'table' then | if type(show) ~= 'table' then | ||
show = | show = translate_parameters.show[show] | ||
end | end | ||
if parms.disp == 'disp_raw' then | if parms.disp == 'disp_raw' then | ||
default_join = 'sep_space' | |||
abbr = 'abbr_raw' | abbr = 'abbr_raw' | ||
elseif parms. | elseif parms.want_sc then | ||
default_join = 'sep_serialcomma' | |||
end | end | ||
local | local diff_options = { | ||
round = parms.round, | round = parms.round, | ||
duration = parms. | duration = parms.want_duration, | ||
range = parms.range and true or nil, | range = parms.range and true or nil, | ||
} | } | ||
local | local prefix | ||
if parms.sortable then | if parms.sortable then | ||
local value = diff.age_days + (parms. | local value = diff.age_days + (parms.want_duration and 1 or 0) -- days and fraction of a day | ||
if diff.isnegative then | if diff.isnegative then | ||
value = -value | value = -value | ||
end | end | ||
prefix = make_sort(value, parms.sortable) | |||
end | end | ||
local | local text_options = { | ||
prefix = prefix, | |||
suffix = parms.suffix, -- not currently used | |||
format = parms.format, | format = parms.format, | ||
join = parms.sep or | join = parms.sep or default_join, | ||
isnegative = diff.isnegative, | isnegative = diff.isnegative, | ||
range = parms.range, | range = parms.range, | ||
} | } | ||
if show.id == 'hide' then | if show.id == 'hide' then | ||
return | return prefix or '' | ||
end | end | ||
local values = { diff:age(show.id, | local values = { diff:age(show.id, diff_options) } | ||
if values[1] then | if values[1] then | ||
return | return make_text(values, show, names[abbr], text_options) | ||
end | end | ||
return message('Parameter show=' .. show.id .. ' is not supported here') | |||
end | end | ||
local function | local function get_dates(frame, getopt) | ||
-- Parse template parameters and return one of: | -- Parse template parameters and return one of: | ||
-- * date (a date table, if single) | -- * date (a date table, if single) | ||
-- * 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 | -- A missing date is replaced with the current date. | ||
-- If | -- If want_mixture 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 | ||
-- specified/current y/m/d as has been done by some "age" templates. | -- specified/current y/m/d as has been done by some "age" templates. | ||
-- Some results may be placed in table getopt. | -- Some results may be placed in table getopt. | ||
local Date, | local Date, current_date = get_exports(frame) | ||
getopt = getopt or {} | getopt = getopt or {} | ||
local | local fix = getopt.fix and 'fix' or '' | ||
local partial = getopt.range and 'partial' or '' | |||
local args = frame:getParent().args | local args = frame:getParent().args | ||
local fields = {} | local fields = {} | ||
local | local is_named = args.year or args.year1 or args.year2 or | ||
args.month or args.month1 or args.month2 or | args.month or args.month1 or args.month2 or | ||
args.day or args.day1 or args.day2 | args.day or args.day1 or args.day2 | ||
if | if is_named then | ||
fields[1] = args.year1 or args.year | fields[1] = args.year1 or args.year | ||
fields[2] = args.month1 or args.month | fields[2] = args.month1 or args.month | ||
Line 620: | Line 410: | ||
local imax = 0 | local imax = 0 | ||
for i = 1, 6 do | for i = 1, 6 do | ||
fields[i] = | fields[i] = strip_to_nil(fields[i]) | ||
if fields[i] then | if fields[i] then | ||
imax = i | imax = i | ||
end | end | ||
end | end | ||
local | local single = getopt.single | ||
local dates = {} | local dates = {} | ||
if | if is_named or imax > 2 then | ||
local | local nr_dates = single and 1 or 2 | ||
if getopt. | if getopt.want_mixture then | ||
-- Cannot be partial since empty fields are set from current. | -- Cannot be partial since empty fields are set from current. | ||
local components = { 'year', 'month', 'day' } | local components = { 'year', 'month', 'day' } | ||
for i = 1, | for i = 1, nr_dates * 3 do | ||
fields[i] = fields[i] or | fields[i] = fields[i] or current_date[components[i > 3 and i - 3 or i]] | ||
end | end | ||
for i = 1, | for i = 1, nr_dates do | ||
local index = i == 1 and 1 or 4 | local index = i == 1 and 1 or 4 | ||
dates[i] = Date(fields[index], fields[index+1], fields[index+2]) | |||
end | end | ||
else | else | ||
for i = 1, nr_dates do | |||
for i = 1, | |||
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 ( | if (partial and y) or (y and m and d) then | ||
dates[i] = Date(fix, | dates[i] = Date(fix, partial, y, m, d) | ||
elseif not y | elseif not (y or m or d) then | ||
dates[i] = Date( | dates[i] = Date('currentdate') | ||
end | end | ||
end | end | ||
end | end | ||
else | else | ||
getopt.textdates = true | getopt.textdates = true | ||
dates[1] = Date(fix, | dates[1] = Date(fix, partial, fields[1] or 'currentdate') | ||
if not | if not single then | ||
dates[2] = Date(fix, | dates[2] = Date(fix, partial, fields[2] or 'currentdate') | ||
end | end | ||
end | end | ||
if not dates[1] then | if not dates[1] then | ||
return message( | return message('Need valid year, month, day') | ||
end | end | ||
if | if single then | ||
return dates[1] | return dates[1] | ||
end | end | ||
if not dates[2] then | if not dates[2] then | ||
return message( | return message('Second date should be year, month, day') | ||
end | end | ||
return dates[1], dates[2] | return dates[1], dates[2] | ||
end | end | ||
local function | local function age_generic(frame) | ||
-- Return the result required by the specified template. | -- Return the result required by the specified template. | ||
-- Can use sortable=x where x = on | -- Can use sortable=x where x = on/off/debug in any supported template. | ||
-- Some templates default to sortable=on but can be overridden. | -- Some templates default to sortable=on but can be overridden with sortable=off. | ||
local name = frame.args.template | local name = frame.args.template | ||
if not name then | if not name then | ||
return message(' | return message('The template invoking this must have "|template=x" where x is the wanted operation') | ||
end | end | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
Line 727: | Line 494: | ||
show = 'y', | show = 'y', | ||
abbr = 'abbr_raw', | abbr = 'abbr_raw', | ||
}, | }, | ||
age_full_years_nts = { -- {{age nts}} | age_full_years_nts = { -- {{age nts}} | ||
Line 771: | Line 535: | ||
age_yd = { -- {{age in years and days}} | age_yd = { -- {{age in years and days}} | ||
show = 'yd', | show = 'yd', | ||
sep = args.sep ~= 'and' and 'sep_comma' or nil, | sep = args.sep ~= 'and' and 'sep_comma' or nil, | ||
sortable = 'on', | sortable = 'on', | ||
Line 790: | Line 548: | ||
age_ymwd = { -- {{age in years, months, weeks and days}} | age_ymwd = { -- {{age in years, months, weeks and days}} | ||
show = 'ymwd', | show = 'ymwd', | ||
want_mixture = true, | |||
}, | }, | ||
} | } | ||
local spec = specs[name] | local spec = specs[name] | ||
if not spec then | if not spec then | ||
return message(' | return message('The specified template name is not valid') | ||
end | end | ||
if name == 'age_days' then | if name == 'age_days' then | ||
local su = | local su = strip_to_nil(args['show unit']) | ||
if su then | if su then | ||
if su == 'abbr' or su == 'full' then | if su == 'abbr' or su == 'full' then | ||
Line 806: | Line 564: | ||
end | end | ||
end | end | ||
local range = spec.range or yes(args.range) or (args.range == 'dash' and 'dash' or nil) | |||
local range = | |||
local getopt = { | local getopt = { | ||
fix = yes(args.fix), | fix = yes(args.fix), | ||
range = range, | |||
want_mixture = spec.want_mixture, | |||
} | } | ||
local date1, date2 = | local date1, date2 = get_dates(frame, getopt) | ||
if type(date1) == 'string' then | if type(date1) == 'string' then | ||
return date1 | return date1 | ||
end | end | ||
local format = | local format = strip_to_nil(args.format) | ||
if format then | if format then | ||
format = 'format_' .. format | format = 'format_' .. format | ||
Line 844: | Line 581: | ||
end | end | ||
local parms = { | local parms = { | ||
diff = date2 | diff = date2 - date1, | ||
want_duration = spec.duration or yes(args.duration), | |||
range = range, | range = range, | ||
want_sc = 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, | ||
disp = spec.disp, | disp = spec.disp, | ||
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 = | sortable = translate_parameters.sortable[args.sortable or spec.sortable], | ||
} | } | ||
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(' | return message('The second date should not be before the first date') | ||
end | end | ||
return | return date_difference(parms) | ||
end | end | ||
local function | local function date_to_gsd(frame) | ||
-- | -- This implements {{gregorian serial date}}. | ||
-- Return Gregorian serial date of the given date, or the current date. | -- Return Gregorian serial date of the given date, or the current date. | ||
-- The returned value is negative for dates before 1 January 1 AD | -- The returned value is negative for dates before 1 January 1 AD | ||
-- despite the fact that GSD is not defined for such dates. | -- despite the fact that GSD is not defined for such dates. | ||
local date = | local date = get_dates(frame, { want_mixture=true, single=true }) | ||
if type(date) == 'string' then | if type(date) == 'string' then | ||
return date | return date | ||
Line 1,033: | Line 611: | ||
end | end | ||
local function | local function jd_to_date(frame) | ||
-- Return formatted date from a Julian date. | -- Return formatted date from a Julian date. | ||
-- The result includes a time if the input includes a fraction. | -- The result includes a time if the input includes a fraction. | ||
-- The word 'Julian' is accepted for the Julian calendar. | -- The word 'Julian' is accepted for the Julian calendar. | ||
local Date = | local Date = get_exports(frame) | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
local date = Date('juliandate', args[1], args[2]) | local date = Date('juliandate', args[1], args[2]) | ||
if date then | if date then | ||
return | return date:text() | ||
end | end | ||
return message(' | return message('Need valid Julian date number') | ||
end | end | ||
local function | local function date_to_jd(frame) | ||
-- Return Julian date (a number) from a date which may include a time, | -- Return Julian date (a number) from a date which may include a time, | ||
-- or the current date ('currentdate') or current date and time ('currentdatetime'). | -- or the current date ('currentdate') or current date and time ('currentdatetime'). | ||
-- The word 'Julian' is accepted for the Julian calendar. | -- The word 'Julian' is accepted for the Julian calendar. | ||
local Date = | local Date = get_exports(frame) | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
local date = Date(args[1], args[2], args[3], args[4], args[5], args[6], args[7]) | local date = Date(args[1], args[2], args[3], args[4], args[5], args[6], args[7]) | ||
Line 1,056: | Line 634: | ||
return tostring(date.jd) | return tostring(date.jd) | ||
end | end | ||
return message(' | return message('Need valid year/month/day or "currentdate"') | ||
end | end | ||
local function | local function time_interval(frame) | ||
-- | -- This implements {{time interval}}. | ||
-- There are two positional arguments: date1, date2. | -- There are two positional arguments: date1, date2. | ||
-- The default for each is the current date and time. | -- The default for each is the current date and time. | ||
-- Result is date2 - date1 formatted. | -- Result is date2 - date1 formatted. | ||
local Date = | local Date = get_exports(frame) | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
local parms = { | local parms = { | ||
want_duration = 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), | ||
want_sc = yes(args.sc), | |||
} | } | ||
local fix = yes(args.fix) and 'fix' or '' | local fix = yes(args.fix) and 'fix' or '' | ||
local date1 = Date(fix, 'partial', | local date1 = Date(fix, 'partial', strip_to_nil(args[1]) or 'currentdatetime') | ||
if not date1 then | if not date1 then | ||
return message(' | return message('Invalid start date in first parameter') | ||
end | end | ||
local date2 = Date(fix, 'partial', | local date2 = Date(fix, 'partial', strip_to_nil(args[2]) or 'currentdatetime') | ||
if not date2 then | if not date2 then | ||
return message(' | return message('Invalid end date in second parameter') | ||
end | end | ||
parms.diff = date2 - date1 | parms.diff = date2 - date1 | ||
for argname, translate in pairs( | for argname, translate in pairs(translate_parameters) do | ||
local parm = | local parm = strip_to_nil(args[argname]) | ||
if parm then | if parm then | ||
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(' | return message('Parameter ' .. argname .. '=' .. args[argname] .. ' is invalid') | ||
end | end | ||
parms[argname] = parm | parms[argname] = parm | ||
Line 1,098: | Line 675: | ||
if show then | if show then | ||
if show.id ~= round then | if show.id ~= round then | ||
return message(' | return message('Parameter show=' .. args.show .. ' conflicts with round=' .. args.round) | ||
end | end | ||
else | else | ||
parms.show = | parms.show = translate_parameters.show[round] | ||
end | end | ||
end | end | ||
parms.round = true | parms.round = true | ||
end | end | ||
return | return date_difference(parms) | ||
end | end | ||
return { | return { | ||
age_generic = | age_generic = age_generic, -- can emulate several age templates | ||
gsd = date_to_gsd, -- Template:Gregorian_serial_date | |||
extract = date_extract, -- Template:Extract | |||
gsd = | jd_to_date = jd_to_date, -- Template:? | ||
extract = | JULIANDAY = date_to_jd, -- Template:JULIANDAY | ||
jd_to_date = | time_interval = time_interval, -- Template:Time_interval | ||
JULIANDAY = | |||
time_interval = | |||
} | } |