Editing Module:Date

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. Read the Privacy Policy to learn what information we collect about you and how we use it.

If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.

Latest revision Your text
Line 897: Line 897:
end
end
return date, options
return date, options
end
local function autofill(date1, date2)
-- Fill any missing month or day in each date using the
-- corresponding component from the other date, if present,
-- or with 1 if both dates are missing the month or day.
-- This gives a good result for calculating the difference
-- between two partial dates when no range is wanted.
-- Return filled date1, date2 (two full dates).
local function filled(a, b)
-- Return date a filled, if necessary, with month and/or day from date b.
-- The filled day is truncated to fit the number of days in the month.
local fillmonth, fillday
if not a.month then
fillmonth = b.month or 1
end
if not a.day then
fillday = b.day or 1
end
if fillmonth or fillday then  -- need to create a new date
a = Date(a, {
month = fillmonth,
day = math.min(fillday or a.day, days_in_month(a.year, fillmonth or a.month, a.calendar))
})
end
return a
end
return filled(date1, date2), filled(date2, date1)
end
end


Line 1,130: Line 1,102:
-- Return true if dates identify same date/time where, for example,
-- Return true if dates identify same date/time where, for example,
-- Date(-4712, 1, 1, 'Julian') == Date(-4713, 11, 24, 'Gregorian') is true.
-- Date(-4712, 1, 1, 'Julian') == Date(-4713, 11, 24, 'Gregorian') is true.
-- This is called only if lhs and rhs have the same type and the same metamethod.
-- This is only called if lhs and rhs have the same metatable.
if lhs.partial or rhs.partial then
if lhs.partial or rhs.partial then
-- One date is partial; the other is a partial or a full date.
-- One date is partial; the other is a partial or a full date.
Line 1,142: Line 1,114:
-- Return true if lhs < rhs, for example,
-- Return true if lhs < rhs, for example,
-- Date('1 Jan 2016') < Date('06:00 1 Jan 2016') is true.
-- Date('1 Jan 2016') < Date('06:00 1 Jan 2016') is true.
-- This is called only if lhs and rhs have the same type and the same metamethod.
-- This is only called if lhs and rhs have the same metatable.
if lhs.partial or rhs.partial then
if lhs.partial or rhs.partial then
-- One date is partial; the other is a partial or a full date.
-- One date is partial; the other is a partial or a full date.
Line 1,188: Line 1,160:
options = {},
options = {},
list = _date_list,
list = _date_list,
subtract = function (self, rhs, options)
return DateDiff(self, rhs, options)
end,
text = _date_text,
text = _date_text,
}
}
Line 1,340: Line 1,309:
local function _diff_age(diff, code, options)
local function _diff_age(diff, code, options)
-- Return a tuple of integer values from diff as specified by code, except that
-- Return a tuple of integer values from diff as specified by code, except that
-- each integer may be a list of two integers for a diff with a partial date, or
-- each integer may be a list of two integers for a diff with a partial date.
-- return nil if the code is not supported.
-- If want round, the least significant unit is rounded to nearest whole unit.
-- If want round, the least significant unit is rounded to nearest whole unit.
-- For a duration, an extra day is added.
-- For a duration, an extra day is added.
Line 1,360: Line 1,328:
local function choose(v)
local function choose(v)
if type(v) == 'table' then
if type(v) == 'table' then
if not wantrange or v[1] == v[2] then
if not wantrange then
-- Example: Date('partial', 2005) - Date('partial', 2001) gives
-- Example: Date('partial', 2005) - Date('partial', 2001) gives
-- diff.years = { 3, 4 } to show the range of possible results.
-- diff.years = { 3, 4 } to show the range of possible results.
Line 1,379: Line 1,347:
return choose(diff.partial.years), choose(diff.partial.months)
return choose(diff.partial.years), choose(diff.partial.months)
end
end
if code == 'y' then
-- Default: assume code == 'y'; ignore invalid codes.
return choose(diff.partial.years)
return choose(diff.partial.years)
end
if code == 'm' or code == 'w' or code == 'd' then
return choose({ diff.partial.mindiff:age(code), diff.partial.maxdiff:age(code) })
end
return nil
end
end
local extra_days = wantduration and 1 or 0
local extra_days = wantduration and 1 or 0
Line 1,400: Line 1,363:
return floor(days/7 + offset)
return floor(days/7 + offset)
end
end
local H, M, S = diff.hours, diff.minutes, diff.seconds
local H, M = diff.hours, diff.minutes
if code == 'dh' or code == 'dhm' or code == 'dhms' or code == 'h' or code == 'hm' or code == 'hms' or code == 'M' or code == 's' then
if code == 'dh' or code == 'dhm' then
local days = floor(diff.age_days + extra_days)
local days = floor(diff.age_days + extra_days)
local inc_hour
local inc_hour
if wantround then
if wantround then
if code == 'dh' or code == 'h' then
if code == 'dh' then
if M >= 30 then
if M >= 30 then
inc_hour = true
inc_hour = true
end
end
elseif code == 'dhm' or code == 'hm' then
elseif diff.seconds >= 30 then
if S >= 30 then
M = M + 1
M = M + 1
if M >= 60 then
if M >= 60 then
M = 0
M = 0
inc_hour = true
inc_hour = true
end
end
elseif code == 'M' then
if S >= 30 then
M = M + 1
end
end
else
-- Nothing needed because S is an integer.
end
end
if inc_hour then
if inc_hour then
Line 1,432: Line 1,387:
end
end
end
end
if code == 'dh' or code == 'dhm' or code == 'dhms' then
if code == 'dh' then
if code == 'dh' then
return days, H
return days, H
elseif code == 'dhm' then
return days, H, M
else
return days, H, M, S
end
end
local hours = days * 24 + H
if code == 'h' then
return hours
elseif code == 'hm' then
return hours, M
elseif code == 'M' or code == 's' then
M = hours * 60 + M
if code == 'M' then
return M
end
return M * 60 + S
end
end
return hours, M, S
return days, H, M
end
end
if wantround then
if wantround then
Line 1,462: Line 1,399:
end
end
elseif code == 'ymdhm' or code == 'ymwdhm' then
elseif code == 'ymdhm' or code == 'ymwdhm' then
if S >= 30 then
if diff.seconds >= 30 then
M = M + 1
M = M + 1
if M >= 60 then
if M >= 60 then
Line 1,535: Line 1,472:
return y, m, floor(d/7), d % 7, H, M
return y, m, floor(d/7), d % 7, H, M
end
end
if code == 'y' then
-- Default: assume code == 'y'; ignore invalid codes.
if wantround and m >= 6 then
if wantround and m >= 6 then
y = y + 1
y = y + 1
end
return y
end
end
return nil
return y
end
end


