Super Spread Sheet S³

Or little computing tricks and hacks

Sorting out time zones in Rails

NOTE: Post edited 9 March, 2015.
Original post had incomplete information. The solution given was not enough.

Nothing more annoying that an app which cannot sort out or at least tell you in what time zone the date displayed is given in.

Standard for Rails apps are the fields created_at and updated_at. By default Rails uses UTC to store this, but when this command is issued

Time.now

the time is adjusted to show local time. This creates an odd situation when you use Time.now to set in the database a time field through an input form. The time is stored without transformation in UTC.

Furthermore, ruby only supports UTC. By typing

article.created_at.class

I discovered that these are in fact of Class

ActiveSupport::TimeWithZone

which is (taken from ActiveSupport TimeWithZone) a

Time-like class that can represent a time in any time zone.

To sort out any discrepancies or errors with respect to you application, the time zone should be set. To find the available zones type

rake -D time

for the commands available and

rake time:zones:all

to get a listing of all the time zones recognized. Or try

rake time:zones:local

There seems to be different places to set the time zone:

  • config/environment.rb was mentioned in this post.
  • config/application.rb is where the commented portion with the explanations, was.

I used the latter, with the following line:

    config.time_zone = 'Eastern Time (US & Canada)'

This magic line

… sets Time.zone default to the specified zone and makes Active Record auto-convert to this zone.

is misleading, since I discovered that in the database dates are indeed and still stored in UTC, after all the changes.

To fix this, once the current date is captured, it is converted into UTC before storing in the database.

A snippet of the new.html.rb:

      my_date_time = Time.now

      select_datetime(my_date_time,
        datetime_separator: " at ",
        prompt: {day: 'Day', month: 'Month', year: 'Year',
                 hour: 'Hour', minute: 'Minutes'})

      my_date_time.zone

and in the controller.rb:

def create
    time_in_localzone = Time.new(
      params[:date]['year'].to_i,
      params[:date]['month'].to_i,
      params[:date]['day'].to_i,
      params[:date]['hour'].to_i,
      params[:date]['minute'].to_i,
    )
    @article.published_on = time_in_localzone.utc

    if @article.save
      redirect_to articles_path
    else
      render 'new'
    end
end

Useful links:

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: