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) |
m (3 revisions imported from wikipedia:Module:Date: see Topic:Vtixlm0q28eo6jtf) |
||
| (20 intermediate revisions by 4 users not shown) | |||
| Line 3: | Line 3: | ||
local MINUS = '−' -- Unicode U+2212 MINUS SIGN | local MINUS = '−' -- Unicode U+2212 MINUS SIGN | ||
local floor = math.floor | |||
local Date, DateDiff, diffmt -- forward declarations | local Date, DateDiff, diffmt -- forward declarations | ||
| Line 34: | Line 35: | ||
local function strip_to_nil(text) | local function strip_to_nil(text) | ||
-- If text is a string, return its trimmed content, or nil. | -- If text is a string, return its trimmed content, or nil if empty. | ||
-- Otherwise return text (convenient when Date fields are provided from | -- Otherwise return text (convenient when Date fields are provided from | ||
-- another module which | -- another module which may pass a string, a number, or another type). | ||
if type(text) == 'string' then | if type(text) == 'string' then | ||
text = text:match('(%S.-)%s*$') | text = text:match('(%S.-)%s*$') | ||
end | end | ||
return text | return text | ||
end | end | ||
| Line 65: | Line 58: | ||
end | end | ||
return ({ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 })[month] | return ({ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 })[month] | ||
end | |||
local function h_m_s(time) | |||
-- Return hour, minute, second extracted from fraction of a day. | |||
time = floor(time * 24 * 3600 + 0.5) -- number of seconds | |||
local second = time % 60 | |||
time = floor(time / 60) | |||
return floor(time / 60), time % 60, second | |||
end | |||
local function hms(date) | |||
-- Return fraction of a day from date's time, where (0 <= fraction < 1) | |||
-- if the values are valid, but could be anything if outside range. | |||
return (date.hour + (date.minute + date.second / 60) / 60) / 24 | |||
end | end | ||
| Line 76: | Line 83: | ||
-- 1 January 4713 BC = (-4712, 1, 1) Julian calendar | -- 1 January 4713 BC = (-4712, 1, 1) Julian calendar | ||
-- 24 November 4714 BC = (-4713, 11, 24) Gregorian calendar | -- 24 November 4714 BC = (-4713, 11, 24) Gregorian calendar | ||
local offset | local offset | ||
local a = floor((14 - date.month)/12) | local a = floor((14 - date.month)/12) | ||
local y = date.year + 4800 - a | local y = date.year + 4800 - a | ||
if date. | if date.calendar == 'Julian' then | ||
offset = floor(y/4) - 32083 | offset = floor(y/4) - 32083 | ||
else | else | ||
| Line 88: | Line 94: | ||
local jd = date.day + floor((153*m + 2)/5) + 365*y + offset | local jd = date.day + floor((153*m + 2)/5) + 365*y + offset | ||
if date.hastime then | if date.hastime then | ||
jd = jd + (date | jd = jd + hms(date) - 0.5 | ||
return jd, jd | return jd, jd | ||
end | end | ||
| Line 100: | Line 106: | ||
-- This handles the proleptic Julian and Gregorian calendars. | -- This handles the proleptic Julian and Gregorian calendars. | ||
-- Negative Julian dates are not defined but they work. | -- Negative Julian dates are not defined but they work. | ||
local calname = date.calendar | |||
local calname = date. | local low, high -- min/max limits for date ranges −9999-01-01 to 9999-12-31 | ||
local | if calname == 'Gregorian' then | ||
if calname == ' | low, high = -1930999.5, 5373484.49999 | ||
elseif calname == 'Julian' then | |||
elseif calname == ' | low, high = -1931076.5, 5373557.49999 | ||
else | else | ||
return | return | ||
end | end | ||
local jd = date.jd | local jd = date.jd | ||
if not (type(jd) == 'number' and | if not (type(jd) == 'number' and low <= jd and jd <= high) then | ||
return | return | ||
end | end | ||
local jdn = floor(jd) | |||