11

Consider the following scenario.

Suppose I consider time range from TimeObject[{18,30,0}] to TimeObject[{22,30,0}] on Weekdays and TimeObject[{18,0,0}] to TimeObject[{22,0,0}] on Weekends as peak time for something.

Now given a date range DateObject[{2019,7,18,20,12,30}] to DateObject[{2019,7,31,18,45,30}]. I want to find the intervals of peak times encountered in this range. Also I want to find the proportion of time spend in peak? What is the easiest way to calculate this using the Mathematica's Date and Time functionality.

Does Wolfram language provide a symbolic wrapper to represent a date/time interval and also a disjoint but periodic intervals of time?


Thank you @kglr it works! Although "Duration" property does not exactly calculate what I want but the following workaround works.

With[{
    interval=DateTime`DateInterval[{3755358615, 3755368800}, {3755440800, 3755455200}, {3755527200, 3755540710}, True]
},
    {
        Query[Apply[Plus]@*All,Apply[Subtract]@*Reverse]@interval["Dates"],
        interval["Duration"],
        DateObject[{2019,1,1,19,10,15},"Instant","Gregorian",1.`]-DateObject[{2019,1,3,21,45,10},"Instant","Gregorian",1.`]
    }
]
user13892
  • 9,375
  • 1
  • 13
  • 41

2 Answers2

14

Yes ... there is (undocumented) DateTime`DateInterval:

di = DateTime`DateInterval[{DateObject[{2019, 7, 18, 1, 30, 0}] , 
       DateObject[{2019, 7, 18, 12, 30, 0}]}]

enter image description here

Options[DateTime`DateInterval]

{CalendarType -> Automatic, TimeZone :> $TimeZone}

di["Properties"]

{"CalendarType", "DateRange", "Dates", "DayCount", "Duration", "Max", "Min", "RawDates", "TimeZone"}

di /@ {"Min", "Max"}

enter image description here

di["Duration"]

Quantity[0.458333, "Days"]

UnitConvert[di["Duration"], "Seconds"]

Quantity[39600., "Seconds"]

Multiple intervals:

dilist = DateTime`DateInterval /@ 
   {{DateObject[{2019, 7, 18, 1, 30}] , DateObject[{2019, 7, 21, 12, 30}]}, 
    {DateObject[{2019, 7, 20, 2, 45}] , DateObject[{2019, 7, 22, 10, 30}]}};

Column @ dilist

enter image description here

Interval operations work the same way as for Interval objects:

IntervalIntersection @@ dilist 

enter image description here

IntervalUnion @@ dilist 

enter image description here

Show[TimelinePlot[Association /@ 
   (Column[Insert[DateObject /@ #[[1]], "thru", 2], Center] -> # & /@ dilist), 
     AxesOrigin -> Bottom],
 TimelinePlot[Association[
    Column[Insert[DateObject /@ #[[1]], "thru", 2], Center] -> # &[
     IntervalIntersection @@ dilist]], 
     AxesOrigin -> Top, PlotStyle -> Red], 
  PlotRange -> All, Frame -> False, Axes -> {True, False}]

enter image description here

Note: Used this answer by Vitaliy Kaurov to avoid label clutter in TimelinePlot.

kglr
  • 394,356
  • 18
  • 477
  • 896
  • 1
    Thanks for this answer. I did not know about this undocumented functionality. – Anton Antonov Jul 30 '19 at 20:28
  • 2
    @Anton, I did not know about it myself till I tried Names["*`*Date*Interval*"]:) – kglr Jul 30 '19 at 20:33
  • 2
    @klgr I am near speechless that that actually worked. It tells you something about the consistency of Mathematica's naming scheme, and perhaps the number of functions existing behind the scenes. – lirtosiast Jul 31 '19 at 07:32
3

Since V 12.1 DateInterval is part of the language:

di = DateInterval[{DateObject[{2019, 7, 18}], DateObject[{2019, 8, 29}]}]

enter image description here

di["Properties"]

{"CalendarType", "DateBounds", "Dates", "Duration", "Granularity", "Max", "Min", "RawDates", "TimeZone"}

("Granularity" was added with V 13.3)

di /@ {"Min", "Max"}

enter image description here

TimelinePlot[di]

enter image description here

eldo
  • 67,911
  • 5
  • 60
  • 168