Module:Date: Difference between revisions

11,778 bytes added ,  9 years ago
update from Module:Date/sandbox; major refactor to support new features in Module:Age
(fix bug where Date('2016-06-01') - Date('2016-05-31 23:00') gave 1 day instead of 1 hour)
(update from Module:Date/sandbox; major refactor to support new features in Module:Age)
Line 69: Line 69:


local function hms(date)
local function hms(date)
-- Return fraction of a day (0 <= fraction < 1) from date's time.
-- 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
return (date.hour + (date.minute + date.second / 60) / 60) / 24
end
end
Line 149: Line 150:
date.year = 100*b + d - 4800 + floor(m/10)
date.year = 100*b + d - 4800 + floor(m/10)
return true
return true
end
local function fix_numbers(numbers, y, m, d, H, M, S, partial, hastime, calendar)
-- Put the result of normalizing the given values in table numbers.
-- The result will have valid m, d values if y is valid; caller checks y.
-- The logic of PHP mktime is followed where m or d can be zero to mean
-- the previous unit, and -1 is the one before that, etc.
-- Positive values carry forward.
local date
if not (1 <= m and m <= 12) then
date = Date(y, 1, 1)
if not date then return end
date = date + ((m - 1) .. 'm')
y, m = date.year, date.month
end
local days_hms
if not partial then
if hastime and H and M and S then
if not (0 <= H and H <= 23 and
0 <= M and M <= 59 and
0 <= S and S <= 59) then
days_hms = hms({ hour = H, minute = M, second = S })
end
end
if days_hms or not (1 <= d and d <= days_in_month(y, m, calendar)) then
date = date or Date(y, m, 1)
if not date then return end
date = date + (d - 1 + (days_hms or 0))
y, m, d = date.year, date.month, date.day
if days_hms then
H, M, S = date.hour, date.minute, date.second
end
end
end
numbers.year = y
numbers.month = m
numbers.day = d
if days_hms then
-- Don't set H unless it was valid because a valid H will set hastime.
numbers.hour = H
numbers.minute = M
numbers.second = S
end
end
end


Line 163: Line 207:
local M = numbers.minute or date.minute or 0
local M = numbers.minute or date.minute or 0
local S = numbers.second or date.second or 0
local S = numbers.second or date.second or 0
if not (y and m and d) or not
local need_fix
(-9999 <= y and y <= 9999 and
if y and m and d then
date.partial = nil
if not (-9999 <= y and y <= 9999 and
1 <= m and m <= 12 and
1 <= m and m <= 12 and
1 <= d and d <= days_in_month(y, m, date.calendar)) then
1 <= d and d <= days_in_month(y, m, date.calendar)) then
if not date.want_fix then
return
end
need_fix = true
end
elseif y and date.partial then
if d or not (-9999 <= y and y <= 9999) then
return
end
if m and not (1 <= m and m <= 12) then
if not date.want_fix then
return
end
need_fix = true
end
else
return
return
end
end
if H then
if date.partial then
-- It is not possible to set M or S without also setting H.
H = nil  -- ignore any time
date.hastime = true
M = nil
S = nil
else
else
H = date.hour or 0
if H then
-- It is not possi