VB.NET DateTime examples

How would you calculate which date is the fourth Thursday of a month? The fourth Thursday must be somewhere in the fourth week of the month, so at the latest on the  4 x 7 = 28th, or earlier. Then check if the 28th is a Thursday and if not, count back days until your reached a Thursday. The same procedure is valid for the 2nd Monday of a month = 2 x 7 = 14th or earlier. The algorithm has been worked out for Thanksgivingday. According to Wikipedia there a two versions of this holiday: an American and a Canadian.

Public Shared Function thanksgivingDayUSA(year As Integer) As DateTime
    '4th Thursday of November
    Dim returnDate As New DateTime(year, 11, 4 * 7)
    Do While returnDate.DayOfWeek <> DayOfWeek.Thursday
        returnDate = returnDate.AddDays(-1)
    Loop
    Return returnDate
End Function

Public Shared Function thanksgivingDayCanada(year As Integer) As DateTime
    '2nd Monday of October
    Dim returnDate As New DateTime(year, 10, 2 * 7)
    Do While returnDate.DayOfWeek <> DayOfWeek.Monday
        returnDate = returnDate.AddDays(-1)
    Loop
    Return returnDate
 End Function


DateTime example lastDayThisMonth

If you are coming from a VBA (for Excel) or VB6 environment, you are probably familiar with DateSerial. Let's say our problem is to determine the last day of a month, given a certain date. Using DateSerial the solution is quite simple:

Public Shared Function lastDayThisMonth(thisDate As DateTime) As DateTime
    Return DateSerial(thisDate.Year, thisDate.Month + 1, 0)
End Function

In this function we are cheating a little bit. Our starting point is thisDate as the actual input date. Then we go to the next month (adding +1 to the actual month) and then inserting '0' as a day. This '0' is the day before day 1 of the month, being the last day of the month before the next month, in fact being the last day of this month. DateSerial is used in VB6 and Excel VBA and can still be used in Visual Studio. DateSerial accepts days like '0' and months like '13' or higher. DateTime on the other hand is more strict and does not accept invalid arguments. So the following function, although Visual Studio does not give any warning, will not work:

Public Shared Function lastDayThisMonth(thisDate As DateTime) As DateTime
    Dim returnDate As New DateTime(thisDate.Year, thisDate.Month + 1, 0)
    return returnDate
End Function

The solution to this problem is as follows: calculate the first day of this month, then add one month and subtract one day:

Public Shared Function lastDayThisMonth(thisDate As DateTime) As DateTime
    Dim firstDay As New DateTime(thisDate.Year, thisDate.Month, 1)
    Return firstDay.AddMonths(1).AddDays(-1)
End Function

Do you agree the DateTime solution is more elegant than the DateSerial solution?