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:
- 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.
- 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.