# How to work with Date calculations?

I have never worked using the DateObject function

But I suspect there must be a (easy) way of doing it.

I want to find out, when in the future, from which point, that the cumulative days of not being in the country is less than 540 days, given

(* Periods that I am not in the UK *)
DateObject[{2017, 1, 1}] - DateObject[{2016, 12, 17}]
DateObject[{2014, 7, 19}] - DateObject[{2014, 7, 11}]
DateObject[{2014, 4, 1}] - DateObject[{2014, 3, 27}]
DateObject[{2014, 1, 28}] - DateObject[{2013, 12, 28}]
DateObject[{2013, 11, 25}] - DateObject[{2013, 10, 25}]
DateObject[{2013, 5, 6}] - DateObject[{2013, 4, 28}]
DateObject[{2012, 8, 26}] - DateObject[{2012, 8, 5}]
DateObject[{2012, 7, 6}] - DateObject[{2012, 7, 2}]
DateObject[{2011, 8, 15}] - DateObject[{2011, 6, 25}]
DateObject[{2010, 9, 18}] - DateObject[{2010, 6, 19}]
DateObject[{2009, 9, 23}] - DateObject[{2009, 6, 18}]
DateObject[{2009, 4, 18}] - DateObject[{2009, 3, 22}]
DateObject[{2008, 10, 4}] - DateObject[{2008, 6, 19}]
DateObject[{2007, 10, 2}] - DateObject[{2007, 6, 16}]
DateObject[{2007, 4, 6}] - DateObject[{2007, 3, 24}]
DateObject[{2007, 1, 4}] - DateObject[{2006, 12, 16}]


Background: to apply for UK permanent residency, you cannot be away for more than 540 days in the last 10 years. I just want to find out when I can start applying. Thanks.

Using Mr Wizard's data the complete list of away days is

away = Join @@ DateRange @@@ Reverse @ data;


The 540th most recent absence, plus 10 years is:

away[[-540]] + {10, 0, 0}
(* {2017, 9, 2} *)

• I was specifically trying to avoid an exhaustive enumeration of the days, but seeing this I wonder why. +1 of course. – Mr.Wizard Jan 19 '17 at 0:16

Assuming you don't leave again I think it should suffice to simply add 10 years to the 540th day in that range from the back. I.e. something like:

days = DayRange @@@
Partition[{
DateObject[{2017, 1, 1}], DateObject[{2016, 12, 17}],
DateObject[{2014, 7, 19}], DateObject[{2014, 7, 11}],
DateObject[{2014, 4, 1}], DateObject[{2014, 3, 27}],
DateObject[{2014, 1, 28}], DateObject[{2013, 12, 28}],
DateObject[{2013, 11, 25}], DateObject[{2013, 10, 25}],
DateObject[{2013, 5, 6}], DateObject[{2013, 4, 28}],
DateObject[{2012, 8, 26}], DateObject[{2012, 8, 5}],
DateObject[{2012, 7, 6}], DateObject[{2012, 7, 2}],
DateObject[{2011, 8, 15}], DateObject[{2011, 6, 25}],
DateObject[{2010, 9, 18}], DateObject[{2010, 6, 19}],
DateObject[{2009, 9, 23}], DateObject[{2009, 6, 18}],
DateObject[{2009, 4, 18}], DateObject[{2009, 3, 22}],
DateObject[{2008, 10, 4}], DateObject[{2008, 6, 19}],
DateObject[{2007, 10, 2}], DateObject[{2007, 6, 16}],
DateObject[{2007, 4, 6}], DateObject[{2007, 3, 24}],
DateObject[{2007, 1, 4}], DateObject[{2006, 12, 16}]
}, 2] // Apply[Join];
days // Sort // Take[#, -540] & // First@# + Quantity[10, "Years"] &


Sort orders by earliest to latest so this ought to work.

I got DateObject[{2017, 9, 2}] as the earliest date you can apply.

This is probably not the canonical approach but I couldn't think of a way to solve this using Date functions so I converted to AbsoluteTime and worked with Interval.

data = {
{{2016, 12, 17}, {2017, 1, 1}}, {{2014, 7, 11}, {2014, 7, 19}},
{{2014, 3,  27}, {2014, 4, 1}}, {{2013, 12, 28}, {2014, 1, 28}},
{{2013, 10, 25}, {2013, 11, 25}}, {{2013, 4, 28}, {2013, 5, 6}},
{{2012, 8, 5}, {2012, 8, 26}}, {{2012, 7, 2}, {2012, 7, 6}},
{{2011, 6, 25}, {2011, 8, 15}}, {{2010, 6, 19}, {2010, 9, 18}},
{{2009, 6, 18}, {2009, 9, 23}}, {{2009, 3, 22}, {2009, 4, 18}},
{{2008, 6, 19}, {2008, 10, 4}}, {{2007, 6, 16}, {2007, 10, 2}},
{{2007, 3, 24}, {2007, 4, 6}}, {{2006, 12, 16}, {2007, 1, 4}}
};


The data in absolute interval form:

ooc = Interval @@ Map[AbsoluteTime, data, {2}];


A function to compute the number of days in that interval that intersects with another date range:

days[int_, start_, end_] :=
DayCount @@@ List @@ IntervalIntersection[int, Interval[{start, end}]] + 1 // Tr;


Interactive search:

t0 = AbsoluteTime @ Today;

Manipulate[
{DateObject[end],
days[ooc, DatePlus[end, {-10, "Year"}], end]},
{end, t0, t0 + 1*^8, 24*60^2}
] • Are you getting a different answer or am I reading this date wrong? 19th Aug? – Chen Stats Yu Jan 19 '17 at 19:23
• @ChenStatsYu I probably made a mistake. I'll try to take a look at this later, but honestly I'll not consider it a high priority as Simon already gave a much better answer. – Mr.Wizard Jan 19 '17 at 20:09
• @ChenStatsYu DayCount does not count the beginning date of the date range, so this code counts one fewer day per interval. – Simon Woods Jan 19 '17 at 21:09
• @SimonWoods Oops! Thanks, Simon. – Mr.Wizard Jan 19 '17 at 21:20