HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Listing the weeks in a given month

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thelistingweeksmonthgiven

Problem

I need to take a month (defined as a start and end date) and return a set of date ranges for each week in that month. A week is defined as Sunday through Saturday. A good way to visualize it is if you double click on your Windows date in the start bar:

The month of October 2011 has 6 weeks:


10/1-10/1


10/2-10/8


10/9-10/15


10/16-10/22


10/23-10/29


10/30-10/31

I can describe each week as a struct:

struct Range
   {
      public DateTime Start;
      public DateTime End;

      public Range(DateTime start, DateTime end)
      {
         Start = start;
         End = end;
      }
   }


I need to write a function that takes a month and returns an array of ranges within it. Here's my first attempt, which appears to work and addresses the obvious edge cases:

public static IEnumerable GetRange(DateTime start, DateTime end)
{
   DateTime curStart = start;
   DateTime curPtr = start;
   do
   {
      if (curPtr.DayOfWeek == DayOfWeek.Saturday)
      {
         yield return new Range(curStart, curPtr);
         curStart = curPtr.AddDays(1);
      }

      curPtr = curPtr.AddDays(1);
   } while (curPtr <= end);

   if(curStart <= end)
      yield return new Range(curStart, end);
}


I would like to know if there's a cleaner or more obvious approach to do the same. I'm not overly concerned about performance, but I'd like to improve code readability and make the algorithm a bit more concise. Perhaps there's a very creative solution involving a single LINQ expression or something.

Solution

Well, first of all your range only has to store the start date, as the weeks are always the same length:

struct Range {

  public DateTime Start { get; private set; }

  public DateTime End { get { return Start.AddDays(6); } }

  public Range(DateTime start) {
     Start = start;
  }

}


Getting the weeks can simply be done by looking for sundays starting six days into the previous month:

public static IEnumerable GetRange(int year, int month) {
  DateTime start = new DateTime(year, month, 1).AddDays(-6);
  DateTime end = new DateTime(year, month, 1).AddMonths(1).AddDays(-1);
  for (DateTime date = start; date <= end; date = date.AddDays(1)) {
    if (date.DayOfWeek == DayOfWeek.Sunday) {
      yield return new Range(date);
    }
  }
}


To clarify: This returns the whole weeks that have days in the month, not partial weeks created from the days in the month by grouping them by what week they belong to.

Code Snippets

struct Range {

  public DateTime Start { get; private set; }

  public DateTime End { get { return Start.AddDays(6); } }

  public Range(DateTime start) {
     Start = start;
  }

}
public static IEnumerable<Range> GetRange(int year, int month) {
  DateTime start = new DateTime(year, month, 1).AddDays(-6);
  DateTime end = new DateTime(year, month, 1).AddMonths(1).AddDays(-1);
  for (DateTime date = start; date <= end; date = date.AddDays(1)) {
    if (date.DayOfWeek == DayOfWeek.Sunday) {
      yield return new Range(date);
    }
  }
}

Context

StackExchange Code Review Q#5451, answer score: 8

Revisions (0)

No revisions yet.