Juggling time zones
Handling times for different timezones is one of the usual things I had to face with every project that has in one way or the other involves the element of time.
The usual projects I work on store dates into a datetime field in the database. This means that the date must use the YYYY-MM-DD HH:MM:SS format (e.g. 2009-09-03 07:45:00).
One of the first things you’d want to do is to let the user specify a timezone setting for that user account (assuming this is in a multi-user environment, as most web applications are). You could view all the timezones using this code:
foreach(DateTimeZone::listAbbreviations() AS $timezone_abbreviation=>$timezones){
foreach($timezones AS $timezone)
if(isset($timezone['timezone_id']))
echo '<li>'.$timezone_abbreviation.' - ' . $timezone['timezone_id'] . '
<ul>
<li>Uses DST: ' . ($timezone['dst']===TRUE?'Yes':'No') . '</li>
<li>Offset: ' . $timezone['offset'] . '</li>
</ul></li>';
}
echo '</ul>';
You could modify the code above to create a drop-down list of the different timezones to make it easier for the user to pick a timezone (because simply writing GMT+8 or UTC+8 might be confusing for some people).
Next, we will have to convert all of our stored dates into a single timezone, for simplicity, I use GMT/UTC as a reference timezone (since it is easy to add timezone offsets to it). If you store your dates in a datetime field, you can perform the following conversion after retrieving the timestamp from the database:
// and $offset is the timezone offset we got based on the user's settings
$parsedtime = '2009-09-15 12:00:00';
$offset = 8*60*60; // this is GMT +8
// get the GMT counterpart of the parsedtime
$unix_time = strtotime($parsedtime . ' GMT');
echo gmdate('m d Y h:iA',$unix_time-$offset); // displays: 09 15 2009 04:00AM
So that means, 12nn of September 15, 2009 is 4am of September 15, 2009 in GMT/UTC.
Let’s say we had a Calendar application, and you wanted to set an alarm for 6pm on that same day. You could do the something like the this (assuming you wrote some sort of class for this thing):
echo $reminder->timeLeft();
Since the current date and time was 12nn of September 15, 2009, this means that the above reminder will display “6 hours left”, depending on how the timeLeft() method is formatted.
If we didn’t convert the date into a standard timezone, this will force our functions to use the server’s timezone setting and that might not be what you want.