How do I determine if a given date is the Nth weekday of the month?

14,090

Solution 1

You could change the check of the week so the function would read:

private bool NthDayOfMonth(DateTime date, DayOfWeek dow, int n){
  int d = date.Day;
  return date.DayOfWeek == dow && (d-1)/7 == (n-1);
}

Other than that, it looks pretty good and efficient.

Solution 2

The answer is from this website. Copy/pasted here in case that site is ever lost.

public static DateTime FindTheNthSpecificWeekday(int year, int month,int nth, System.DayOfWeek day_of_the_week)
{
    // validate month value
    if(month < 1 || month > 12)
    {
        throw new ArgumentOutOfRangeException("Invalid month value.");
    }

    // validate the nth value
    if(nth < 0 || nth > 5)
    {
        throw new ArgumentOutOfRangeException("Invalid nth value.");
    }

    // start from the first day of the month
    DateTime dt = new DateTime(year, month, 1);

    // loop until we find our first match day of the week
    while(dt.DayOfWeek != day_of_the_week)
    {
        dt = dt.AddDays(1);
    }

    if(dt.Month != month)
    {
        // we skip to the next month, we throw an exception
        throw new ArgumentOutOfRangeException(string.Format("The given month has less than {0} {1}s", nth, day_of_the_week));
    }

    // Complete the gap to the nth week
    dt = dt.AddDays((nth - 1) * 7);

    return dt;
}

Solution 3

Here is what the MSDN have to say. Its VB, but it translates easily.

Solution 4

It looks like the language supplies date/day methods for a given date. If anybody was interested you can read about Zeller's congruence.

I don't think that's what they wanted you to do but you could find the day of week of the first day of a month from that. Now that I thought about it you could find the day of week for the given day as N and get that modulo 7.

Oh wait, is that the Nth occurance of a day of the week (like Sunday) or like the Nth weekday of the month! Okay I see the examples.

Maybe it would make a difference if you could construct a date such as the 1st of a month..

Given that it is Nth occurance of a day of the week, and that you can't fiddle with whatever datetime datatype, and that you have access to both a get day of week and get day of month functions. Would Sunday be a zero?

1) First, the day of the week would have to match the day of the week given.
2) N would have to be at least 1 and at most 4.
3) The day of the month would range between n*7*dayOfWeek + 1 and n*7*dayOfWeek + 6 for the same n.
- Let me think about that. If Sunday was the first.. 0*7*0+1 = 1 and Saturday the 6th would be 0*7*0+6.

Think 1 and 3 above are sufficient since a get day of month function shouldn't violate 2.

(* first try, this code sucks *)

function isNthGivenDayInMonth(date : dateTime;
                              dow : dayOfWeek;
                              N : integer) : boolean;
    var B, A : integer (* on or before and after day of month *)
    var Day : integer (* day of month *)
    begin
    B := (N-1)*7 + 1; A := (N-1)*7 + 6;
    D := getDayOfMonth(date);
    if (dow <> getDayOfWeek(date) 
        then return(false)
        else return( (B <= Day) and (A >= Day) );
    end; (* function *)

Hope there isn't a bug in that lol!
[edit: Saturday would have been the 7th, and the upper bound above (N-1)*7 + 7.]
Your solution looks like it would match 2 different weeks? Looks like it would always return zero for Sundays? Should have done pseudocode in C#.. short circuit && is like my if.. hey shouldn't Sunday the first match for N = 1 in months that start on Sunday?

 d/ 7 == n

That would result in (either 0 or 1)/7 == 1, that can't be right! Your || catches the (n-1) also, Robert has that. Go with Robert Wagner's answer! It's only 2 lines, short is good! Having (Day-1) mod 7
[edit: (Day-1) div 7] eliminates my unnecessary variables and 2 lines of setup.

For the record this should be checked for boundary cases and so forth like what if August 31st was a Sunday or Saturday.
[edit: Should have checked the end of week case too. Sorry!]

Solution 5

You can find a function which returns a date for the nth occurrence of particular week day in any month.

See http://chiragrdarji.wordpress.com/2010/08/23/find-second-saturday-and-fourth-saturday-of-month/

Share:
14,090
Kevin
Author by

Kevin

SOreadytohelp

Updated on June 03, 2022

Comments

  • Kevin
    Kevin almost 2 years

    Here is what I am trying to do: Given a date, a day of the week, and an integer n, determine whether the date is the nth day of the month.

    For example:

    • input of 1/1/2009,Monday,2 would be false because 1/1/2009 is not the second Monday

    • input of 11/13/2008,Thursday,2 would return true because it is the second Thursday

    How can I improve this implementation?

    private bool NthDayOfMonth(DateTime date, DayOfWeek dow, int n)
    {
        int d = date.Day;
        return date.DayOfWeek == dow && (d/ 7 == n || (d/ 7 == (n - 1) && d % 7 > 0));
    }