diff options
6 files changed, 43 insertions, 10 deletions
diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb index b672ada7b9..2e85d14579 100644 --- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb @@ -5,6 +5,16 @@ module ActiveSupport #:nodoc: module DateTime #:nodoc: # Enables the use of time calculations within DateTime itself module Calculations + def self.included(base) #:nodoc: + base.extend ClassMethods + end + + module ClassMethods + # DateTimes aren't aware of DST rules, so use a consistent non-DST offset when creating a DateTime with an offset in the local zone + def local_offset + ::Time.local(2007).utc_offset.to_r / 86400 + end + end # Seconds since midnight: DateTime.now.seconds_since_midnight def seconds_since_midnight diff --git a/activesupport/lib/active_support/core_ext/date_time/conversions.rb b/activesupport/lib/active_support/core_ext/date_time/conversions.rb index 776f1806f9..45d09f344d 100644 --- a/activesupport/lib/active_support/core_ext/date_time/conversions.rb +++ b/activesupport/lib/active_support/core_ext/date_time/conversions.rb @@ -35,10 +35,9 @@ module ActiveSupport #:nodoc: end # Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class - # If self.offset is 0, then will attempt to cast as a utc time; otherwise will attempt to cast in local time zone + # If self has an offset other than 0, self will just be returned unaltered, since there's no clean way to map it to a Time def to_time - method = if self.offset == 0 then 'utc' else 'local' end - ::Time.send(method, year, month, day, hour, min, sec) rescue self + self.offset == 0 ? ::Time.utc_time(year, month, day, hour, min, sec) : self end # To be able to keep Times, Dates and DateTimes interchangeable on conversions diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 7f449aee49..19ac8f5a36 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -35,7 +35,7 @@ module ActiveSupport #:nodoc: def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0) ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec) rescue - offset = if utc_or_local.to_sym == :utc then 0 else ::DateTime.now.offset end + offset = utc_or_local.to_sym == :local ? ::DateTime.local_offset : 0 ::DateTime.civil(year, month, day, hour, min, sec, offset, 0) end diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index 3ef4744c44..05835a5fed 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -174,9 +174,13 @@ class DateExtCalculationsTest < Test::Unit::TestCase def test_xmlschema with_timezone 'US/Eastern' do - assert_match(/^1880-06-28T00:00:00-04:?00$/, Date.new(1880, 6, 28).xmlschema) + assert_match(/^1980-02-28T00:00:00-05:?00$/, Date.new(1980, 2, 28).xmlschema) assert_match(/^1980-06-28T00:00:00-04:?00$/, Date.new(1980, 6, 28).xmlschema) - assert_match(/^2080-06-28T00:00:00-04:?00$/, Date.new(2080, 6, 28).xmlschema) + # these tests are only of interest on platforms where older dates #to_time fail over to DateTime + if ::DateTime === Date.new(1880, 6, 28).to_time + assert_match(/^1880-02-28T00:00:00-05:?00$/, Date.new(1880, 2, 28).xmlschema) + assert_match(/^1880-06-28T00:00:00-05:?00$/, Date.new(1880, 6, 28).xmlschema) # DateTimes aren't aware of DST rules + end end end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index f4d5427d0f..0f2c788926 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -35,8 +35,9 @@ class DateTimeExtCalculationsTest < Test::Unit::TestCase # FIXME: ruby 1.9 compat def test_to_time assert_equal Time.utc(2005, 2, 21, 10, 11, 12), DateTime.new(2005, 2, 21, 10, 11, 12, 0, 0).to_time - assert_equal Time.local(2005, 2, 21, 10, 11, 12), DateTime.new(2005, 2, 21, 10, 11, 12, Rational(-5, 24), 0).to_time assert_equal Time.utc_time(2039, 2, 21, 10, 11, 12), DateTime.new(2039, 2, 21, 10, 11, 12, 0, 0).to_time + # DateTimes with offsets other than 0 are returned unaltered + assert_equal DateTime.new(2005, 2, 21, 10, 11, 12, Rational(-5, 24)), DateTime.new(2005, 2, 21, 10, 11, 12, Rational(-5, 24)).to_time end def test_seconds_since_midnight @@ -211,4 +212,21 @@ class DateTimeExtCalculationsTest < Test::Unit::TestCase def test_acts_like_time assert DateTime.new.acts_like_time? end + + def test_local_offset + with_timezone 'US/Eastern' do + assert_equal Rational(-5, 24), DateTime.local_offset + end + with_timezone 'US/Central' do + assert_equal Rational(-6, 24), DateTime.local_offset + end + end + + protected + def with_timezone(new_tz = 'US/Eastern') + old_tz, ENV['TZ'] = ENV['TZ'], new_tz + yield + ensure + old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ') + end end diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 9965e2574a..8ead0d7fe6 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -312,7 +312,9 @@ class TimeExtCalculationsTest < Test::Unit::TestCase assert_equal "17:44", time.to_s(:time) assert_equal "February 21, 2005 17:44", time.to_s(:long) assert_equal "February 21st, 2005 17:44", time.to_s(:long_ordinal) - assert_equal "Mon, 21 Feb 2005 17:44:30 +0000", time.to_s(:rfc822) + with_timezone "UTC" do + assert_equal "Mon, 21 Feb 2005 17:44:30 +0000", time.to_s(:rfc822) + end end def test_custom_date_format @@ -387,8 +389,8 @@ class TimeExtCalculationsTest < Test::Unit::TestCase def test_local_time assert_equal Time.local_time(2005, 2, 21, 17, 44, 30), Time.local(2005, 2, 21, 17, 44, 30) - assert_equal Time.local_time(2039, 2, 21, 17, 44, 30), DateTime.civil(2039, 2, 21, 17, 44, 30, DateTime.now.offset, 0) - assert_equal Time.local_time(1901, 2, 21, 17, 44, 30), DateTime.civil(1901, 2, 21, 17, 44, 30, DateTime.now.offset, 0) + assert_equal Time.local_time(2039, 2, 21, 17, 44, 30), DateTime.civil(2039, 2, 21, 17, 44, 30, DateTime.local_offset, 0) + assert_equal Time.local_time(1901, 2, 21, 17, 44, 30), DateTime.civil(1901, 2, 21, 17, 44, 30, DateTime.local_offset, 0) end def test_next_month_on_31st |