I'm writing a module that will move calendar events from another on-line calendar application into the Drupal Event module. Now that I've figured out how to create nodes from inside of a program, it's going fairly well. But I've run into a very annoying problem caused by the way that Drupal handles user time zones and time stamps. While I will be able to hack around it, this really ought to be fixed in the framework itself, since from reading the forums, it's clearly causing problems for users.

Here's a quick description of the problem. The Event module stores the start time as a Unix time number, which represents the number of seconds that have passed since January 1, 1970 GMT. The GMT (actually, UTC to be exact) is an important piece of this: if two computers running Unix are in different time zones, but are syncing to an external clock, they should be have the same number for the current time. The servers, though, have a notion of their own time zone, and use libraries to convert from the UTC time number into the current local time when they format a date for an application.

So how does Drupal (circa 4.5) deal with this?

  • Each user can store a "time zone" number, which is the number of seconds that local time is off from UTC. So if you live in Central Europe, during the winter, you are an hour ahead of UTC, and your number is 3600. I'm in California, and right now, I'm 8 hours behind UTC, and my number is -28800.
  • When Drupal formats a time number, it calls format_date (from common.inc), which takes a time number, adds your timezone offset to it, and calls the PHP function gmdate to format it

So what's wrong with that? There are a number of issues with this as far as it affects server applications like Drupal:

  • If your region has "Daylight Savings Time" or "Summer Time", on some day during the year (not the same day in every place), you need to change the time zone for the server, and every user as well if you are going to format the current time correctly for users
  • Worse yet, what do you do about time numbers that refer to dates that are not in the same part of the year? If your meeting on June 1 is at 12PM, do you really want to suddenly start displaying it as "11AM"? Because that's what Drupal does when you change the time zone number so that the current date formats correctly.
  • For those of you that are thinking that you can solve this by having Drupal account to the time zone, remember that (1) not every time zone observes summer time, (2) different time zones make the transition on different dates, and (3) if you are in Australia or in parts of South America, you are in summer time when the US and Europe are in winter time, and shifting everybody's time ahead 3600 seconds in April will mean dates down in Oz will be off by two full hours.

This is a mess, but it's how it works. That's the bad news. The good news is that most operating systems keep track of all of this stuff, and do a pretty good job of it. So the short solution of the problem is "let the OS take care of it" by coding Drupal's implementation in an OS neutral way that makes the OS solve the problem.

This isn't complete neat, since PHP's date functions don't make it as easy as it should be. But if you do the following, this will work both on the Unix based OSes and on Microsoft Windows:

  • If you only want to support server time, don't play with the time zone, and let PHP do the rest. The Unix time number is always right, and PHP will do the right thing during summer time. So don't use gmdate() to format dates; use date() instead, and PHP will just do the right thing.
  • If you need to support different time zones for each user, do something like this to covert Unix time number $ts into a formatted date:
    $old_tz = getenv("TZ");
    putenv('TZ=US/Pacific'); //see "man tzset" for how to find valid time zone names
    $formatted_date = date($my_format_string, $ts);
    if($old_tz)
       putenv("TZ=$old_tz");
  • You could also use a timezone library like PEAR's Date, although the approach above is probably faster, and I'd guess does a better job supporting summer time than the current implementation in Date_Timezone does

I'm not sure how the main developers of Drupal see this, but I hope that if they haven't considered changing this code, that they'd at least be willing to look at any patches folks like me could supply. Properly done, we could keep the changes to the code base limited to common.inc and user.inc (for the changed setting of time zone information), and a little bit of tweaking of the Event module to let it set the time zone correctly at the module level.

I'd be willing to supply the patches if y'all are willing to consider them. In the meantime, I need to get back to changing how Event stores dates and times.... ;-)

Cheers,
Rob Thorne
Torenware Networks

Comments

moshe weitzman’s picture

there is a new, much improved event.module coming any day now. it fixes this issue and about a hundred more. you can preview it now in crunchwelch's sandbox in Contrib repository. HEAD drupal only for now.

Torenware’s picture

Moshe,

Thanks. I pulled the module from CVS and gave it a look. Since I'm pretty tied to 4.5 for my current projects (at least until the modules I'm depending upon get ported up to HEAD), I'd need to back port the module to even test it. This turns out to be hard, since event is no longer a node type, and the new code uses 4.6 features to even display itself.

I'll give it another look as 4.6 gets further along, but for now, I'm going to hack on the 4.5 version.

Cheers,
Rob

Rob Thorne
Torenware Networks

Gerhard Killesreiter’s picture

There's a patch that try's do deal with soem DST issues:

http://drupal.org/node/11077

Maybe you can try it and report how it works for you.

Torenware’s picture

Gerhard,

Much thanks for the suggestion of the patch. It looks pretty clean, and my setup seems to run fine with it folded in.

I suspect I'll still have to hack into the Events module a bit (it's doing some of its own stuff with the time zone offset), but I'll report back as to what I needed to do in order to get the Event module working correctly with the patch.

Regards,
Rob

Rob Thorne
Torenware Networks

Torenware’s picture

The patch does a reasonable job. Event, though, does some really evil stuff with time stamps. Once I removed essentially all of the Event module's time zone handling (essentially, I forced it work in local time only), I get reasonable results.

This won't work for a site that needs to allow users to set their own time zones, or needs to post events in multiple regions, but for a site serving a community in a single geographic area, it works fine.

Anybody else is going to have a heck of a time of it, though.

Thanks again to both of you,
Rob

Rob Thorne
Torenware Networks