Skip to Navigation | Skip to Content



Rails Timezones | October 5th, 2008

In my spare time I have been working on a geo-location application that runs on a BlackBerry mobile phone connecting to a Rails server where the geo data is stored.

If you happen to still be using Rails < 2.1 then this may be interesting, however, with the recent release of 2.1 timezones have been fixed up pretty well. Of course I wanted to get something that worked for my application in pre 2.1 days so I rolled together a few different libraries that seems to work pretty well. Having said that, the JavaScript will help you determine a users timezone no matter what version of Rails you are using.

The particular use case that I want to hit is that people can login to the web application from wherever they want and the application will automagically display the times in the timezone of the user viewing the site - not the timezone of the user that created the geo data and not the timezone of the server.

The general approach taken is to get the users timezone offset through JavaScript in the browser, then save that in the users profile, and then have a helper method to convert any times that are saved in the servers timezone to the users local zone.

Prerequisites

Gems: tzinfo (0.3.9, 0.3.8), tztime (0.1.0)

Plugins, tzinfo_timezone, tztime

Now for the code

So how do we figure out the users timezone? Through JavaScript of course! In application.js put the following script at the top - don’t put it on the onload event since it should set as soon as a user hits the page:


Cookie.set("tz", (new Date()).getTimezoneOffset());

This sets a cookie in the browsr to be the JavaScript timezone offset, which we will use later on the server. Note that this is using a simple cookie abstraction.

Now in application.rb we need some magic that will take that timezone offset from the cookie and update the users profile with their current timezone. This will be achieved with an around_filter (damn I love around filters) like so:


around_filter :set_timezone

def set_timezone
  if logged_in? && browser_timezone && (browser_timezone.name != current_user.time_zone || current_user.time_zone.nil?)
    current_user.update_attribute(:time_zone, browser_timezone.name)
  end
  TzTime.zone = logged_in? ? current_user.time_zone : browser_timezone
  yield
  TzTime.reset!
end

def browser_timezone
  return nil if cookies[:tz].blank?
  @browser_timezone ||= begin
    min = cookies[:tz].to_i
    TimeZone[-min/60]
  end
end

That takes care of getting the users current timezone. Now all we have left is to make it accessible to the application with a simple function in the application_helper.rb as follows:


def local_time(time_at)
  TimeZone[TzTime.zone].utc_to_local(time_at.utc)
end

Finally, we can just call local_time from anywhere passing in a time that is in the servers timezone from the database:


local_time(location.updated_at)

So if you are stuck on Rails < 2.1 that is a good approach to getting timezones working.

Posted in AJAX, Components, Flex, Uncategorized, Web | 2 Comments » | Add to Delicious | Digg It

This entry was posted on Sunday, October 5th, 2008 at 12:15 pm and is filed under AJAX, Components, Flex, Uncategorized, Web. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

2 Responses to “Rails Timezones”

  1. Detecting Browser Time Zone with Rails « Spongecell Tech Blog Says:

    [...] time zone because I wanted to try the new time zone functionality in Rails 2.1. I found this post from Dave Johnson. To my disappointment this was the same solution Spongecell used in the personal calendar 3 years [...]

  2. Chris Hobbs Says:

    Here’s an alternative solution that doesn’t require using a cookies but that does use jquery. For a simple use of time zones it could be a cleaner solution.
    http://spongetech.wordpress.com/2009/02/27/detecting-browser-time-zone-with-rails/

Leave a Reply


Search Posts

Archives

Categories