The calendar block isn't displaying properly. It can have the month starting on the wrong day. The reason is because it was reporting the day of week that 12:01am GMT was. For example, although Dec 1, 2007 starts on a Saturday morning, it is 12:01 am GMT when it is still Friday night in the U.S., and so if the default or a user's time zone is set to anything west of Greenwich, their calendar will have Dec 1 starting on Friday!

The theme_archive_block_calendar() function is the culprit. It actually contains two bugs, one is more obvious, and another subtle. The obvious one of reporting the first weekday of the month incorrectly, can be fixed by subtracting the value of variable_get('date_default_timezone', 0) from the $start variable. This will make the line that calculates $weekday actually report the day of the week that the 1st falls on in the right timezone.

The more subtle bug is that the PHP function strtotime() uses the TZ environment variable, if set, on the host system. If this environment variable is set to GMT, there's no problem, but if it is set to something else, there's a problem. Even with the above fix, the calendar may still report an erroneous start day of week. So the the strtotime(gmdate()) construct doesn't return the timestamp of GMT midnight on the first of the month, it returns the timestamp of the midnight of the 1st of the month in the local TZ. The way to remedy this is to use gmmktime to create the timestamp.

Here is the diff against the 5.x-1.7 version of archive.module:

344,346c344,348
<   // We use gmdate the first time so that we don't apply the user's timezone twice
<   $start = strtotime(gmdate('Y-m-01', $timestamp));
<   $weekday = array_search(format_date($start, 'custom', 'D'), $day_titles);
---
>   $start_year = format_date($timestamp, 'custom', 'Y');
>   $start_month = format_date($timestamp, 'custom', 'm');
>   $start = gmmktime( 0, 0, 0, (int)$start_month, 1, (int)$start_year );
>   $timezone = variable_get('date_default_timezone', 0);
>   $weekday = array_search(format_date($start - $timezone, 'custom', 'D'), $day_titles);

Enjoy, and thanks again for the great module.

Comments

jaysmall’s picture

Had the same problem, applied the changes Ross provided and the calendar display now works properly on my site.

Susurrus’s picture

While I would love to include this code, I don't fully understand why you subtract the default timezone for the site from the start time.

Edit: Okay, I think I figured it out. So you get the year and month that the user is in and then build a GMT timestamp for that time. After this point seems a little redundant, though. You should be able to use gmdate('D') to get the info you want directly from the $start variable instead of getting the default_timezone and using format_date(). What you're doing is building a date out in GMT from where the user is in their timezone, then you adjust it by the default timezone of the site and convert it back to the user's timezone. You should be able to use the following instead:

$start_year = format_date($timestamp, 'custom', 'Y');
$start_month = format_date($timestamp, 'custom', 'm');
$start = gmmktime( 0, 0, 0, (int)$start_month, 1, (int)$start_year );
$weekday = array_search(gmdate($start, 'D'), $day_titles);
jrisberg’s picture

Had the same problem, but the patch suggested by Susurrus has worked for me, as long as I fix the typo that the args to gmdate() are backwards. It should be ('D', $start).

Susurrus’s picture

Included in the dev versions for both the 5.x and 6.x branch. Let me know if those releases work for you. They'll be released tonight.

Susurrus’s picture

Status: Active » Fixed
Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.