Correct Use of Rails Time Zone

Dealing with time zone with Rails was complicated before. It involves in database, Rails ActiveRecord & ActionView and Javascript. But it is now clear to me that Rails provides a simple way to handle it. The rules are:

  1. Store time in UTC in database and ActiveRecord
  2. Convert time to user-defined time zone in ActionView
  3. Convert user-input time into UTC before keeping in ActiveRecord and database

Just remember, whenever you store time, always keep it in UTC. It makes searching and comparing much easier. Dealing with display and input time with user time zone at ActionView and Javascript level.

To be sure your database is in UTC time zone, you can do this:

# rake console
> Rails.application.config.time_zone
=> "UTC"
=> "UTC"

On the ActiveView and Javascript side, you must have a time zone to determine how to display time. You can have a time_zone field defined in user model or in event model. Or you can simply supply the time in UTC and let client-side Javascript to convert the time to user locale.

In Rails, to convert time in UTC to user time zone, you can do this:


For example:

# rails console
> event.time
=> Wed, 01 Mar 2017 09:00:00 UTC +00:00 # time is stored in UTC
> event.time.in_time_zone(event.time_zone)
=> Wed, 01 Mar 2017 17:00:00 CST +08:00 # the same time in other time zone

If you want to display time in time zone of browser, you can do it in Javascript as described in this article. It first maps Rails time zone to Javascript one, then use moment.js to do the conversion.

For input, if you use datetime_select or any other method, just specify the time zone before saving your model like this:

def update = event_params[:time_zone]
respond_to do |format|
if @event.update(event_params)
format.html { redirect_to @event }

or Time.use_zone.

In this way, time is converted into UTC before saving.

Do not calculate the time zone offset by yourself because it cannot handle day-time saving correctly. Always let Rails or Javascript do the conversion for you.