Rails Basics - Handling user timezones in Rails

These “Rails Basics” blog posts are simple how-to’s for Rails 3. These are aimed at beginners to Rails, but prior programming knowledge will be helpful. This post will assist you in handling user specific timezones in your rails applications.

I would strongly recommend you consider and implement your handling for timezones early on in development (at least before you have any real data stored in your application). By default rails will assume your users are in the UTC timezone, so any dates that are stored before you start handling timezones properly will be out by your timezones offset (ie. all my dates were off by 10 or 11 hours, as I am in Melbourne - Australia).

There are two common ways to know what the timezone is for your user:

  1. Detect the users timezone from their browser/system. This is the best choice if you have anonymous users (ie. they do not require a user account to your application). If choosing this option keep in mind that not all users will set their timezones correctly in their browsers, making this a somewhat unreliable choice.
  2. Ask the user to set/choose their timezone. This post will be focused on this method.

Allow your application to store the users timezone

You will need to add a time_zone field to your users table, your migration will look like this:

class AddTimezoneColumnToUsers < ActiveRecord::Migration
  def self.up
    add_column :users, :time_zone, :string
  end

  def self.down
    remove_column :users, :time_zone
  end
end

Change your add/edit form for user accounts to capture the timezone

You will need to add a drop down list for selecting timezones, the code will look like:

<%= f.label :time_zone %>
<%= f.time_zone_select :time_zone, /Australia/, :default => "Melbourne" %>

Note: In my example code above, I included the /Australia/ option, this will have the drop down list display Australian timezones as priority in the top of the list. A common variant for US is TimeZone.us_zones.

I have also included a default value in my list, this is optional.

Change the time zone of the application to that of the logged in user

You will now need to change your applications time zone to that of your logged in user. In my example, user authentication is handled by the Devise plugin, however it has minimal impact on the code.

The following code is added to the application controller of your application:

before_filter: set_user_time_zone

def set_user_time_zone
  Time.zone = current_user.time_zone if user_signed_in?
end

Additional information

To set the default time zone for your application (in the above example, this would be used when no user is logged in), put the following code into your application.rb:

config.time_zone = 'Melbourne'

Acknowledgements

Much of this information was gathered from the following post by Geoff Buesing. I would recommend checking it out for more information on timezones in rails.

Time Zone Support - An Overview

By Joel Friedlaender