# How to calculate time period?

I have the starting and ending dates and times. And I need to calculate the night time in this period (from 10 pm (22) to 6 am (6)).
Example:
starting date and time is {2015, 1, 4, 3, 10}
ending date and time is {2015, 3, 4, 18, 10}
Total (this is the result of function)= 1090 min (18 h 10 min)

How can I do this?

Thanks!

• your example results are not correct (?) else I don't understand the question, i get more like 500h. – george2079 Apr 9 '15 at 21:44
• do you need to be accurate if there is a daylight savings offset in the range? – george2079 Apr 9 '15 at 21:55
• no, I don't. it doesn't matter. – V_kid Apr 9 '15 at 21:59
• starting date and time is {2015, 1, 4, 3, 10} = {year, day, month, hour, minutes} – V_kid Apr 9 '15 at 22:13
• That's why I get like 18h but you more 500h I tried to use your code and it didn't work correct: didn't calculate nightfirstpart And for example I will have the ending date and time like this {2015, 3, 4, 22, 10}. In this case I need to take in account 10 minutes after 22 (10 pm). – V_kid Apr 9 '15 at 22:22

d1 = {2015, 4, 1, 3, 10};
d2 = {2015, 4, 3, 18, 10};
j[d_, s_, h_] := Join[DatePlus[d, s][[1 ;; 3]], {h, 00}]
abst = AbsoluteTime;
l1 = DateRange[j[d1, -2, 22], j[d2, 2, 22]];
l2 = DateRange[j[d1, -1, 6], j[d2, 3, 6]];
ints = Interval /@ Map[abst, Transpose@{l1, l2}, {2}];
iu = IntervalUnion@@(IntervalIntersection[Interval[abst/@{d1,d2}], #] & /@ ints);
res = DateList @@ ((Differences /@ (List @@ iu) // Total));
DateDifference[{1900, 1, 1}, res, "Minute"]
(* {1130, "Minute"} *)


Note that your arithmetic is wrong and you're interchanging the month and day places in your lists

• You're absolutely right. My arithmetic is wrong. It should be 18 h 50 m. Your code works correct! Thank you! Can you help me to get the answer just in minutes? – V_kid Apr 9 '15 at 22:32
• @V_kid There you've it – Dr. belisarius Apr 9 '15 at 22:48

Edit, fixing some errors to show this "works"

 tend = AbsoluteTime[{2015, 4, 3, 18, 10}];
deltimed = (tend - AbsoluteTime[{2015, 4, 1, 3, 10}])/3600/24;
{wholedays, fractionseconds} =
{Floor[#], FractionalPart[#] 24 3600 } & @ deltimed;
isnight[t_?NumericQ] := Boole[0 <= # < 6 || # >= 22] &@DateList[t][[4]];
nightfirstpartday =
NIntegrate[isnight[t], {t, tend - fractionseconds, tend}]/3600 //
Quiet;
answer = wholedays 8 + nightfirstpartday


18.8332

 {Quantity[Floor[#], "Hours"],
Quantity[60 FractionalPart[#], "Seconds"]} & @ answer


{Quantity[18, "Hours"], Quantity[49.9931, "Seconds"]}

slow and inelegant.. but it does work.

Note you can in principle get the result in one shot like this:

 NIntegrate[isnight[t],
{t, AbsoluteTime[{2015, 4, 1, 3, 10}],
AbsoluteTime[{2015, 4, 3, 18, 10}]}]/3600 // Quiet


This will severely loose accuracy if the time span is more than a few days however.

Night time of First day + (night time period times [[2;;-2]] days) + night time of Last day

nightTime[{startDateTime_?DateObjectQ, endDateTime_?DateObjectQ}, {nightStartTime_?TimeObjectQ, nightEndTime_?TimeObjectQ}] :=
(* night time of First day + night time period \[Times] [[2;;-2]] \days + night time of Last day *)
Simplify[
Max[TimeObject[startDateTime] - nightStartTime, nightEndTime - TimeObject[startDateTime], Quantity[0, "Seconds"]] +
Max[(QuantityMagnitude@Floor@UnitConvert[endDateTime - startDateTime, "Days"] - 2)*
((TimeObject[{23, 59, 59}] - nightStartTime) + (nightEndTime - TimeObject[{0, 0, 0}])), Quantity[0, "Seconds"]] +
If[(startDateTime - TimeObject[startDateTime]) == (endDateTime - TimeObject[endDateTime]),
Max[TimeObject[endDateTime] - nightStartTime, nightEndTime - TimeObject[endDateTime], Quantity[0, "Seconds"]],
Quantity[0, "Seconds"]
]
]


Let

start = DateObject@{2015, 1, 4, 3, 10};
end = DateObject@{2015, 3, 4, 18, 10};
nightStart = TimeObject[{22, 00}];
nightEnd = TimeObject[{6, 00}];


Then

timePeriod = nightTime[{start, end}, {nightStart, nightEnd}];
UnitConvert[timePeriod, "Hours"]
(* Quantity[458.818, "Hours"] *)


Hope this helps.

*Updated to account for date range less than 3 days *

Now end = DateObject@{2015, 1, 4, 18, 10}; and nightTime[{start, end}, {nightStart, nightEnd}] will work.

• There is an assumption in this function that the time span is at least 3 days long but it is very easy to modify this by not accepting a negative for the middle days and comparing the date only part of startDateTime and endDateTime. – Edmund Apr 10 '15 at 1:10
• You ought to fix this to show the result with the corrected time spec. – george2079 Apr 10 '15 at 14:11
• @george2079 Yup. Done. – Edmund Apr 10 '15 at 16:38