Be a Zeek

Rails tricky timezones

Configuring timezones in rails can be tricky if one doesn’t understand the actual config settings and their use.

Ruby’s Time can also get really confusing when used in Rails app.

Consider Time.now and Time.zone.now

Time is a ruby library hence Time.now will return system’s time. To change that for your Rails app use time_zone config.

Say, I have a server in UTC and all my users are in IST then my rails app time_zone should be like,

#config/application.rb
config.time_zone = ‘IST’

In Rails console,
Time.now #returns time in UTC
=> 2015-07-12 11:26:05 +0000

Time.zone.now #returns time in IST
=> Sun, 12 Jul 2015 16:56:46 IST +05:30

In fact, in rails use Time.current which is a mix of both. Read code here.

ActiveRecord and DB timezones
(Considering MySQL here)

By default, our DB picks system’s timezone (here UTC) and our application here is using IST. Hence when we save a time using Rails app in IST, it actually is saved in UTC in our DB.

So ideally, if we have a time saved in DB as 2015-07-12 11:26:05 +0000 then we should retrieve this in our rails app (in IST) as datetime object Sun, 12 Jul 2015 16:56:05 IST +05:30.

Tricky active_record.default_timezone

There is another setting in Rails, config.active_record.default_timezone, with default value as :local (picks system’s timezone). This config is responsible to identify timezone for our ActiveRecord datetime objects.

So lets say, our DB is on another server with system timezone as UTC and our application is now on a server with system and application timezone as IST, which now means Time.now and Time.zone.now are same.

In this case, config.active_record.default_timezone has value as IST (:local) which will tell our system that the datetime values we are getting from DB are in IST timezone. Hence it will just convert the timezone of the value and not the datetime value itself resulting in wrong results,

  • Actual datetime value in DB, 2015-07-12 11:26:05 +0000 (which is considered in IST timezone by our app due to active_record.default_timezone)
  • Retrieved datetime value in app, Sun, 12 Jul 2015 11:26:05 IST +05:30

To handle these situation we just have to set,

#config/application.rb
config.active_record.default_timezone = :utc

And now the expectation of ActiveRecord datetime object’s timezone from our app will be of UTC which is actually same as DB’s timezone.

Advertisements

Comments on: "Rails tricky timezones" (1)

  1. Sneaky little timezoneses, wicked, tricksy, false! 😉

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: