views:

267

answers:

3

Hi,

I'd like to be able to guess the user's timezone offset and whether or not daylight savings is being applied. Currently, the most definitive code that I've found for this is here:

http://www.michaelapproved.com/articles/daylight-saving-time-dst-detect/

So this gives me the offset along with the DST indicator.

Now, I want to use these in my PHP scripts in order to ouput the local date/time for the user....but what's best for this? I figure I have 2 options:

a) Pick a random timezone which has the same offset and DST setting from the output of timezone_abbreviations_list(). Then call date_timezone_set() with this in order to apply the correct treatment to the time.

b) Continue treating the date as UTC but just do some timestamp addition to add the appropriate number of hours on.

My feeling is that option B is the best way. The reason for this is that with A, I could be using a timezone which although correct in terms of offset/dst, may have some obscur rules in place behind the scene that could give surprising results (I don't know of any but nonetheless I don't think I can rule it out).

I'd then re-check the timezone using Javascript at the start of each session in order to capture when either the user's timezone changes (very unlikely) or they pass in to the DST period.

Sorry for the brain dump - I'm really just after some sort of reassurance that the approaches above are valid.

Thanks,

James.

+2  A: 

If this is a poll, then "b" is my vote.

Firstly, all times should be stored in UTC. This is dogma. It's very sensible dogma, the kind about which you end up saying "I sure wish I had followed that," after your project gets more complicated. Among other things, it is the only unambiguous, consistent way to store all points in time. Any timezone with daylight savings time has ambiguous time references around the switch (1:30 am usually happens twice, for example). Also, when converting between timezones, most of the time you end up using UTC as an intermediary anyway.

Second of all, you have to decide whether your site is international or not. If not, then you make rules for the six U.S. time zones and end it. With three browsers reporting timestamps in their own whacky ways, that's still only 18 cases, and it should be possible to handle them. Anything beyond that, and you should assume that it requires an advanced degree to anticipate daylight savings time differences. The times switch on different days in different places.

Your biggest problem with b is that, if this is a calendar-like application, scheduling will still be an issue if you can't accurately determine what time zone someone is in. For example, suppose it's February. No one is on DST. Someone schedules something for 6pm (local) on May 5. You see the offset is UTC-4. How do you know whether that person is in New Brunswick, which observes DST (in which case the time meant is 2100 UTC), or Puerto Rico, which does not (in which case the time meant is 2200 UTC? It's a tricky question. This post may have some help.

David Berger
Hi David,Thanks very much for your response. Your point around scheduling has sparked off plenty of conversation here so much appreciated. Checking out that link now...James.
James
A: 

If you want to rely on javascript you can simply send the utc time/timestamp back and forth and let the client convert it to its local time representation.

edit: simple self-contained example (using jquery)

<html>
  <head>
    <title>...</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&gt;&lt;/script&gt;
    <script type="text/javascript">
      function foo(){
        $('.time').each( function() {
          var t = $(this);
          var d = new Date(Date.parse(t.text()));
          t.text(d.toLocaleString());
        });
      }
    </script>
  </head>
  <body>
    <div class="time"><?php echo gmdate(DateTime::RFC1123); ?></div>
    <button onclick="foo()">local time</button>
  </body>
</html>

If javascript is not available the user still sees a date/time though it's in UTC.
edit2: And there is a javascript library (or was it even a jquery plugin?) that does this kind of things plus some nifty conversions like "an hour ago", "last week" ..something like that. But I forgot the name :(

VolkerK
A: 

I think that without knowing the exact timezone, There will always be a chance you miss out on some obscure rule.
As with most internationalization issues, there tend more obscure rules than you expect.

I would however go for option A: "pick a likely timezone with the correct offset" exactly because timezone stuff tends to be more complicated than you would expect. especially when you take daylight saving changes into account. If you go for option A, you can use the standard functions provided by PHP.

You could combine this with other metrics to improve your quality of prediction; for example:

  • Based on visitor statistics: pick the timezone where most visitors come from;
  • Based on accept_headers: match the language to a timezone;
  • based on IP-geolocation: match with country in correct timezone.

Combining the above should give a quite reasonable estimate. But 100% certainty cannot be achieved.

Jacco