What have you found for these years?

2010-11-28

rails 2 didn't respect timezone doing db query

So suppose we're storing UTC time in database,
while Time.now returns a local time (i.e. with local timezone).
This would be wrong:

User.first(:conditions => ['created_at < ?', Time.now])

Timezone information would be dropped when the query is
converted to SQL. Instead we shall call Time#utc before
passing it to ActiveRecord:

User.first(:conditions => ['created_at < ?', Time.now.utc])

But actually ActiveRecord is respecting ActiveSupport::TimeWithZone,
that is, if we're passing an instance of it, timezone information won't
be dropped:

User.first(:conditions => ['created_at < ?', Time.now.in_time_zone(8)])

The effect is exactly the same as the one calling Time.now.utc.
I don't think this is a good design. It's more like a bug IMO.

As pointed out at:
Rails Timezone Gotcha: ActiveRecord::Base.find does not convert Time objects to UTC
It's marked as "invalid" in Rails' issue tracker. I totally have no idea why.
ActiveRecord timezone issues

Here's a monkey patch modified from Peter Marklund.

# http://marklunds.com/articles/one/402
module ActiveRecord
  module ConnectionAdapters # :nodoc:
    module Quoting
      # Convert dates and times to UTC so that the following two will be equivalent:
      # Event.all(:conditions => ["start_time > ?", Time.zone.now])
      # Event.all(:conditions => ["start_time > ?", Time.now])
      def quoted_date(value)
        value.respond_to?(:utc) ? value.dup.utc.to_s(:db) : value.to_s(:db)
      end
    end
  end
end
I have no idea if Rails 3 fixed this.

0 retries:

Post a Comment

All texts are licensed under CC Attribution 3.0