Difference between revisions of "Module:Age/sandbox"
Jump to navigation
Jump to search
blackwiki>Johnuniq (does unpack work on args?) |
blackwiki>Johnuniq (prove it doesn't) |
||
Line 210: | Line 210: | ||
-- The word 'Julian' is accepted for the Julian calendar. | -- The word 'Julian' is accepted for the Julian calendar. | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
+ | if unpack(args) == nil then return 'unpack(args) is nil' end | ||
local date = Date(unpack(args)) | local date = Date(unpack(args)) | ||
if date then | if date then |
Revision as of 07:13, 29 May 2016
Documentation for this module may be created at Module:Age/sandbox/doc
-- Implement various "age of" and other date-related templates.
local datemod = require('Module:Date')
local current = datemod._current
local Date = datemod._Date
local MINUS = '−' -- Unicode U+2212 MINUS SIGN
local function strip_to_nil(text)
-- If text is a string, return its trimmed content, or nil if empty.
-- Otherwise return text (which may, for example, be nil).
if type(text) == 'string' then
text = text:match('(%S.-)%s*$')
end
return text
end
local function number_name(number, singular, plural, sep)
-- Return the given number, converted to a string, with the
-- separator (default space) and singular or plural name appended.
plural = plural or (singular .. 's')
sep = sep or ' '
return tostring(number) .. sep .. ((number == 1) and singular or plural)
end
local function message(msg, nocat)
-- 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" />'
local category
if not nocat and mw.title.getCurrentTitle():inNamespaces(0, 10) then
-- Category only in namespaces: 0=article, 10=template.
category = '[[Category:Age error]]'
else
category = ''
end
return anchor ..
'<strong class="error">Error: ' ..
msg ..
'</strong>' ..
category .. '\n'
end
local function date_component(named, positional, component)
-- Return the first of the two arguments (named like {{example|year=2001}}
-- or positional like {{example|2001}}) that is not nil and is not empty.
-- If both are nil, return the current date component, if specified.
-- This translates empty arguments passed to the template to nil, and
-- optionally replaces a nil argument with a value from the current date.
named = strip_to_nil(named)
if named then
return named
end
positional = strip_to_nil(positional)
if positional then
return positional
end
if component then
return current[component]
end
return nil
end
local function get_dates(frame, want_mixture)
-- Return date1, date2 from template parameters.
-- Either may be nil if given arguments are invalid.
-- If want_mixture is true, a missing date component is replaced
-- from the current date, so can get a bizarre mixture of
-- specified/current y/m/d as has been done by some "age" templates.
-- TODO Accept a date as a string like "1 April 2016".
local date1, date2
local args = frame:getParent().args
if want_mixture then
date1 = Date(
date_component(args.year1 , args[1], 'year' ),
date_component(args.month1, args[2], 'month'),
date_component(args.day1 , args[3], 'day' )
)
date2 = Date(
date_component(args.year2 , args[4], 'year' ),
date_component(args.month2, args[5], 'month'),
date_component(args.day2 , args[6], 'day' )
)
else
local fields = {}
for i = 1, 6 do
fields[i] = strip_to_nil(args[i])
end
date1 = Date(fields[1], fields[2], fields[3])
if fields[4] and fields[5] and fields[6] then
date2 = Date(fields[4], fields[5], fields[6])
else
date2 = Date('currentdate')
end
end
return date1, date2
end
local function age_days(frame)
-- Return age in days between two given dates, or
-- between given date and current date.
-- This code implements the logic in [[Template:Age in days]].
-- Like {{Age in days}}, a missing argument is replaced from the current
-- date, so can get a bizarre mixture of specified/current y/m/d.
local date1, date2 = get_dates(frame, true)
if not (date1 and date2) then
return message('Need valid year, month, day')
end
local sign = ''
local result = date2.jd - date1.jd
if result < 0 then
sign = '−'
result = -result
end
return sign .. tostring(result)
end
local function _age_ym(diff)
-- Return text specifying date difference in years, months.
local sign = diff.isnegative and MINUS or ''
local years, months = diff:age('ym')
local mtext = number_name(months, 'month')
local result
if years > 0 then
local ytext = number_name(years, 'year')
if months == 0 then
result = ytext
else
result = ytext .. ', ' .. mtext
end
else
if months == 0 then
sign = ''
end
result = mtext
end
return sign .. result
end
local function age_ym(frame)
-- Return age in years and months between two given dates, or
-- between given date and current date.
-- The older date is usually first; result is negative if the first is newer.
local date1, date2 = get_dates(frame, false)
if not date1 then
return message('Need valid year, month, day')
end
if not date2 then
return message('Second date should be year, month, day')
end
return _age_ym(date2 - date1)
end
--[[ TODO
All these templates usually have the older date first (otherwise result is negative).
* = date1, date2 positional; date2 defaults to current
age_days(frame) * also accepts named y,m,d and text dates
age_years(frame) *
age_yd(frame) * also accepts text dates
age_ym(frame) *
age_ymd(frame) * also accepts named y,m,d; can omit d for "or"
age_ymwd(frame) . named only; defaults to current
]]
local function age_years(frame)
-- TODO d1, d2 positional; d2 defaults to current; usually d1 < d2
end
local function age_yd(frame)
-- TODO
end
local function age_ymd(frame)
-- TODO
end
local function age_ymwd(frame)
-- TODO
end
local function gsd_ymd(frame)
-- Return Gregorian serial date of the given date, or the current date.
-- Like {{Gregorian serial date}}, a missing argument is replaced from the
-- current date, so can get a bizarre mixture of specified/current y/m/d.
-- This also accepts positional arguments, although the original template does not.
-- The returned value is negative for dates before 1 January 1 AD despite
-- the fact that GSD is not defined for earlier dates.
local args = frame:getParent().args
local date = Date(
date_component(args.year , args[1], 'year' ),
date_component(args.month, args[2], 'month'),
date_component(args.day , args[3], 'day' )
)
if date then
return tostring(date.gsd)
end
return message('Need valid year, month, day')
end
local function ymd_from_jd(frame)
-- Return formatted date from a Julian date.
-- The result is y-m-d or y-m-d H:M:S if input includes a fraction.
-- The word 'Julian' is accepted for the Julian calendar.
local args = frame:getParent().args
local date = Date('juliandate', args[1], args[2])
if date then
return date:text()
end
return message('Need valid Julian date number')
end
local function ymd_to_jd(frame)
-- Return Julian date (a number) from a date (y-m-d), or datetime (y-m-d H:M:S),
-- or the current date ('currentdate') or current datetime ('currentdatetime').
-- The word 'Julian' is accepted for the Julian calendar.
local args = frame:getParent().args
if unpack(args) == nil then return 'unpack(args) is nil' end
local date = Date(unpack(args))
if date then
return tostring(date.jd)
end
return message('Need valid year/month/day or "currentdate"')
end
return {
age_days = age_days,
age_years = age_years,
age_yd = age_yd,
age_ym = age_ym,
age_ymd = age_ymd,
age_ymwd = age_ymwd,
gsd = gsd_ymd,
JULIANDAY = ymd_to_jd,
ymd_from_jd = ymd_from_jd,
ymd_to_jd = ymd_to_jd,
}