5
$\begingroup$

What would be the best way to represent a complex schedule in Mathematica ?

For example a representation of the plain words schedule: "From Monday to Friday, from 8 am to 12pm and from 1pm to 4pm", or another schedule like "Monday from 2am to 6am,Tuesday from 10 am to 11am, ..."

This needs stems from the fact that I need to start and stop scheduled tasks if I am in an interval specified by a schedule, and given a time I need to know if I'm in such an interval or not, in order to know if the state is "Started" or "Stopped".

Possibly somebody has had a similar need in Mathematica before, thank you.

Maybe one possibility would be to create a scheduled task that starts or stops the next bound of a time interval.

$\endgroup$
8
$\begingroup$

Try (in version 10.1):

    TimelinePlot[{{Interval[{DateObject[{2015, 4, 27, 6, 30, 15}], 
     DateObject[{2015, 4, 28, 9, 15, 45}]}], 
   DateObject[{2015, 4, 28, 12, 0, 0}], 
   Interval[{DateObject[{2015, 4, 28, 15, 30, 0}], 
     DateObject[{2015, 4, 29, 10, 0, 
       0}]}]}, {Interval[{DateObject[{2015, 4, 28, 11, 0, 0}], 
     DateObject[{2015, 4, 29, 0, 0, 0}]}], 
   DateObject[{2015, 4, 29, 0, 30, 0}], 
   Interval[{DateObject[{2015, 4, 29, 12, 0, 0}], 
     DateObject[{2015, 4, 30, 18, 0, 0}]}]}},
 Ticks -> {
   ({DateObject[{2015, 4, #}],
       DateString[{2015, 4, #}, {"DayName", "  ", "Month", "/", 
         "Day"}]}) & /@ Range[26, 30]
   , Automatic} 
 ]

enter image description here

To check whether you're in an interval it appears you must convert to absolute time:

IntervalMemberQ[
 Interval[{AbsoluteTime[DateObject[{2015, 4, 27, 4, 30, 0}]], 
   AbsoluteTime[DateObject[{2015, 4, 29, 4, 30, 0}]]}], 
 AbsoluteTime[DateObject[{2015, 4, 28, 4, 30, 0}]]]

(* True *)

$\endgroup$
  • $\begingroup$ Does IntervalMemberQ handle datetime objects in 10.0? $\endgroup$ – 2012rcampion Apr 27 '15 at 16:57
  • $\begingroup$ @2012rcampion no it doesn't. but you can convert to AbsoluteTime. $\endgroup$ – Eric Brown Apr 27 '15 at 17:38
  • $\begingroup$ David, I'd add that to your answer, considering the question: "I need to know if I'm in such an interval or not" $\endgroup$ – 2012rcampion Apr 27 '15 at 17:40
  • $\begingroup$ @2012rcampion See my amended answer for the answer to your interval question. $\endgroup$ – David G. Stork Apr 27 '15 at 17:59
  • $\begingroup$ How would you represent "From Monday to Friday, from 8 am to 12pm and from 1pm to 4pm"? It would require an infinite number of DateObjects it seems. $\endgroup$ – C. E. Apr 27 '15 at 19:15
2
$\begingroup$

In short: use DayMatchQ to check the day and use TimeObject for time intervals.

timeIntervals = {};

AppendTo[timeIntervals, {
    TimeObject[{8, 0, 0}],
   TimeObject[{12, 0, 0}]
   }];

AppendTo[timeIntervals, {
    TimeObject[{13, 0, 0}],
   TimeObject[{16, 0, 0}]
   }];

dayCriterias = {
   "Weekday"
   };

checkDay[day_, time_, timeIntervals_, dayCriterias_] := 
 Module[{dayMatch, timeMatch},
  dayMatch = Or @@ Map[DayMatchQ[day, #] &, dayCriterias];
  timeMatch = Or @@ (# < time < #2 & @@@ timeIntervals);
  And[dayMatch, timeMatch]
  ]

Examples, evaluated on a Monday:

checkDay[Today, TimeObject[{10, 0, 0}], timeIntervals, dayCriterias]
(* True *)

checkDay[Today, TimeObject[{12, 30, 0}], timeIntervals, dayCriterias]
(* False *)
$\endgroup$
2
$\begingroup$

Here's how I did it. I use the fact that Sort sorts lists in lexicographic order.
Note that a schedule for a day of the form "Monday(23:40)" matches a time until the end of the day.

schedule="Monday(10:30-10:40/23:40-23:41:32),Tuesday(10:50-11:23:26)";
IsInTimeSchedule[schedule,{2004,3,8,23,41,31}]

The code:

parseTime[time_]:=StringSplit[time,"-"]//Map[(StringSplit[#,":"]//ToExpression)&];
parseDaySchedule[daySchedule_]:=StringCases[daySchedule,x__~~"("~~Shortest[y__]~~")":>{ToExpression@x,StringSplit[y,"/"]//Map[parseTime]}]//First;
g:parseSchedule[schedule_]:=g=StringSplit[schedule,","]//Map[parseDaySchedule];

isInTimeInInterval[timeInterval_,t_]:=t==Sort[Append[timeInterval,t]][[2]];(*Sort sorts lists in lexicographic order*)

IsInTimeSchedule[schedule_String,time_]:=IsInTimeSchedule[parseSchedule[schedule],time];
IsInTimeSchedule[schedule_,time_]:=
    Block[{dayName,daySchedule},

        dayName=DayName@time;
        daySchedule=SelectFirst[schedule,First@#===dayName&];

        If[daySchedule=!=Missing["NotFound"],
            AnyTrue[daySchedule[[2]],isInTimeInInterval[#,time[[4;;]]]&]
            ,
            False
        ]
    ];
$\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.