Module:Date: Difference between revisions

1,021 bytes added ,  6 years ago
update from sandbox: a date difference accepts an option to fill missing fields to handle partial dates
(update from sandbox: ranges of more time units)
(update from sandbox: a date difference accepts an option to fill missing fields to handle partial dates)
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)
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 = fillday })
end
return a
end
return filled(date1, date2), filled(date2, date1)
end
end


Line 1,160: Line 1,183:
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,538: Line 1,564:
}
}


function DateDiff(date1, date2)  -- for forward declaration above
function DateDiff(date1, date2, options)  -- 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,553: Line 1,579:
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,571: Line 1,601:
-------------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
local function zdiff(date1, date2)
if wantfill then
local diff = date1 - date2
date1, date2 = autofill(date1, date2)
if diff.isnegative then
else
return date1 - date1  -- a valid diff in case we call its methods
local function zdiff(date1, date2)
local diff = date1 - date2
if diff.isnegative then
return date1 - date1  -- a valid diff in case we call its methods
end
return diff
end
local function getdate(date, which)
return date.partial and date.partial[which] or date
end
end
return diff
local maxdiff = zdiff(getdate(date1, 'last'), getdate(date2, 'first'))
end
local mindiff = zdiff(getdate(date1, 'first'), getdate(date2, 'last'))
local function getdate(date, which)
local years, months
return date.partial and date.partial[which] or date
if maxdiff.years == mindiff.years then
end
years = maxdiff.years
local maxdiff = zdiff(getdate(date1, 'last'), getdate(date2, 'first'))
if maxdiff.months == mindiff.months then
local mindiff = zdiff(getdate(date1, 'first'), getdate(date2, 'last'))
months = maxdiff.months
local years, months
else
if maxdiff.years == mindiff.years then
months = { mindiff.months, maxdiff.months }
years = maxdiff.years
end
if maxdiff.months == mindiff.months then
months = maxdiff.months
else
else
months = { mindiff.months, maxdiff.months }
years = { mindiff.years, maxdiff.years }
end
end
else
return setmetatable({
years = { mindiff.years, maxdiff.years }
date1 = date1,
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,
maxdiff = maxdiff,
mindiff = mindiff,
},
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
Anonymous user