Lingceng's Blog

Rails Time Best Practice


Let’s create a demo table and do some configurations in a rails project. Then we’ll do some tests about time in rails console.

class CreateHellos < ActiveRecord::Migration
  def change
    create_table :hellos do |t|

Add following to config/application.rb

Rails.application.config.active_record.default_timezone = :local
Rails.application.config.time_zone = 'Beijing'

config.time_zone sets the default time zone for the application and enables time zone awareness for Active Record.

config.active_record.default_timezone determines whether to use (if set to :local) or (if set to :utc) when pulling dates and times from the database. The default is :utc.

Let active_record.default_timezone be :utc is a better practice.
Always save the utc to database.
It helps when you make a world-wide application.

Rails console datetime ouptut

Run following codes in rails console.

l = FinanceItem.create
#=> #<FinanceItem id: 1, created_at: "2014-11-22 03:00:32", updated_at: "2014-11-22 03:00:32" >
#=> Sat, 22 Nov 2014 11:00:32 CST +08:00

The rails console calls inspect to show return value.
The default datatime inspcet is to_s(:db).
So the created_at is “2014-11-22 03:00:32”.

But l.created_atis an instance of ActiveSupport::TimeWithZone. So it’s output is “Sat, 22 Nov 2014 11:00:32 CST +08:00” VS Datetime.parse

Let’s try following codes.

a = DateTime.parse('2014-11-22 12:35:05')
#=> Sat, 22 Nov 2014 12:35:05 +0000
#=> "Sat, 22 Nov 2014 12:35:05 +0000"
#=> "Sat, 22 Nov 2014 20:35:05 +0800"

b ='2014-11-22 12:35:05')
#=> 2014-11-22 12:35:05
#=> "Sat, 22 Nov 2014 12:35:05 +0800"

So may be better for you. VS Time.current

Let’s see the definition of Time.current

# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 29
def current ? :
end uses the system time zone because it’s is part of the Ruby standard library. will set zone with config.time_zone.

Using make troubles when your system time zone is different with config.time_zone

Best practice

Set the following config.

config.active_record.default_timezone = :utc
config.time_zone = 'YourLocalName'

Use and do NOT use DateTime.parse.
Use or Time.current and do NOT use
Thus we can keep all time class to TimeWithZone and get consistent behavior.