diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index f39b58a980..b916b560a7 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -338,7 +338,7 @@ module ActiveSupport # so transfer time values to a utc constructor if necessary @time = transfer_time_values_to_utc_constructor(@time) unless @time.utc? begin - @time_zone.period_for_local(@time) + @time_zone.period_for_local(@time) { |periods| periods.first } rescue ::TZInfo::PeriodNotFound # time is in the "spring forward" hour gap, so we're moving the time forward one hour and trying again @time += 1.hour diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index f935180036..05285083b4 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -309,8 +309,8 @@ module ActiveSupport end # Adjust the given time to the simultaneous time in UTC. Returns a Time.utc() instance. - def local_to_utc(time, dst=true) - tzinfo.local_to_utc(time, dst) + def local_to_utc(time, dst=true, &block) + tzinfo.local_to_utc(time, dst, &block) end # Available so that TimeZone instances respond like TZInfo::Timezone instances @@ -319,8 +319,8 @@ module ActiveSupport end # Available so that TimeZone instances respond like TZInfo::Timezone instances - def period_for_local(time, dst=true) - tzinfo.period_for_local(time, dst) + def period_for_local(time, dst=true, &block) + tzinfo.period_for_local(time, dst, &block) end def self.find_tzinfo(name) diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index bd4bfca82c..0d8ecf7966 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -136,6 +136,17 @@ class TimeZoneTest < Test::Unit::TestCase assert_equal 'EDT', twz.zone end + def test_local_handles_non_dst_clock_set_back + # If the clocks are set back during a transition from one non-DST observance + # to another, the time of the transition will be ambiguous. The earlier + # observance will be selected to mirror behaviour of DST to non-DST transitions. + # Such a transition occurred at 02:00 local time in Moscow on 26 October 2014. + zone = ActiveSupport::TimeZone['Moscow'] + twz = zone.local(2014,10,26,1) + assert_equal Time.utc(2014,10,26,1), twz.time + assert_equal Time.utc(2014,10,25,21), twz.utc + end + def test_at zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] secs = 946684800.0