Line 1,579: Line 1,514:
}
}


function DateDiff(date1, date2, options)  -- for forward declaration above
function DateDiff(date1, date2)  -- for forward declaration above
-- Return a table with the difference between two dates (date1 - date2).
-- Return a table with the difference between two dates (date1 - date2).
-- The difference is negative if date1 is older than date2.
-- The difference is negative if date1 is older than date2.
Line 1,594: Line 1,529:
if not (is_date(date1) and is_date(date2) and date1.calendar == date2.calendar) then
if not (is_date(date1) and is_date(date2) and date1.calendar == date2.calendar) then
return
return
end
local wantfill
if type(options) == 'table' then
wantfill = options.fill
end
end
local isnegative = false
local isnegative = false
Line 1,616: Line 1,547:
-------------A===B------------------------- A=2001-04-01  B=2001-04-30
-------------A===B------------------------- A=2001-04-01  B=2001-04-30
--------C=====================D------------ C=2001-01-01  D=2001-12-31
--------C=====================D------------ C=2001-01-01  D=2001-12-31
if wantfill then
local function zdiff(date1, date2)
date1, date2 = autofill(date1, date2)
local diff = date1 - date2
else
if diff.isnegative then
local function zdiff(date1, date2)
return { years = 0, months = 0 }
local diff = date1 - date2
if diff.isnegative then
return date1 - date1  -- a valid diff in case we call its methods
end
return diff
end
end
local function getdate(date, which)
return diff
return date.partial and date.partial[which] or date
end
end
local function getdate(date, which)
local maxdiff = zdiff(getdate(date1, 'last'), getdate(date2, 'first'))
return date.partial and date.partial[which] or date
local mindiff = zdiff(getdate(date1, 'first'), getdate(date2, 'last'))
end
local years, months
local maxdiff = zdiff(getdate(date1, 'last'), getdate(date2, 'first'))
if maxdiff.years == mindiff.years then
local mindiff = zdiff(getdate(date1, 'first'), getdate(date2, 'last'))
years = maxdiff.years
local years, months
if maxdiff.months == mindiff.months then
if maxdiff.years == mindiff.years then
months = maxdiff.months
years = maxdiff.years
else
if maxdiff.months == mindiff.months then
months = { mindiff.months, maxdiff.months }
months = maxdiff.months
end
else
else
years = { mindiff.years, maxdiff.years }
months = { mindiff.months, maxdiff.months }
end
end
return setmetatable({
else
date1 = date1,
years = { mindiff.years, maxdiff.years }
date2 = date2,
partial = {
years = years,
months = months,
maxdiff = maxdiff,
mindiff = mindiff,
},
isnegative = isnegative,
iszero = iszero,
age = _diff_age,
duration = _diff_duration,
}, diffmt)
end
end
return setmetatable({
date1 = date1,
date2 = date2,
partial = { years = years, months = months },
isnegative = isnegative,
iszero = iszero,
age = _diff_age,
duration = _diff_duration,
}, diffmt)
end
end
local y1, m1 = date1.year, date1.month
local y1, m1 = date1.year, date1.month
Please note that all contributions to Nonbinary Wiki are considered to be released under the Creative Commons Attribution-ShareAlike (see Nonbinary Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!
Cancel Editing help (opens in new window)

Template used on this page: