Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying timezones without using UTC

Tags:

I've been reading up on how to do this all morning, and the general consensus is this: store your timestamps in UTC and calculate the offset from there.

However, like most people, I am maintaining an existing codebase and I can't change the way we store our dates. At least, not in the allotted time frame.

So my question is, can I safely do something like this?

// this is my time zone
$timestamp = strtotime($timestampFromDatabase);
date_default_timezone_set('America/New York');
$tz = date_default_timezone_get();

// this is theoretically their timezone, which will eventually
// be taken from a session variable
date_default_timezone_set('Europe/Paris');
$offset = time() - $timestamp;
$timestamp -= $offset;

// now that I have the offset, display dates like this
date('r', $timestamp);

Some people have advised against doing date arithmetic, but is what I'm doing here wrong? Is there a better way? Are there pitfalls I need to watch out for? I'm particularly interested in what kind of bugs this method could produce, and if any, who will they affect?

My boss is the kind of guy that doesn't care if the bug only affects 1% of the user base.

Edit: Can I make this any clearer? I don't seem to have too many takers on this. Anyone? Even a vague suggestion or a link would be immensely helpful.

like image 802
Alt-Rock Ninja Cowgirl Avatar asked Oct 13 '09 17:10

Alt-Rock Ninja Cowgirl


1 Answers

The short answer is that timezones are tricky to work with and no-one wants to tackle the difficult questions!

The longer, answer is this:

Firstly, you need to create a representation of your date, in their current timezones. The following are equivalent:

date_default_timezone_set('America/New York');

$date = new DateTime(null);

OR

$date = new DateTime(null, new DateTimeZone('America/New York'));   

This gives you a date with zone set to America/New York. We can easily convert it to the user timezone, in this case Europe/Paris with the next line:

$date->setTimezone(new DateTimeZone('Europe/London'));

You can use the following line to get the date/time represented at any point.

echo $date->format('d/m/Y H:i:s');

I strongly recommend this over arithmetic, as the built in PHP functions have knowledge of daylight saving times and lots of complicated things that you won't get right.


My test script in full:

date_default_timezone_set('America/Belize');

$date = new DateTime(null);

echo $date->format('d/m/Y H:i:s') . '<br>';

$date->setTimezone(new DateTimeZone('Europe/London'));

echo $date->format('d/m/Y H:i:s') . '<br>';
like image 86
David Snabel-Caunt Avatar answered Oct 12 '22 08:10

David Snabel-Caunt