The first method is based on checking various times on different dates to resolve to a short list of time zones. The short list is by no means extensive, and is meant to provide the time zone offset -- not specifically the location of the client. The data is comprised of the most useful aspects of the Time Zone Database which keeps the data loaded on the client small.
The second method is to use the HTML5 Geolocation API combined with the GeoNames API. Latitude and longitude is provided by the client (when approved), and the name/offset of the time zone is fetched using JSONP via the GeoNames API. This method provides much more accurate location information -- though I haven't been able to get the two to methods to disagree about the actual offset, so if you don't need this level of location accuracy you can get by without it.
If you've ever done time zone specific logic in your applications you know it's a bit of a beast. First, you'll need to ask each user where they're located to know what time zone you should use when displaying any times converted to their local time. Wouldn't it be nice not to have to ask users for their time zone? That's one step removed from your sign up / configuration process, and maybe you don't even have a sign up process, in which case it's even harder to display local times.
I haven't found a really good solution for detecting a users time zone, and I'm not happy asking a user for it, so I wrote Temporal to determine it for me before ever having to ask. I'm putting it out there in case anyone else finds it useful as a tool, or a learning opportunity.
Then require temporal in your application.js:
//= require temporal
There's really not much to it. Call
Temporal.detect() to trigger the detection. This method sets a cookie on the
client, and the next request to the server will have that cookie, letting us use it to set the Rails Time.zone (which
is done for you in the Gem). It's important to note that the exact location of the user isn't guaranteed, so it should
be treated as the time zone, and not the location (eg. don't display it unless you have a way to change it).
Temporal.detect method takes two arguments:
- your GeoNames username -- can be created here and also turn on the web service here (it's near the bottom)
- a callback function
If you don't provide the first argument the HTML5 geolocation and GeoNames APIs will not be used.
The callback is called whenever the time zone is set or changed -- it can be called twice if you're using the GeoName API because Temporal first does the quick detection and sets the cookie based on that, and then calls through to the GeoNames API. Since the GoeNames API uses JSONP, the reponse may take a moment to update the cookie further and with more accuracy.
More reading about time zone handling in rails: What time is it? Or, handling timezones in Rails
Temporal is as efficient as possible when it comes to refreshing the users time zone and using the GeoNames API. It does this by caching the determined time zone for a month, and does a quick check on each page load to see if it looks like the users time zone has changed (if they're traveling, or have moved, etc.). If it looks like the time zone may have changed it will trigger the GoeNames API hit again for clarification.
Licensed under the MIT License
Copyright 2012 Jeremy Jackson