From 0bdb208aaf5fc97e99f4e74ea6ef0ea5f0fac6ba Mon Sep 17 00:00:00 2001 From: Scott Fleckenstein Date: Wed, 7 May 2008 06:54:07 -0700 Subject: [PATCH] Fix Time.zone.parse from stripping time zone information and make Time aware attribute methods use Time.zone.parse instead of to_time --- .../lib/active_record/attribute_methods.rb | 2 +- activerecord/test/cases/attribute_methods_test.rb | 27 ++++++++++++++++++++ .../lib/active_support/values/time_zone.rb | 3 ++ activesupport/test/time_zone_test.rb | 8 ++++++ 4 files changed, 39 insertions(+), 1 deletions(-) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 46ecfc1..973b761 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -180,7 +180,7 @@ module ActiveRecord method_body = <<-EOV def #{attr_name}=(time) if time - time = time.to_time rescue time unless time.acts_like?(:time) + time = Time.zone.parse(time) rescue time unless time.acts_like?(:time) time = time.in_time_zone if time.acts_like?(:time) end write_attribute(:#{attr_name}, time) diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 61a049a..ab9abf2 100755 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -173,6 +173,33 @@ class AttributeMethodsTest < ActiveRecord::TestCase end end + def test_setting_time_zone_aware_attribute_with_string + utc_time = Time.utc(2008, 1, 1) + (-11..13).each do |timezone_offset| + time_string = utc_time.in_time_zone(timezone_offset).to_s + in_time_zone "Pacific Time (US & Canada)" do + record = @target.new + record.written_on = time_string + assert_equal Time.zone.parse(time_string), record.written_on + assert_equal TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone + assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time + end + end + end + + def test_setting_time_zone_aware_attribute_interprets_time_zone_unaware_string_in_time_zone + time_string = 'Tue Jan 01 00:00:00 2008' + (-11..13).each do |timezone_offset| + in_time_zone timezone_offset do + record = @target.new + record.written_on = time_string + assert_equal Time.zone.parse(time_string), record.written_on + assert_equal TimeZone[timezone_offset], record.written_on.time_zone + assert_equal Time.utc(2008, 1, 1), record.written_on.time + end + end + end + def test_setting_time_zone_aware_attribute_in_current_time_zone utc_time = Time.utc(2008, 1, 1) in_time_zone "Pacific Time (US & Canada)" do diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 9cdc2a7..2342cd1 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -214,6 +214,9 @@ class TimeZone # Time.zone.parse('22:30:00') # => Fri, 31 Dec 1999 22:30:00 HST -10:00 def parse(str, now=now) time = Time.parse(str, now) rescue DateTime.parse(str) + unless time.is_a?(DateTime) || Date._parse(str)[:offset].nil? + time += time.in_time_zone(self).utc_offset - time.utc_offset + end ActiveSupport::TimeWithZone.new(nil, self, time) end diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 2f06c34..dd70186 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -173,6 +173,14 @@ class TimeZoneTest < Test::Unit::TestCase assert_equal zone, twz.time_zone end + def test_parse_string_with_timezone + (-11..13).each do |timezone_offset| + zone = TimeZone[timezone_offset] + twz = zone.parse('1999-12-31 19:00:00') + assert_equal twz, zone.parse(twz.to_s) + end + end + def test_parse_with_old_date silence_warnings do # silence warnings raised by tzinfo gem zone = TimeZone['Eastern Time (US & Canada)'] -- 1.5.4.3