Displaying a date time correctly for users around the world is made very easy with Ruby on Rails. The time zone can be set per request and loaded from the logged in user's configuration. All of the default time zones are already built into Ruby on Rails and provides the ability to add custom ones, for custom cities too.


First we need to allow the user to choose their desired timezone, so a migration is required:

class AddTimezoneToUser < ActiveRecord::Migration
  def change
    add_column :users, :timezone, :string

Then of course this change needs to be applied to the database.

$ rake db:migrate

Then ensure the User model has timezone under its accessible attributes

class User < ActiveRecord::Base
    attr_accessible :email, :name, :timezone, :created_at, :updated_at


Next we must provide a field to choose from. In this example I am simply adding a new form field to my users/_form.html.erb partial. Here we use the built in time_zone_select form helper.

Which will automatically give a result similar to the following screenshot. The select menu is prefilled from the Rails ActiveSupport::TimeZone class.



Lastly, an application controller before_filter is required that will set the time zone for each request.

class ApplicationController < ActionController::Base
  before_filter :set_timezone


  def set_timezone
    tz = current_user ? current_user.timezone : nil
    Time.zone = tz || ActiveSupport::TimeZone["London"]

Here current_user points to the logged in user record. This is the default behavior when using the "devise" gem. If the current user does not have a timezone, I choose to fallback to GMT (London) time. This can be changed for whatever default makes sense in your given project.