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

前端 未结 8 1761
无人及你
无人及你 2020-12-03 11:14

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.

相关标签:
8条回答
  • 2020-12-03 11:21

    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.

    0 讨论(0)
  • 2020-12-03 11:22

    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;
    }
    
    0 讨论(0)
  • 2020-12-03 11:22

    Most of the answers above are partially accurate or unnecessarily complex. You could try this simpler function, which also checks if the given date is the last but Nth day of the month.

        public static bool IsNthDayofMonth(this DateTime date, DayOfWeek weekday, int N)
        {
            if (N > 0)
            {
                var first = new DateTime(date.Year, date.Month, 1);
                return (date.Day - first.Day)/ 7 == N - 1 && date.DayOfWeek == weekday;
            }
            else
            {
    
                var last = new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1);
                return (last.Day - date.Day) / 7 == (Math.Abs(N) - 1) && date.DayOfWeek == weekday;
            }
    
    0 讨论(0)
  • 2020-12-03 11:23

    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/

    0 讨论(0)
  • 2020-12-03 11:25

    In case you want a list of dates for a span of time (not just one) for the Nth DayOfWeek of a Month, you can use this:

    internal static List<DateTime> GetDatesForNthDOWOfMonth(int weekNum, DayOfWeek DOW, DateTime beginDate, DateTime endDate)
    {
        List<DateTime> datesForNthDOWOfMonth = new List<DateTime>();
        int earliestDayOfMonth = 1;
        int latestDayOfMonth = 7;
        DateTime currentDate = beginDate;
    
        switch (weekNum)
        {
            case 1:
                earliestDayOfMonth = 1;
                latestDayOfMonth = 7;
                break;
            case 2:
                earliestDayOfMonth = 8;
                latestDayOfMonth = 14;
                break;
            case 3:
                earliestDayOfMonth = 15;
                latestDayOfMonth = 21;
                break;
            case 4:
                earliestDayOfMonth = 22;
                latestDayOfMonth = 28;
                break;
        }
    
        while (currentDate < endDate)
        {
            DateTime dateToInc = currentDate;
            DateTime endOfMonth = new DateTime(dateToInc.Year, dateToInc.Month, DateTime.DaysInMonth(dateToInc.Year, dateToInc.Month));
            bool dateFound = false;
            while (!dateFound)
            {
                dateFound = dateToInc.DayOfWeek.Equals(DOW);
                if (dateFound)
                {
                    if ((dateToInc.Day >= earliestDayOfMonth) && 
                        (dateToInc.Day <= latestDayOfMonth))
                    {
                        datesForNthDOWOfMonth.Add(dateToInc);
                    }
                }
                if (dateToInc.Date.Equals(endOfMonth.Date)) continue;
                dateToInc = dateToInc.AddDays(1);
            }
            currentDate = new DateTime(currentDate.Year, currentDate.Month, 1);
            currentDate = currentDate.AddMonths(1);
        }
        return datesForNthDOWOfMonth;
    }
    

    ...and call it this way:

    // This is to get the 1st Monday in each month from today through one year from today
    DateTime beg = DateTime.Now;
    DateTime end = DateTime.Now.AddYears(1);
    List<DateTime> dates = GetDatesForNthDOWOfMonth(1, DayOfWeek.Monday, beg, end);
    // To see the list of dateTimes, for verification
    foreach (DateTime d in dates)
    {
        MessageBox.Show(string.Format("Found {0}", d.ToString()));
    }
    

    You could get the 2nd Friday of each month like so:

    List<DateTime> dates = GetDatesForNthDOWOfMonth(2, DayOfWeek.Friday, beg, end);
    

    ...etc.

    0 讨论(0)
  • 2020-12-03 11:44

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

    0 讨论(0)
提交回复
热议问题