3
$\begingroup$

I am interesting to calculate the time between a first event and last event.

I calculate this in following way: The data looks as:

datesListEx = {"2014-12-08", "2014-01-14", "2014-05-30", "2014-11-13",
"2014-03-30", "2014-09-28", "2014-03-05", "2014-07-28", 
"2014-03-05", "2014-11-13", "2014-02-12", "2013-11-27", 
"2013-12-08", "2014-01-04", "2014-07-07", "2014-07-07", 
"2014-03-30", "2014-11-13", "2014-02-21", "2014-04-23", 
"2013-11-11", "2014-04-06", "2014-02-12", "2014-01-04", 
"2014-08-25", "2014-10-07", "2013-11-19", "2013-11-19", 
"2014-02-18", "2014-10-07", "2014-01-14", "2013-11-04", 
"2014-03-05", "2014-02-12", "2014-05-30", "2014-12-08", 
"2014-02-02", "2014-07-07", "2014-06-12"};

I sorted the data

datesListExSort = Sort@datesListEx;

And subtraction

 DateDifference[First[datesListExSort], Last[datesListExSort]]

I repeat the action thousands of times (with different data), the subtraction between dates that takes a lot of time. Is there a way to speed up this action?

$\endgroup$
  • 1
    $\begingroup$ You can convert to integers with AbsoluteTime /@ datesListEx and do computations and finally convert back with DateString[#, {"Year", "-", "Month", "-", "Day"}] &. (Documentation says "AbsoluteTime[] gives the total number of seconds since the beginning of January 1, 1900, in your time zone.") $\endgroup$ – Henrik Schumacher May 12 '18 at 14:21
  • $\begingroup$ Thank you. The convert to integers take more time than using DateDifference In[266]:= AbsoluteTime /@ datesListEx; // AbsoluteTiming Out[266]= {0.0176399, Null} and DateDifference[First[datesListExSort], Last[datesListExSort]] // AbsoluteTiming Out[262]= {0.00331155, Quantity[399, "Days"]} $\endgroup$ – Kiril Danilchenko May 12 '18 at 14:33
3
$\begingroup$

Edmund made a very good point. If your data strings are well-structured, you can load the data even faster with

dates2 = Map[
     DateObject[Join[#, {0, 0, 0}]] &,
     StringCases[datesListEx, s : DigitCharacter .. :> ToExpression[s]]
     ]; // RepeatedTiming // First

0.00048

Compared to Edmund's solution:

dates1 = Map[
     DateObject[{#, {"Year", "Month", "Day"}}] &,
     datesListEx
     ]; // RepeatedTiming // First

dates1 == dates2

0.00806

True

$\endgroup$
5
$\begingroup$

If you are processing dates it is better to have them as DateObjects and use the functions in the Date & Time guide. Try converting to DateObjects when you import. Over a list of DateObjects named dates you will find DateDifference @@ DateBounds@dates to be very fast.

dates = DateObject[{#, {"Year", "Month", "Day"}}] & /@ datesListEx;

Then

RepeatedTiming[
 DateDifference @@ DateBounds@dates;
 ]
{0.00085, Null}

versus

RepeatedTiming[
 datesListExSort = Sort@datesListEx;
 DateDifference[First[datesListExSort], Last[datesListExSort]];
 ]
{0.0031, Null}

Hope this helps.

$\endgroup$

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.