diff options
author | Andrew White <andyw@pixeltrix.co.uk> | 2013-07-09 14:04:49 +0100 |
---|---|---|
committer | Andrew White <andyw@pixeltrix.co.uk> | 2013-07-09 14:04:49 +0100 |
commit | ccad803bf44fe30602a041ff0ab1cbe985bc3840 (patch) | |
tree | 22636c9a0829b7c7f5ec5c65fd7e5ebfe67c8d7b /activesupport | |
parent | d704c1cb9850bd563b7ad99762e75b9b3cb7aebf (diff) | |
download | rails-ccad803bf44fe30602a041ff0ab1cbe985bc3840.tar.gz rails-ccad803bf44fe30602a041ff0ab1cbe985bc3840.tar.bz2 rails-ccad803bf44fe30602a041ff0ab1cbe985bc3840.zip |
Retain offset and fraction when using Time.at_with_coercion
The standard Ruby behavior for Time.at is to return the same type of
time when passing an instance of Time as a single argument. Since the
an ActiveSupport::TimeWithZone instance may be a different timezone than
the system timezone and DateTime just understands offsets the best we
can do is to return an instance of Time with the correct offset.
It also maintains the correct fractional second value as well.
Fixes #11350.
Backports:
484253515c0e05760541dc48946361185c9e6904
1b3873730b96035a238dbff7627bd5942e6dc4e7
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/CHANGELOG.md | 6 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/time/calculations.rb | 11 | ||||
-rw-r--r-- | activesupport/test/core_ext/time_ext_test.rb | 37 |
3 files changed, 51 insertions, 3 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 79bccf6d7e..21a726bfc1 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,11 @@ ## unreleased ## +* Make `Time.at_with_coercion` retain the second fraction and offset from UTC. + + Fixes #11350 + + *Neer Friedman*, *Andrew White* + * Fix `ActiveSupport::TaggedLogging` incorrectly providing program name the same as log message even when block is not provided. diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 7524063efb..9663edb0ad 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -49,10 +49,15 @@ class Time # Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime # instances can be used when called with a single argument def at_with_coercion(*args) - if args.size == 1 && args.first.acts_like?(:time) - at_without_coercion(args.first.to_i) + return at_without_coercion(*args) if args.size != 1 + + # Time.at can be called with a time or numerical value + time_or_number = args.first + + if time_or_number.is_a?(ActiveSupport::TimeWithZone) || time_or_number.is_a?(DateTime) + at_without_coercion(time_or_number.to_f).getlocal(time_or_number.utc_offset) else - at_without_coercion(*args) + at_without_coercion(time_or_number) end end alias_method :at_without_coercion, :at diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index a22e161279..57ead2edc5 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -785,6 +785,12 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end end + def test_at_with_datetime_maintains_offset + with_env_tz 'US/Eastern' do + assert_equal 3600, Time.at(DateTime.civil(2000, 1, 1, 0, 0, 0, '+1')).utc_offset + end + end + def test_at_with_time_with_zone assert_equal Time.utc(2000, 1, 1, 0, 0, 0), Time.at(ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone['UTC'])) @@ -796,6 +802,37 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end end + def test_at_with_time_with_zone_maintains_offset + with_env_tz 'US/Eastern' do + assert_equal 0, Time.at(ActiveSupport::TimeWithZone.new(Time.utc(2000, 1, 1, 0, 0, 0), ActiveSupport::TimeZone['London'])).utc_offset + assert_equal 3600, Time.at(ActiveSupport::TimeWithZone.new(Time.utc(2000, 7, 1, 0, 0, 0), ActiveSupport::TimeZone['London'])).utc_offset + end + end + + def test_at_with_time_microsecond_precision + assert_equal Time.at(Time.utc(2000, 1, 1, 0, 0, 0, 111)).to_f, Time.utc(2000, 1, 1, 0, 0, 0, 111).to_f + end + + def test_at_with_utc_time + with_env_tz 'US/Eastern' do + assert_equal Time.utc(2000), Time.at(Time.utc(2000)) + assert_equal 0, Time.at(Time.utc(2000)).utc_offset + assert_equal 'UTC', Time.at(Time.utc(2000)).zone + end + end + + def test_at_with_local_time + with_env_tz 'US/Eastern' do + assert_equal Time.local(2000), Time.at(Time.local(2000)) + assert_equal -18000, Time.at(Time.local(2000)).utc_offset + assert_equal 'EST', Time.at(Time.local(2000)).zone + + assert_equal Time.local(2000, 7, 1), Time.at(Time.local(2000, 7, 1)) + assert_equal -14400, Time.at(Time.local(2000, 7, 1)).utc_offset + assert_equal 'EDT', Time.at(Time.local(2000, 7, 1)).zone + end + end + def test_eql? assert_equal true, Time.utc(2000).eql?( ActiveSupport::TimeWithZone.new(Time.utc(2000), ActiveSupport::TimeZone['UTC']) ) assert_equal true, Time.utc(2000).eql?( ActiveSupport::TimeWithZone.new(Time.utc(2000), ActiveSupport::TimeZone["Hawaii"]) ) |