Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Accessing datetime via read_attribute loses timezone

#1637

In my project I needed to alter getter method for datetime attribute, like that:


class SomeModel < ActiveRecord::Base
  has_one :overriding_model
  def start_time
    if overriding_model
      overriding_model.start_time
    else
      read_attribute(:start_time)
    end
  end
end

With such definition start_time method began to return instances of Time class (with time in UTC timezone), so that broke displaying of times for us.

Here's diff to test case that will fail test_time_attributes_are_retrieved_in_current_time_zone


diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index 77ee8d8..cc5198f 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -146,7 +146,9 @@ class AttributeMethodsTest < ActiveRecord::TestCase
       record[:written_on] = utc_time
       assert_equal utc_time, record.written_on # record.written on is equal to (i.e., simultaneous with) utc_time
       assert_kind_of ActiveSupport::TimeWithZone, record.written_on # but is a TimeWithZone
+      assert_kind_of ActiveSupport::TimeWithZone, record.read_attribute(:written_on)
       assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone # and is in the current Time.zone
+      assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.read_attribute(:written_on).time_zone
       assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time # and represents time values adjusted accordingly
     end
   end

Reported by Artem Ignatiev · December 26th, 2008 @ 02:43 PM

State: wontfix
Milestone: 2.x
Assigned to: nobody
Importance: none

Activity

  1. Mark Turner
    Mark Turner

    What version of Rails are you using?

    December 26th, 2008 @ 09:02 PM

  2. Frederick Cheung
    Frederick Cheung

    Well currently the conversion happens at the level of the automatically generated attribute reader so it's not surprising that this happens.

    All you need to do is change your code to say

    
      read_attribute(:start_time).in_time_zone
    

    Furthermore I'm of the opinion that time zone conversions etc... are none of read_attribute's business. It's a low level method, so if you use it there will be slighly more faffing around

    December 26th, 2008 @ 10:26 PM

  3. Artem Ignatiev
    Artem Ignatiev

    What version of Rails are you using? Using 2.2, patch is against 07298fd0929ae1c6dd6d1b41bf320112d6bfc6a0 (Fri Dec 26 01:49:14 2008 +0000)

    2Frederick:

    Well, after reading the source I came to conclusion that it's intended behaviour when reading datetime attributes.

    Perhaps, a note should be added to rdoc about timezone conversion when reading/writing datetime attributes?

    December 29th, 2008 @ 12:07 PM

  4. Geoff Buesing
    Geoff Buesing
    • State changed from new to wontfix

    In agreement with Frederick -- time zone conversions shouldn't be done inside of read_attribute.

    @Artem, agreed, an rdoc note could help by explaining that time zone conversions are done via generated methods, and not inside of read_attribute.

    January 7th, 2009 @ 06:29 AM