Rails Time Zone Guide for Beginners

Posted by labrat

Making your rails app aware of time zones can be a real pain. There's really nothing special about it. You simply want your app to display dates and time according to whatever time zone the end user happens to be in. The problem is that you have the server's time and the user's time and whatever values stored in the database for dates and time. This isn't supposed to be a detailed guide from beginning to end but a simple walk through to explain some things that tripped me up. Your mileage will vary. The first thing you need to do is follow all the steps in this excellent guide from Caboo.se. In my approach, I changed the set_timezone filter in application.rb to the following:

  private
  
  def set_timezone
    if logged_in? && !current_user.time_zone.nil?
      TzTime.zone = current_user.tz
    else
      TzTime.zone = TZInfo::Timezone.new(ENV['TZ'])
    end
    yield
    TzTime.reset!
  end
This takes advantage of the fact that I have this in environment.rb:
  config.active_record.default_timezone = :utc
  ENV['TZ'] = 'America/Los_Angeles'
You can of course, replace "ENV['TZ']" in the filter above with a valid time zone string such as 'America/Los_Angeles'. You always need to have a valid TZInfo::Timezone object when setting the time zone which is why we convert the string to a time zone object by calling TZInfo::Timezone.new("the_time_zone_string") otherwise you get funky errors like "TZInfo::Timezone constructed directly" and a mess of others. For my views I always format the date time into something more user friendly using strftime so I have this in one of my modules to convert the time in views.
  def tz_convert
    TzTime.zone.nil? ? self : TzTime.zone.utc_to_local(self.utc)
  end
  
  def full_date
    self.tz_convert.strftime("%m/%d/%Y %H:%M")
  end
  
  def short_date
    self.tz_convert.strftime("%m/%d %H:%M")
  end
The tz_convert method is written so it wont throw an error if the time zone isn't set. Like I said, this is an incomplete guide so you definitely want to read up on the other blogs out there:

caboose adding timezone to your rails app

Peter Marklund's Home : Rails Recipe: A Timezone Aware Datetime Picker

Comments

Leave a response

  1. linojJuly 30, 2007 @ 03:58 PM

    hi, I’m trying to use tztime with activescaffold. I know its been said “components are bad” and maybe here’s a reason why. as uses components to embed tables in a page, and its nice. But the TzTime.reset! in the around_filter resets the timezone before the view finishes rendering. If i comment out the reset, it works. What’s the harm in leaving the reset out? won’t a new zone be set the next time through anyway?

  2. Matt MNovember 25, 2007 @ 08:02 AM

    Great ideas for methods - I’m sure that’s saved people a lot of time! My co-founder just wrote a little plugin with similar methods on top of TZInfo called timezonefu … where all you declare is hastimezone in the model. It might help your readers too!

    http://hackd.wordpress.com/2007/11/23/sexy-time-zones-in-ruby-on-rails-with-timezone_fu

  3. Madhu NallamaniMay 16, 2008 @ 02:19 AM

    Hi ,

    Is there anyway I can display time in “US-Central” or “US-Eastern” format instead of “ America-New york” or “ Europe-Athens” format at the top of drop down list using Tzinfo .

    I am presently using “timezoneselect” which displays US zones on top of drop down in “ America-New york” format .

    <%= timezoneselect ('profile', 'timezone',TZInfo::Timezone.uszones, :model => TZInfo::Timezone, :default => “America/Chicago” )%>

    I can display US zones in “ (GMT - 06:00 ) CentralTime (US & Canada)” by using standard rails TimeZone ( <%= timezoneselect ('profile', 'timezone' > ) . But , I will have problem when I use “utcto_local” method .

    Thanks, Madhu Nallamani

Comment