views:

5765

answers:

9

I need to get a list of weeks for a given month, with Monday as the start day.

So for example, for the month of February 2009, this method would return:

2/2/2009
2/9/2009
2/16/2009
2/23/2009
A: 

Just change the response line to what ever you need to do with it

protected void PrintDay(int year, int month, DayOfWeek dayName)
{
  CultureInfo ci = new CultureInfo("en-US");
  for (int i = 1 ; i <= ci.Calendar.GetDaysInMonth (year, month); i++)
  {
    if (new DateTime (year, month, i).DayOfWeek == dayName)
      Response.Write (i.ToString() + "<br/>");
  }
}

Quick solution: i don't think there is a built in function for it....

Glennular
If you use this approach, you might want to hoist the GetDaysInMonth call first, rather then re-calculate it for every day (plus 1).
Marc Gravell
+7  A: 
public static List<DateTime> GetWeeks(
    this DateTime month, DayOfWeek startOfWeek)
{
    var firstOfMonth = new DateTime(month.Year, month.Month, 1);
    var daysToAdd = ((Int32)startOfWeek - (Int32)month.DayOfWeek) % 7;
    var firstStartOfWeek = firstOfMonth.AddDays(daysToAdd);

    var current = firstStartOfWeek;
    var weeks = new List<DateTime>();
    while (current.Month == month.Month)
    {
        weeks.Add(current);
        current = current.AddDays(7);
    }

    return weeks;
}
Robert Wagner
Rather than being clever with AddDays, just new up a new DateTime replacing the day with 1. Isn't that more clear?
Larsenal
Robert's is the pattern I went with, but I refactored his code into an extension method. Thanks!
Daniel Schaffer
@Larsenal - it's a little more tricky than that - replacing the day with one would give us the first of the month, but we also need the first day in the month that is the start of a new week, according to the day that is specified as the start of a week.
Daniel Schaffer
@Daniel - Good point
Larsenal
When I edited Robert's code, I added a few more variables to make it clearer what I was doing, and also changed the expression in the while statement.
Daniel Schaffer
Realized I got the calculation of first day wrong, it should be DayRequired - CurrentDayOfWeek
Robert Wagner
A: 

Something like the following pseudo-code should work:

  • Determine the start date of the month (use month and year from a date and set the day to 1
  • Determine the end date of the month (start date + 1 month)
  • Determine the first date that is a monday (this is your first item in the list)
  • Add 7 days to find the next date and repeat until you read or pass the month end
Rune Grimstad
A: 
int year = 2009;
int month = 2;
DateTime startDate = new DateTime(year, month, 1);
DateTime endDate = startDate.AddMonths(1);
while (startDate.DayOfWeek != DayOfWeek.Monday)
    startDate = startDate.AddDays(1);
for (DateTime result = startDate; result < endDate; result = result.AddDays(7))
    DoWhatYouWant(result);
chaowman
A: 

How about this?

  public IEnumerable<DateTime> GetWeeks(DateTime date, DayOfWeek startDay)
  {
     var list = new List<DateTime>();
     DateTime first = new DateTime(date.Year, date.Month, 1);

     for (var i = first; i < first.AddMonths(1); i = i.AddDays(1))
     {
        if (i.DayOfWeek == startDay)
           list.Add(i);
     }

     return list;
  }
Matt Brunell
+2  A: 

Here's a solution (effectively one line) using C# 3.0/LINQ, in case you're interested:

var month = new DateTime(2009, 2, 1);
var weeks = Enumerable.Range(0, 4).Select(n => month.AddDays(n * 7 - (int)month.DayOfWeek + 1)).TakeWhile(monday => monday.Month == month.Month);
Noldorin
A: 

Hi.

I see you got your answer, but I wanted to share with you a helper class I created for one of my projects. It's far to be a comprehansive class, but might help...

public static class WeekHelper {

#region Public Methods
public static DateTime GetWeekStart(DateTime date) {
    DateTime weekStart;
    int monday = 1;
    int crtDay = (int)date.DayOfWeek;
    if (date.DayOfWeek == DayOfWeek.Sunday)
        crtDay = 7;
    int difference = crtDay - monday;
    weekStart = date.AddDays(-difference);
    return weekStart;
}
public static DateTime GetWeekStop(DateTime date) {
    DateTime weekStart;
    int sunday = 7;
    int crtDay = (int)date.DayOfWeek;
    if (date.DayOfWeek == DayOfWeek.Sunday)
        crtDay = 7;
    int difference = sunday - crtDay;
    weekStart = date.AddDays(difference);
    return weekStart;
}
public static void GetWeekInterval(int year, int weekNo,
    out DateTime weekStart, out DateTime weekStop) {
    GetFirstWeekOfYear(year, out weekStart, out weekStop);
    if (weekNo == 1)
        return;
    weekNo--;
    int daysToAdd = weekNo * 7;
    DateTime dt = weekStart.AddDays(daysToAdd);
    GetWeekInterval(dt, out weekStart, out weekStop);
}
public static List<KeyValuePair<DateTime, DateTime>> GetWeekSeries(DateTime toDate) {
    //gets week series from beginning of the year
    DateTime dtStartYear = new DateTime(toDate.Year, 1, 1);
    List<KeyValuePair<DateTime, DateTime>> list = GetWeekSeries(dtStartYear, toDate);
    if (list.Count > 0) {
        KeyValuePair<DateTime, DateTime> week = list[0];
        list[0] = new KeyValuePair<DateTime, DateTime>(dtStartYear, week.Value);
    }
    return list;
}
public static List<KeyValuePair<DateTime, DateTime>> GetWeekSeries(DateTime fromDate, DateTime toDate) {
    if (fromDate > toDate)
        return null;
    List<KeyValuePair<DateTime, DateTime>> list = new List<KeyValuePair<DateTime, DateTime>>(100);
    DateTime weekStart, weekStop;
    toDate = GetWeekStop(toDate);
    while (fromDate <= toDate) {
        GetWeekInterval(fromDate, out weekStart, out weekStop);
        list.Add(new KeyValuePair<DateTime, DateTime>(weekStart, weekStop));
        fromDate = fromDate.AddDays(7);
    }
    return list;
}
public static void GetFirstWeekOfYear(int year, out DateTime weekStart, out DateTime weekStop) {
    DateTime date = new DateTime(year, 1, 1);
    GetWeekInterval(date, out weekStart, out weekStop);
}
public static void GetWeekInterval(DateTime date,
    out DateTime dtWeekStart, out DateTime dtWeekStop) {
    dtWeekStart = GetWeekStart(date);
    dtWeekStop = GetWeekStop(date);
}
#endregion Public Methods

}

Adi
A: 

This works beautifully! All you have to do is get the first day of the month you want to get the weeks for and then this will give you the first day of every week. You need to get 5 weeks (not 4) so the Enumerable.Range counts out 5 instead of 4.

var date = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
var weeks = from n in Enumerable.Range(0, 5)
   select date.AddDays(7 * n + (-1 * (int)date.DayOfWeek));
Tim
+2  A: 
 // Get the weeks in a month

 DateTime date = DateTime.Today;
 // first generate all dates in the month of 'date'
 var dates = Enumerable.Range(1, DateTime.DaysInMonth(date.Year, date.Month)).Select(n => new DateTime(date.Year, date.Month, n));
 // then filter the only the start of weeks
 var weekends = from d in dates
                where d.DayOfWeek == DayOfWeek.Monday
                select d;
Faisal Hasnain
Clever! +1 for making the purpose of the code clearer with LINQ
Daniel Schaffer