tags:

views:

80

answers:

5

In C#, i want to show the first week in a calendar (in a html table) and i am trying to figure out the most elegant algorithm to generate the right days.

If the first day of the week is not Sunday, i want to show the days of preceding month (like you would see on a regular calendar). So, as an input you have a current month. In this case May. I want to generate this:

Month: May

 <table>
 <tr>
   <th>S</th>
   <th>M</th>
   <th>T</th>
   <th>W</th>
   <th>TH</th>
   <th>F</th>
   <th>Sa</th>
 </tr>
 <tr>
   <td>25</td>
   <td>26</td>
   <td>27</td>
   <td>28</td>
   <td>29</td>
   <td>30</td>
   <td>1</td>
 </tr></table>

so it should display something like this (ignore the alignment)

S | M | T | W | Th | F | Sa |
25 - 26 - 27 - 28 - 29 - 30 - 1

given that each month would have the start of day be a different day of the week, i am trying to figure out an elegant way to get the values of this data using the DateTime object. I see it has a dayofweek property on a date.

i am generating this table in C# on my server to pass down to a html page.

A: 

Here's one simple way to do this.

    //Code not tested thoroughly.
    private DateTime[] GetWeek(int month)
    {
        DateTime firstDayofMonth = new DateTime(DateTime.Now.Year, month, 1);
        if (firstDayofMonth.DayOfWeek == DayOfWeek.Sunday)
            return GetWeek(firstDayofMonth);
        else
        {
            DateTime sundayOfPreviousMonth = firstDayofMonth;
            do
            {
                sundayOfPreviousMonth = sundayOfPreviousMonth.AddDays(-1);
            } while (sundayOfPreviousMonth.DayOfWeek != DayOfWeek.Sunday);
            return GetWeek(sundayOfPreviousMonth);
        }
    }

    private DateTime[] GetWeek(DateTime date)
    {
        if (date.DayOfWeek != DayOfWeek.Sunday)
            throw new ArgumentException("Invalid weekday.");
        DateTime[] week = new DateTime[7];
        for (int i = 0; i < week.Length; i++)
        {
            week[i] = date.AddDays(i);
        }
        return week;
    }
this. __curious_geek
+2  A: 

You can use the following code to get the first week:

public static IEnumerable<DateTime> GetFirstWeek(int year, int month) {
    DateTime firstDay = new DateTime(year, month, 1);
    firstDay = firstDay.AddDays(-(int) firstDay.DayOfWeek);
    for (int i = 0; i < 7; ++i)
        yield return firstDay.AddDays(i);
}
Julien Lebosquain
you beat me by 46 seconds. +1
AZ
And what if week starts from e.g. Monday? You'll get `25, 26, 27, 28, 29, 30, 1`, but actually week starts from Monday, the 26th of April.
Alex
Depends on what system you use. The western one considers start of the week on Sunday. If you want to start with Monday just add one day to the firstDay variable
AZ
@AZ: I thought that the week starts with monday in (whole) europe, but since you are from Romania ...
tanascius
@AZ, e.g. week starts on Monday, `-(int)firstDay.DayOfWeek` gives `0` (for Sunday); adding one day gives `1` instead of `6` (take March, 2009).
Alex
@Alex: The question asked for Sunday as the first day. Using the current culture in a web page is not necessarily what you need. If the week is defined and expected to begin on a given day for this page because it's a business rule, showing a different calendar based on the user's browser language would be odd. If that's not the case, then your answer is better.
Julien Lebosquain
@Julien Lebosquain, there is nothing about Sunday here (except `If the first day of the week is not Sunday, ...`) so there is no business rule specified.
Alex
@Alex - don't know what are we nitpicking about. The OP asked for a way to calculate the desired week. We gave him an approach. The solutions posted are supposed to give him a hint in the right direction. He is free to implement it in a way that makes sense in his particular context
AZ
and from the original question : <tr> <th>S</th> <th>M</th> <th>T</th> <th>W</th>seems that the week starts on Sunday for the OP
AZ
+2  A: 
public static IEnumerable<DateTime> GetFirstWeek(int month, int year)
    {
        var firstDay = new DateTime(year, month, 1);
        var dayOfWeek = firstDay.DayOfWeek;
        var firstWeekDay = firstDay.AddDays(-(int)dayOfWeek);

        for (int i = 0; i < 7; i++)
        {
            yield return firstWeekDay.AddDays(i);
        }
    }
AZ
A: 

Check this code:

var days = new[]
{
    "S", "M", "T", "W", "TH", "F", "Sa"
};
var date = DateTime.Parse( "01.05.2010" );
var dayOfWeek = (int)date.DayOfWeek;

for( var i = 0; i < 7; i++ )
{
    Console.WriteLine( days[i] + ": " + date.AddDays( i - dayOfWeek ) );
}

This is just code to give you an idea - for instance should you use a CultureInfo to parse your date. I use any date as an input right now, but you can cut it down to the first day of each month, too.

tanascius
+1  A: 

This should work:

DateTime date = new DateTime(year, month, 1);
DayOfWeek firstDay = CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
int daysBack = (7 + date.DayOfWeek - firstDay) % 7;

Enumerable.Range(-daysBack, 7)
    .Select(x => date.AddDays(x))
    .ToList()
    .ForEach(d => 
    {
        // a place for html generation
    });
Alex
+1 for the elegant Linq approach
AZ