Module:Date: Difference between revisions
major refactor with fixes; force Date to be read-only (error on write); list of dates in a month on a particular day of week
(clean up and some aliases) |
(major refactor with fixes; force Date to be read-only (error on write); list of dates in a month on a particular day of week) |
||
| Line 4: | Line 4: | ||
local MINUS = '−' -- Unicode U+2212 MINUS SIGN | local MINUS = '−' -- Unicode U+2212 MINUS SIGN | ||
local Date, DateDiff, | local Date, DateDiff, diffmt -- forward declarations | ||
local uniq = { 'unique identifier' } | |||
local function is_date(t) | local function is_date(t) | ||
return type(t) == 'table' and getmetatable(t) == | -- The system used to make a date read-only means there is no unique | ||
-- metatable that is conveniently accessible to check. | |||
return type(t) == 'table' and t._id == uniq | |||
end | |||
local function is_diff(t) | |||
return type(t) == 'table' and getmetatable(t) == diffmt | |||
end | |||
local function _list_join(list, sep) | |||
return table.concat(list, sep) | |||
end | end | ||
| Line 18: | Line 29: | ||
self[self.n] = item | self[self.n] = item | ||
end, | end, | ||
join = | join = _list_join, | ||
} | } | ||
end | end | ||
| Line 93: | Line 102: | ||
local floor = math.floor | local floor = math.floor | ||
local calname = date.calname | local calname = date.calname | ||
local limits -- min/max limits for date ranges −9999-01-01 to 9999-12-31 | local limits -- min/max limits for date ranges −9999-01-01 to 9999-12-31 | ||
if calname == 'Julian' then | if calname == 'Julian' then | ||
| Line 100: | Line 108: | ||
limits = { -1930999.5, 5373484.49999 } | limits = { -1930999.5, 5373484.49999 } | ||
else | else | ||
return | |||
end | end | ||
if not (limits[1] <= jd and jd <= limits[2]) then | local jd = date.jd | ||
if not (type(jd) == 'number' and limits[1] <= jd and jd <= limits[2]) then | |||
return | return | ||
end | end | ||
| Line 150: | Line 159: | ||
return | return | ||
end | end | ||
local y = numbers. | local y = numbers.year or date.year | ||
local m = numbers. | local m = numbers.month or date.month | ||
local d = numbers. | local d = numbers.day or date.day | ||
local H = numbers. | local H = numbers.hour | ||
local M = numbers. | local M = numbers.minute or date.minute or 0 | ||
local S = numbers. | local S = numbers.second or date.second or 0 | ||
if not (y and m and d) | if not (y and m and d) or not | ||
(-9999 <= y and y <= 9999 and | |||
1 <= m and m <= 12 and | |||
1 <= d and d <= days_in_month(y, m, date.calname)) then | |||
return | return | ||
end | end | ||
| Line 166: | Line 174: | ||
date.hastime = true | date.hastime = true | ||
else | else | ||
H = 0 | H = date.hour or 0 | ||
end | end | ||
if not (0 <= H and H <= 23 and | if not (0 <= H and H <= 23 and | ||
| Line 206: | Line 214: | ||
-- Example: 'am:AM era:BC' | -- Example: 'am:AM era:BC' | ||
for item in options1:gmatch('%S+') do | for item in options1:gmatch('%S+') do | ||
local lhs, rhs = item:match('^(%w+):(.+)$') | local lhs, rhs = item:match('^(%w+)[:=](.+)$') | ||
if lhs then | if lhs then | ||
result[lhs] = rhs | result[lhs] = rhs | ||
| Line 339: | Line 347: | ||
:gsub('%%%%', PERCENT) | :gsub('%%%%', PERCENT) | ||
:gsub('(%s*)%%{(%w+)}', replace_property) | :gsub('(%s*)%%{(%w+)}', replace_property) | ||
:gsub('(%s*)%%(-?)(%a)', replace_code) | :gsub('(%s*)%%(%-?)(%a)', replace_code) | ||
:gsub(PERCENT, '%%') | :gsub(PERCENT, '%%') | ||
) | ) | ||
| Line 345: | Line 353: | ||
local function _date_text(date, fmt, options) | local function _date_text(date, fmt, options) | ||
-- Return formatted string | -- Return a formatted string representing the given date. | ||
if not is_date(date) then | if not is_date(date) then | ||
return 'Need a date (use "date:text()" with a colon).' | return 'Need a date (use "date:text()" with a colon).' | ||
| Line 410: | Line 418: | ||
{ 'Dec', 'December' }, | { 'Dec', 'December' }, | ||
} | } | ||
local function name_to_number(text, translate) | |||
if type(text) == 'string' then | |||
return translate[text:lower()] | |||
end | |||
end | |||
local function day_number(text) | |||
return name_to_number(text, { | |||
sun = 0, sunday = 0, | |||
mon = 1, monday = 1, | |||
tue = 2, tuesday = 2, | |||
wed = 3, wednesday = 3, | |||
thu = 4, thursday = 4, | |||
fri = 5, friday = 5, | |||
sat = 6, saturday = 6, | |||
}) | |||
end | |||
local function month_number(text) | local function month_number(text) | ||
return name_to_number(text, { | |||
jan = 1, january = 1, | |||
feb = 2, february = 2, | |||
mar = 3, march = 3, | |||
apr = 4, april = 4, | |||
may = 5, | |||
jun = 6, june = 6, | |||
jul = 7, july = 7, | |||
aug = 8, august = 8, | |||
sep = 9, september = 9, | |||