tags:

views:

356

answers:

1

I'm looking to create an MVC web page that displays the 12 months of the year in a calendar format. Inside each day in the month I will bold only the dates that have any activity (data from database). The dates with activity would also be hyperlinked to a route like /Activity/2008/12/25

i'm about to attempt to try the asp.net ajax control toolkit calendar control but was wondering if anyone else had any advice.

+3  A: 

Rendering a calendar is not extremely complicated. By using DateTimeFormatInfo in System.Globalization and the DateTime all the necessary information can be retrieved:

  • DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek
  • DateTimeFormatInfo.CurrentInfo.GetMonthName(month)
  • DateTimeFormatInfo.CurrentInfo.GetAbbreviatedDayName((DayOfWeek)dayNumber)

A month in the calendar can be rendered in a table:

_ _ _ 1 2 3 4 
5 6 7 8 9 ...

To dermine the number of empty cells at the begining something like this can be used:

DateTime date = new DateTime(year, month, 1);
int emptyCells = ((int)date.DayOfWeek + 7 
    - (int)DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek) % 7;

As there are maximum 31 days in a month and maximum 6 empty cells at begining, a month can be rendered on maximum Ceil(37 / 7) = 6 rows. So there are maximum 42 cells to render in a month, some of them will be empty.

A new row is inserted in the table each 7 (number of days in a week) cells.

int days = DateTime.DaysInMonth(year, month);
for (int i = 0; i != 42; i++)
{
    if (i % 7 == 0) {
        writer.WriteLine("<tr>");
        if( i > 0 ) writer.WriteLine("</tr>");
    }

    if (i < emptyCells || i >= emptyCells + days) {
        writer.WriteLine("<td class=\"cal-empty\">&nbsp;</td>");
    } else {
        writer.WriteLine("<td class=\"cal-day\"\">" + date.Day + "</td>");
        date = date.AddDays(1);
    }
}

Also, simply add an additional link in the non-empty cells to the desired route when the dates are with activity.

Aleris
I did end up going with your recommendation. Lots of control but for some reason it feels like this should be easier. Oh, and you did forget int days = DateTime.DaysInMonth(year, month); Thanks for the response.
Mouffette
Yes you are right. I felt the same way, then found myself coming back to this every time I need to implement a full year calendar :)
Aleris
Thanks for the sample implementation. However, you've got an error in there - the date = date.AddDays(1) should go in the last else, otherwise the date is incremented even when an empty cell is rendered, so in example May 2009 is missing the first five days and effectively all dates are wrong.
Pawel Krakowiak
@Pawel Thanks, I've made the modification.
Aleris