What are we trying to do?
Rails makes it very easy to display dates/times are translated and offset properly for the current user.
The standard approach is to display a list of known timezones (time_zone_options_for_select) and then take that value and assign it to Time.zone somewhere early in your request.
With this setting, dates in things like your ActiveRecord models will be translated into your users local time (assuming you know what it is).
Anytime you can remove an unnecessary task for a user, your application gets better. Timezone selection is increasingly a thing of the past. By now you have probably seen plenty of articles explaining how you do this:
- Take this value and store it in a cookie or a hidden field (or just send it to the server via ajax)
- Use this value to offset time values
In Rails, this is particularly easy because not only does Time.zone accept a string representing the timezone name, but you can also specify an offset directly.
And this method works perfectly well….until you hit daylight saving time.
For example, on April 28th in Eastern Standard Time, using getTimezoneOffset() it correctly reported my offset as 14,400 seconds (4 hours). However, this is only because of daylight savings. Normally my offset would be 5 hours.
Setting my current timezone with a four hour offset gets me close, but ends up putting me off by 1 hour.
1 2 3
Now this kind of makes sense. Setting Time.zone via an offset does not have anyway of knowing whether or not it is daylight savings, so it simply ignores it. Adding even more complexity is the fact there are quite a few timezone overlaps. Running rake time:zones:local shows there are 5 different timezones which are UTC -05:00. So even if I did manage to figure out the offset should be 300 minutes, how would we know which of the five to choose? (btw, it defaults to the first in the list, which for -05:00 is Bogota).
The downer hear is there really is no perfect option here. Timezones are simply a mess and there will always be edge cases.
However, there is a bit of hope by using jsTimezoneDetect.
With jsTimezoneDetect you can retrieve the Olson timezone name, offset, and whether or not it daylight savings time or not. Even better, with the Olson name you can remove most of the ambiguity in setting the Time.zone.
We are using jsTimezoneDetect on KickoffLabs and it has worked great. We have never had to ask our customers to choose from a monster list of timezones and we can send them reminders/etc at times that are much more likely to get a response (ie, status emails are sent at 8 am local time).
I am going to use jsTimezoneDetect in a couple of other projects, so over the past weekend I took some time to automate it’s usage.