Close and Go BackBack to Viget

Protip: TimeWithZone, All The Time

David Eisinger
David Eisinger, Senior Developer, September 10, 2008

If you’ve ever tried to retrieve a list of ActiveRecord objects based on their timestamps, you’ve probably been bitten by the quirky time support in Rails:

>> Goal.create(:description => "Run a mile")
=> #<Goal id: 1, description: "Run a mile",
     created_at: "2008-09-09 19:32:57",
     updated_at: "2008-09-09 19:32:57">
>> Goal.find(:all, :conditions => ['created_at < ?',
     Time.now])
=> []

Huh? Checking the logs, we see that the two commands above correspond to the following queries:

INSERT INTO "goals" ("updated_at", "description",
  "created_at") VALUES('2008-09-09 19:32:57',
  'Run a mile', '2008-09-09 19:32:57')
SELECT * FROM "goals" WHERE created_at < '2008-09-09 15:33:17'

Rails stores created_at relative to Coordinated Universal Time, while Time.now is based on the system clock, running four hours behind. The solution? ActiveSupport’s TimeWithZone:

>> Goal.find(:all, :conditions => ['created_at < ?',
     Time.zone.now])
=> [#<Goal id: 1, description: "Run a mile",
     created_at: "2008-09-09 19:32:57",
     updated_at: "2008-09-09 19:32:57">]

Rule of thumb: always use TimeWithZone in your Rails projects. Date, Time and DateTime simply don’t play well with ActiveRecord. Instantiate it with Time.zone.now and Time.zone.local. To discard the time element, use beginning_of_day.

BONUS TIP

Since it’s a subclass of Time, interpolating a range of TimeWithZone objects fills in every second between the two times — not so useful if you need a date for every day in a month:

>> t = Time.zone.now
=> Tue, 09 Sep 2008 14:26:45 EDT -04:00
>> (t..(t + 1.month)).to_a.size
[9 minutes later]
=> 2592001

Fortunately, the desired behavior is just a monkeypatch away:

class ActiveSupport::TimeWithZone
  def succ
    self + 1.day
  end
end

>> (t..(t + 1.month)).to_a.size
=> 31

For more information about time zones in Rails, Geoff Buesing and Ryan Daigle have good, up-to-date posts.

blog comments powered by Disqus

We're the Developers

at Viget Labs. We write about web development trends, tips, best practices, industry events, and our projects — all with an emphasis on Ruby on Rails.

Contact Us

Have any questions, comments, ideas, or secrets to share? Let us know.


What color is the sky?

Sorry, you need to have Javascript enabled to use this form. (Don't blame us, blame the spammers!) If you'd like to contact us, please visit our Contact page.