Get dates in future for only certain days of the week. DateInterval?

Having a tough time wrapping my head around this one. I am trying to make a study schedule for the user based on the days of the week they would select as the days they would plan to study. For example, if the user chooses to study only on Mondays, Wednesdays, and Thursdays, I would like to get the dates as such:
Monday: session 1
Wednesday: session 2
Thursday: session 3
next Monday: session 4
and so on…

I was thinking of using a DateInterval, and still think this is the way to go, but the date interval would be different for each of these days. M to W is DI 2. W to Th is DI 1. Th to M is DI 4

Without needing to have an enormous if…then for all possible scenarios, is there an easier way to accomplish this, considering also that of course, M W Th will not always be the selected study days?

i think its more or less a while wend loop with dateinterval of 1 day.
for the loop you could use a start and end date as range or a count of sessions.
you have a specification (could be a true/false array for weekdays) / condition when the day is ok or not and the output is a list of DateTime.
you need a class with a few methods and propertys to handle this.

Thanks for the reply Markus. I will play around with this and see how I make out

With @MarkusR’s idea, you could improve it by computing the next wanted day. So, with your example of Mondays, Wednesdays and Thursdays, you can do something like that (example written from scratch, not tested in the IDE):

var Days() as Integer=Array(2,4,5) '2=Monday, 4=Wednesday, 5=Thursday; values defined like DateTime's DayOfWeek and must conform to it.
var CurrentDate as DateTime

//Init the date to the first day you want in this line. Must be on a day set in Days().

//Later, in the loop:
do
//Earlier code if you want, then:

var DayIndex as integer=Days.IndexOf(CurrentDate.DayOfWeek) 'Since CurrentDate would always be Monday, Wednesday or Thursday (or the set you'd have defined), we'd find its day index in the array

if DayIndex=-1 then
Break 'Should never happen, but for sake of safety, avoid infinite loops
//raise an exception
end if
var NextDay as Integer=Days((DayIndex+1) mod (Days.LastIndex+1) 'Get the next day in the array, or back to the first one if we're on the last
var DaysInterval=NextDay-DayIndex
if DaysInterval<0 then DaysInterval=DaysInterval+7 'Start again for next week

CurrentDate=CurrentDate.AddInterval(0,0,DaysInterval,0,0,0,0) 'Add the number of days. CurrentDate would always fall to the next day you want.

//Do something with CurrentDate; exit the loop when you're finished
Loop

Of course, you can have more or less days in the array (Days) and different days. Just fill Days with the days you need.

Here’s an extension method that will return the date of the next day of week passed.

Public Function DateOfNextDayOfWeek(Extends dt As DateTime, DayOfWeek As Integer) As DateTime
  If DayOfWeek < 1 Or DayOfWeek > 7 Then
    Var err As New InvalidArgumentException
    err.Message = "A Day of week has been passed that is out of range 1-7"
    Raise err
  End If
  
  Var Result As DateTime = dt.AddInterval(0, 0, If(dt.DayOfWeek < DayOfWeek, DayOfWeek - dt.DayOfWeek, (DayOfWeek + 7) - dt.DayOfWeek))
  Return  Result
  
End Function

Pop this into a module and your DateTime instances will now have the ability to return the date of say the next Wednesday after the Date by passing 4 as the DayOfWeek.

HTH

My Idea

Private Function CreateDateSeries(fromDate As DateTime, toDate As DateTime, DayOfWeekAllowed() As Boolean) As DateTime()
  
  Var dates() As DateTime
  
  Var currentDate As DateTime = fromDate
  
  Do
    
    If DayOfWeekAllowed(currentDate.DayOfWeek) = True Then '1=Sunday, 7=Saturday
      dates.AddRow(currentDate)
    End If
    
    currentDate = currentDate + New DateInterval(0,0,1) '+1 Day
    
  Loop Until currentDate > toDate
  
  Return dates
End Function

Test

Var fromDate As DateTime = DateTime.Now
Var toDate As DateTime = DateTime.Now + New DateInterval(0,3,0)

Var dates() As DateTime = CreateDateSeries(fromDate,toDate ,Array(False,False,True,False,True,False,True,False))

System.DebugLog fromDate.ToString(DateTime.FormatStyles.Full) + " - " + toDate.ToString(DateTime.FormatStyles.Full)

For Each d As DateTime In dates
  System.DebugLog d.ToString(DateTime.FormatStyles.Full)
Next

Thank you all for the replies and sample code! I found that Markus’s solution worked the best for me. Really appreciate this. Spent much of yesterday afternoon trying out different ways but still just could not get it. All set now :slight_smile:

1 Like
Forum for Xojo Programming Language and IDE. Copyright © 2021 Xojo, Inc.