How Soon is Now?

Rails 2.1 added the ability to set a default time zone in your environment file, like this:

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

This defaults Time.zone to the zone specified, and also sets all date and time values written in your database to UTC (Coordinated Universal Time). Getters and setters for your ActiveRecord models adjust automatically, but there's a gotcha.

In script/console:

>> Time.now

=> Sun Mar 29 12:38:47 -0500 2009

>> c = Client.create(:name => "Date Test")

=> #<Client id: 6, address: nil, address_2: nil, , city: nil, country: nil, phone: nil, name: "Date Test", state: nil, url: nil, zip: nil, active: true, created_at: "2009-03-29 17:35:54", updated_at: "2009-03-29 17:35:54">

Notice that local time is 12:38, but the created_at in the database record is 5 hours in the future (UTC - Central Time = 5 hours). However, using an accessor, we get:

>> c.created_at

=> Sun, 29 Mar 2009 12:35:54 CDT -05:00

This is a Good Thing; the ActiveRecord getters and setters are respecting our time zone setting.

But here's the gotcha: if you manually create find conditions to locate records by a time or date, you can't just use Time.now as you might have in the past. For example:

>> Client.find(:last, :conditions => ['created_at < ?', Time.now - 5.minutes])

=> #<Client id: 4, address: "Rt 10 Green Hills", address_2: "P.O. Box 563", city: "Reading", country: "US", phone: "610-777-7777", name: "Some Other Client", state: "Pennsylvania", url: "http://www.foo.com", zip: "19603", active: true, created_at: "2008-10-28 15:00:19", updated_at: "2008-10-28 15:58:04">

This is not the record that we were expecting-- this one is months old!

To fix the find condition, you have to change Time.now to Time.zone.now:

>> Client.find(:last, :conditions => ['created_at < ?', Time.zone.now - 5.minutes])

=> #<Client id: 6, primary_agent_id: nil, primary_contact_id: nil, address: nil, address_2: nil, camp_directory_url: nil, city: nil, country: nil, local_site_meta_description: nil, local_site_meta_keywords: nil, phone: nil, name: "Date Test", state: nil, url: nil, zip: nil, active: true, created_at: "2009-03-29 17:35:54", updated_at: "2009-03-29 17:35:54">

This caused some amount of chaos for me last week, as one member of the team added time zone configuration and suddenly scheduled background tasks weren't running on schedule anymore. I strongly recommend searching your code base for Time.now and DateTime.now and modifying them accordingly; remember, anything that's using accessors is fine as is, but other calls may cause unexpected results.

Comments

Brad Gessler
April 12, 2009 at 7:09 PM

This is good to know; we have some funky time zone problems in our admin panel that this will fix.

Damian Nicholson
May 18, 2009 at 10:29 AM

This caused quite a bit of bother for me too, thanks for pointing out your solution to this :D

Jason
April 30, 2010 at 4:52 PM

Just wanted to let you know that I love the design of your site... was looking for a solution, figured it out on my own, but still had your site open, so I glanced at it... You have good taste in design.
Leave a Comment


IdolHands.com Spam-o-MeterTM
Bot
Spammer
Moron
Human






* Required fields.