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$
0

3 Answers 3

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$
1
  • $\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
    Commented Jan 19, 2017 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$
4
  • $\begingroup$ Are you getting a different answer or am I reading this date wrong? 19th Aug? $\endgroup$ Commented Jan 19, 2017 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
    Commented Jan 19, 2017 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$ Commented Jan 19, 2017 at 21:09
  • $\begingroup$ @SimonWoods Oops! Thanks, Simon. $\endgroup$
    – Mr.Wizard
    Commented Jan 19, 2017 at 21:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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