Figuring the First Visible Day on Month View

Derek Harmon / Wednesday, April 29, 2009

Have you ever wondered why the first visible day is what it is on the WebMonthView?  I know many of you have.  Why can't it just be the 1st day of the month? Why is it a different date from month to month?  For ages, calendars have driven people stark raving into monasteries, but I'm going to shed light on these questions and others.

WebMonthView is always 6 weeks long. That's longer than the average month (and even the not-so-average months), so we have these extra days around the month - what to do with them?  Can't let up to 14 perfectly good days go to waste.

WebMonthView does a balancing act to put some days ahead of the month, and other days after it. Users respond well to balance in a presentation, it's not just good UI design but equally good fung shui.  How many days should appear in front of the month?

Well, if there is only one or two days in front of the month - feels kind of short-shrifted, doesn't it? All those extra days tack onto the end.  So how many to lead off with?  At least half-a-week you think?  That feels like a fair number, right?  Not too small, not too large.

But wait, there's a problem with simply adding half-a-week to the beginning of the month.  Because the left side of the month always starts with the FirstDayOfWeek.  This is a culturally-dependent day of the week.  In Europe your users may start their week on a Monday instead of a Sunday, and any other day of the week is also possible.  By default, WebSchedule picks this up from the culture of your Web application but you can also set it yourself.

Why is this a problem? Because sometimes the first day of the month falls on a day (say, Tuesday), that just doesn't want to cooperate with being half-a-week in front of the required FirstDayOfWeek.  If the FirstDayOfWeek is Sunday, then a first day of the month that is a Tuesday is too close.  Well, we just have to keep going then.  But, how far?  No choice really, it has to be the next FirstDayOfWeek, which goes back another week.  So that the leading days on the calendar could be between one-half of a week, and 1 1/2 weeks.  Now that's as far as it would go, because at that point we have our minimum half-a-week of leading space.

So you're probably thinking to yourself now that you can understand what the WebMonthView is doing, and maybe you can even calculate it yourself (as calendar math goes, this is way simpler than some algorithms.)  If you wanted to find the first visible day in C# for instance, you would write something like this:

   // Starting with the first day of the current calendar month
   DateTime firstVisible = new DateTime( 2009, 5, 1);

   // Subtract at least half-a-week.
   firstVisible = firstVisible.AddDays( -4.0);

   // Keep backing up a day until the first visible day is on
   // the first day of the week.
   while ( firstVisible.DayOfWeek !=
      WebScheduleInfo1.FirstDayOfWeekResolved )
   {
       firstVisible = firstVisible.AddDays( -1.0);
   }

   // Last visible day will be six weeks less one day later.
   DateTime lastVisible = firstVisible.AddDays( 41.0);

There's one more wrinkle to calculating the first visible day, and that's compressed weekends.  Now let me be the first to remark, I don't know who wants their weekends compressed!  Yet, it is a useful feature when most of your activities are going to be scheduled on weekdays, so that each column of days in the WebMonthView take up only one-sixth of its width (instead of one-seventh when compressed weekends are turned off.)

When you set WeekendDisplayFormat to Compressed, the FirstDayOfWeek effectively cannot be a Sunday anymore (would sort of slice the weekend in half if it could.)   If it is set to Sunday, then for purposes of the first visible day determination you must treat it as Monday (because Monday will be that leftmost column on the calendar when Sunday is sitting beneath Saturday over on the right).  So everyone check that condition, and adjust accordingly when calculating the first visible day.