Module:Date: Difference between revisions
m
Reverted edits by 181.112.152.222 (talk) to last version by Johnuniq
(repaired) |
m (Reverted edits by 181.112.152.222 (talk) to last version by Johnuniq) |
||
| Line 1: | Line 1: | ||
-- Date functions for use by other modules. | |||
-- I18N and time zones are not supported. | |||
local MINUS = '−' -- Unicode U+2212 MINUS SIGN | |||
local floor = math.floor | |||
local Date, DateDiff, diffmt -- forward declarations | |||
local uniq = { 'unique identifier' } | |||
local function is_date(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 | |||
local function collection() | |||
-- Return a table to hold items. | |||
return { | |||
n = 0, | |||
add = function (self, item) | |||
self.n = self.n + 1 | |||
self[self.n] = item | |||
end, | |||
join = _list_join, | |||
} | |||
end | |||
local function strip_to_nil(text) | |||
-- If text is a string, return its trimmed content, or nil if empty. | |||
-- Otherwise return text (convenient when Date fields are provided from | |||
-- another module which may pass a string, a number, or another type). | |||
if type(text) == 'string' then | |||
text = text:match('(%S.-)%s*$') | |||
end | |||
return text | |||
end | |||
local function is_leap_year(year, calname) | |||
-- Return true if year is a leap year. | |||
if calname == 'Julian' then | |||
return year % 4 == 0 | |||
end | |||
return (year % 4 == 0 and year % 100 ~= 0) or year % 400 == 0 | |||
end | |||
local function days_in_month(year, month, calname) | |||
-- Return number of days (1..31) in given month (1..12). | |||
if month == 2 and is_leap_year(year, calname) then | |||
return 29 | |||
end | |||
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 | |||
local function julian_date(date) | |||
-- Return jd, jdz from a Julian or Gregorian calendar date where | |||
-- jd = Julian date and its fractional part is zero at noon | |||
-- jdz = same, but assume time is 00:00:00 if no time given | |||
-- http://www.tondering.dk/claus/cal/julperiod.php#formula | |||
-- Testing shows this works for all dates from year -9999 to 9999! | |||
-- JDN 0 is the 24-hour period starting at noon UTC on Monday | |||
-- 1 January 4713 BC = (-4712, 1, 1) Julian calendar | |||
-- 24 November 4714 BC = (-4713, 11, 24) Gregorian calendar | |||
local offset | |||
local a = floor((14 - date.month)/12) | |||
local y = date.year + 4800 - a | |||
if date.calendar == 'Julian' then | |||
offset = floor(y/4) - 32083 | |||
else | |||
offset = floor(y/4) - floor(y/100) + floor(y/400) - 32045 | |||
end | |||