7
$\begingroup$

I'm creating a way to organize some daily appointments.

I am a teacher and I have groups of students rotating for short periods. Sometimes 2 days a week, other times 3 days a week, ...

I am creating a way to define the days that I will have my appointments.

Below I determine the date of the first day of class and the number of days to finish the course:

date1 = {2017,6,26}; nDays=10;

Below I determine the numerical starting day of class and what is the day of the week:

day1=DateValue[DateObject[date1],"Day"]
dayName=DateValue[DateObject[date1],"DayName"]

26

Monday

Having the initial date I check how many days the current month has:

splitDate =
QuantityMagnitude[With[{year=DateValue[DateObject[date1],"Year"],
month = DateValue[DateObject[date1],"Month"]},
DateDifference[{year,month},If[month==12, {year+1,1}, {year,month+1}]]]]

30

Below I determine the days of the week that I will teach:

week = {Monday,Tuesday,Friday};

Below I associated the days of the week by numbers to get the differences between Sunday, Monday, ...

group=<|Sunday→1,Monday->2,Tuesday->3,
Wednesday->4,Thursday->5,Friday->6,Saturday->7|>;
firstWeek=group[#]&/@week-First[group[#]&/@week]

{0,1,4}

Below I defined the first week and created the other weeks according to the number of days I will teach. But it will always exceed the number of days to teach:

list1=Flatten[NestList[#+7&,firstWeek,IntegerPart[nDays/Length[firstWeek]]]]

{0,1,4,7,8,11,14,15,18,21,22,25}

Below I delete the days that are left ...

stepDays=Drop[list1,nDays-Length[list1]]

{0,1,4,7,8,11,14,15,18,21}

Below I create the dates according to the first day:

allDays=stepDays+day1
If[allDays[[#]]<=splitDate,allDays[[#]],allDays[[#]]-splitDate]&/@Range[nDays]

{26,27,30,33,34,37,40,41,44,47}

{26,27,30,3,4,7,10,11,14,17}

After all these steps, the question is this:

Is there any specific function for this type of day count? Or do I have to synthesize all these steps and create a function created by myself?

$\endgroup$
  • $\begingroup$ Do I understand this right, you start teaching on the 26:th of June, and you teach every Monday, Tuesday, and Friday from then on until you have taught for ten days. And you want to find out the dates for these ten days? $\endgroup$ – C. E. Jun 28 '17 at 14:00
  • $\begingroup$ @C.E. That's it. So much so that I got through the last list of my code. But I would like to know if there is an in-built function for this. $\endgroup$ – LCarvalho Jun 28 '17 at 14:05
  • $\begingroup$ @C.E. In fact, I am very grateful for your repository. Helps me a lot. $\endgroup$ – LCarvalho Jun 28 '17 at 14:10
  • 1
    $\begingroup$ Thank you. Glad to know that you find it useful. $\endgroup$ – C. E. Jun 28 '17 at 14:22
7
$\begingroup$

This is simpler:

start = DateObject[{2017, 6, 26}];
end = DateObject[{2017, 9, 1}];

Select[DateRange[start, end], 
  MatchQ[DayName[#], Monday | Tuesday | Friday] &][[;; 10]]

Mathematica graphics

DayRange is as close as it comes to a built in function with this purpose. It can select all weekdays in a range of dates, for example:

DayRange[start, end, "Weekday"]

Ideally, we'd be able to write something like

DayRange[start, end, Monday | Tuesday | Friday]

but this is not supported yet, which is why I had to make it slightly more complicated in my solution.

If selecting the end date is a problem we have to iterate. Check one date, is it a Monday, Tuesday or Friday? Add it to the list. Check the next date, and so on. Here is what an iterative solution could look like:

list = {};
date = DateObject[{2017, 6, 26}];
While[
 Length[list] < 10,
 If[
  MatchQ[DayName[date], Monday | Tuesday | Friday],
  AppendTo[list, date]
  ];
 date = DayPlus[date, 1];
 ]
list

Mathematica graphics

$\endgroup$
  • $\begingroup$ The idea is very good, but I would still like to avoid the end list. Respecting your reputation. $\endgroup$ – LCarvalho Jun 28 '17 at 14:33
  • $\begingroup$ @LCarvalho I added an iterative solution that doesn't require end. $\endgroup$ – C. E. Jun 28 '17 at 16:46
  • 1
    $\begingroup$ I tested it on February 24, 2020 to see if it worked. And it worked. This was a possible error that could arise ... $\endgroup$ – LCarvalho Jun 28 '17 at 17:50
3
$\begingroup$

I have created two functions, but these have been quite extensive:

f[initialDate_, nDays_, week_] := 
 With[{group = <|Sunday -> 1, Monday -> 2, Tuesday -> 3, 
     Wednesday -> 4, Thursday -> 5, Friday -> 6, Saturday -> 7|>}, 
  Drop[Flatten[
     NestList[# + 7 &, group[#] & /@ week - First[group[#] & /@ week],
       IntegerPart[
       nDays/Length[
         group[#] & /@ week - First[group[#] & /@ week]]]]], 
    nDays - Length[
      Flatten[NestList[# + 7 &, 
        group[#] & /@ week - First[group[#] & /@ week], 
        IntegerPart[
         nDays/Length[
           group[#] & /@ week - First[group[#] & /@ week]]]]]]] + 
   DateValue[DateObject[initialDate], "Day"]]

allDays[initialDate_, nDays_, week_] := 
 If[f[initialDate, nDays, week][[#]] <= 
     QuantityMagnitude[
      With[{year = DateValue[DateObject[initialDate], "Year"], 
        month = DateValue[DateObject[initialDate], "Month"]}, 
       DateDifference[{year, month}, 
        If[month == 12, {year + 1, 1}, {year, month + 1}]]]], 
    f[initialDate, nDays, week][[#]], 
    f[initialDate, nDays, week][[#]] - 
     QuantityMagnitude[
      With[{year = DateValue[DateObject[initialDate], "Year"], 
        month = DateValue[DateObject[initialDate], "Month"]}, 
       DateDifference[{year, month}, 
        If[month == 12, {year + 1, 1}, {year, month + 1}]]]]] & /@ 
  Range[nDays]

allDays[{2017, 6, 26}, 10, {Monday, Tuesday, Friday}]

{26,27,30,3,4,7,10,11,14,17}

$\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.