10
$\begingroup$

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.

$\endgroup$
12
$\begingroup$

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} *)
$\endgroup$
  • $\begingroup$ I was specifically trying to avoid an exhaustive enumeration of the days, but seeing this I wonder why. +1 of course. $\endgroup$ – Mr.Wizard Jan 19 '17 at 0:16
5
$\begingroup$

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.

$\endgroup$
5
$\begingroup$

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.

I'll start with your data in a somewhat more compact format:

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}
]

enter image description here

$\endgroup$
  • $\begingroup$ Are you getting a different answer or am I reading this date wrong? 19th Aug? $\endgroup$ – Chen Stats Yu Jan 19 '17 at 19:23
  • $\begingroup$ @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. $\endgroup$ – Mr.Wizard Jan 19 '17 at 20:09
  • 1
    $\begingroup$ @ChenStatsYu DayCount does not count the beginning date of the date range, so this code counts one fewer day per interval. $\endgroup$ – Simon Woods Jan 19 '17 at 21:09
  • $\begingroup$ @SimonWoods Oops! Thanks, Simon. $\endgroup$ – Mr.Wizard Jan 19 '17 at 21:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.