views:

529

answers:

3

Given a standard piece of scheduling information, such as "the second Tuesday in June 2009" or "the last Friday in July 2009", what's the simplest and most efficient formula to translate that into a date?

Inputs:

  • w = Week of month, enumeration (1st, 2nd, 3rd, 4th or Last)
  • d = Day of week, enum Sun through Sat
  • m = Month, integer
  • y = Year, integer

EDIT (again) - It doesn't matter what day the week begins on; I want to get the wth instance of d in the given month. Thus the 2nd Sunday in June 2009 is 14 June, even though that technically falls in the 3rd week of June; similarly the 1st Sunday in June is 7 June, not null/exception.

+6  A: 

Something like:

static DateTime GetDate(int year, int month, DayOfWeek dayOfWeek,
        int weekOfMonth) {
    // TODO: some range checking (>0, for example)
    DateTime day = new DateTime(year, month, 1);
    while (day.DayOfWeek != dayOfWeek) day = day.AddDays(1);
    if (weekOfMonth > 0) {
        return day.AddDays(7 * (weekOfMonth - 1));
    } else { // treat as last
        DateTime last = day;
        while ((day = day.AddDays(7)).Month == last.Month) {
            last = day;
        }
        return last;
    }
}
Marc Gravell
(edited to handle "last" via a weekOfMonth <= 0)
Marc Gravell
Great answer again - thanks Marc!
Shaul
+1  A: 

EDITED to fix bug when weekday asked for was same as dayof week of first of month.

2nd edit to fix issue disc' by Marc

static DateTime GetDate(int year, int month, 
                DayOfWeek weekDay, int week)
{  
    DateTime first = new DateTime(year, month, 1);
    int iDow = (int)weekday, iFirst = (int)first.DayOfWeek;
    int adjust = (7+iDow-iFirst)%7 - 7;
    return first.AddDays(7*week + adjust);
}
Charles Bretana
Should that be 7*(week-1)? Even so, using that formula, "1st Sunday of June 2009" comes out to 31 May 2009.
Shaul
well, no, cause the adddays would be subtraction of up to six days when asking for day of week with smaller enum value than the day of week of the 1st, but was buggy when the dayofweek asked for was same as first of month...
Charles Bretana
With edit, 1st Sunday in Jan 2009 comes out as Monday the 5th...
Marc Gravell
Yes, missed that, hopefully 2nd edit fixes all...
Charles Bretana
A: 

using System;

namespace date_using_week_of_month {

public class Example
{
 public static DateTime WthDayDOfMonthM( int w, DayOfWeek d, DateTime month )
 {
  return first( d, month ).AddDays( 7 * (w - 1) );
 }

 private static DateTime first( DayOfWeek d, DateTime month )
 {
  DateTime first = new DateTime(
   month.Year, month.Month, 1 );
  while ( first.DayOfWeek != d )
  {
   first = first.AddDays( 1 );
  }
  return first;
 }
}

}

maxwellb