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 | |||