From c911e1ac08d119e94fcec6973a012f4cd198ecee Mon Sep 17 00:00:00 2001 From: Geoff Buesing Date: Fri, 25 Jan 2008 15:52:23 +0000 Subject: Time.zone uses thread-local variable for thread safety. Adding Time.use_zone, for overriding Time.zone locally inside a block. Removing unneeded Time.zone_reset! git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8718 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- activesupport/CHANGELOG | 2 + .../lib/active_support/core_ext/time/zones.rb | 20 ++++--- activesupport/test/core_ext/time_with_zone_test.rb | 62 +++++++++++++--------- 3 files changed, 53 insertions(+), 31 deletions(-) (limited to 'activesupport') diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 833c3dd07a..ed9f8a8e00 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Time.zone uses thread-local variable for thread safety. Adding Time.use_zone, for overriding Time.zone locally inside a block. Removing unneeded Time.zone_reset! [Geoff Buesing] + * TimeZone#to_s uses UTC rather than GMT; reapplying change that was undone in [8679]. #1689 [Cheah Chu Yeow] * Time.days_in_month defaults to current year if no year is supplied as argument #10799 [Radar], uses Date.gregorian_leap? to determine leap year, and uses constant lookup to determine days in month [Geoff Buesing] diff --git a/activesupport/lib/active_support/core_ext/time/zones.rb b/activesupport/lib/active_support/core_ext/time/zones.rb index 390d4128a1..a600e4099d 100644 --- a/activesupport/lib/active_support/core_ext/time/zones.rb +++ b/activesupport/lib/active_support/core_ext/time/zones.rb @@ -9,7 +9,9 @@ module ActiveSupport #:nodoc: end module ClassMethods - attr_reader :zone + def zone + Thread.current[:time_zone] + end # Sets a global default time zone, separate from the system time zone in ENV['TZ']. # Accepts either a Rails TimeZone object, a string that identifies a @@ -20,16 +22,20 @@ module ActiveSupport #:nodoc: # # Time.zone = 'Hawaii' # => 'Hawaii' # Time.utc(2000).in_current_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00 - def zone=(zone) - @zone = get_zone(zone) + def zone=(time_zone) + Thread.current[:time_zone] = get_zone(time_zone) end - def zone_reset! - @zone = nil + # Allows override of Time.zone locally inside supplied block; resets Time.zone to existing value when done + def use_zone(time_zone) + old_zone, ::Time.zone = ::Time.zone, ::Time.get_zone(time_zone) + yield + ensure + ::Time.zone = old_zone end - def get_zone(zone) - ::String === zone || ::Numeric === zone ? TimeZone[zone] : zone + def get_zone(time_zone) + ::String === time_zone || ::Numeric === time_zone ? TimeZone[time_zone] : time_zone end end diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index 982384fac8..c88eef7b21 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -27,7 +27,7 @@ uses_tzinfo 'TimeWithZoneTest' do end def test_in_current_time_zone - with_time_zone 'Alaska' do + Time.use_zone 'Alaska' do assert_equal ActiveSupport::TimeWithZone.new(@utc, TimeZone['Alaska']), @twz.in_current_time_zone end end @@ -39,7 +39,7 @@ uses_tzinfo 'TimeWithZoneTest' do end def test_change_time_zone_to_current - with_time_zone 'Alaska' do + Time.use_zone 'Alaska' do assert_equal ActiveSupport::TimeWithZone.new(nil, TimeZone['Alaska'], Time.utc(1999, 12, 31, 19)), @twz.change_time_zone_to_current end end @@ -146,24 +146,20 @@ uses_tzinfo 'TimeWithZoneTest' do assert_equal 12, @twz.month assert_equal 31, @twz.day end - - protected - def with_time_zone(zone) - old_zone, Time.zone = Time.zone, Time.get_zone(zone) - yield - ensure - Time.zone = old_zone - end end class TimeWithZoneMethodsForTimeAndDateTimeTest < Test::Unit::TestCase def setup @t, @dt = Time.utc(2000), DateTime.civil(2000) end + + def teardown + Time.zone = nil + end def test_in_time_zone silence_warnings do # silence warnings raised by tzinfo gem - with_time_zone 'Eastern Time (US & Canada)' do + Time.use_zone 'Eastern Time (US & Canada)' do assert_equal 'Fri, 31 Dec 1999 15:00:00 AKST -09:00', @t.in_time_zone('Alaska').inspect assert_equal 'Fri, 31 Dec 1999 15:00:00 AKST -09:00', @dt.in_time_zone('Alaska').inspect assert_equal 'Fri, 31 Dec 1999 14:00:00 HST -10:00', @t.in_time_zone('Hawaii').inspect @@ -173,15 +169,15 @@ uses_tzinfo 'TimeWithZoneTest' do end def test_in_current_time_zone - with_time_zone 'Alaska' do + Time.use_zone 'Alaska' do assert_equal 'Fri, 31 Dec 1999 15:00:00 AKST -09:00', @t.in_current_time_zone.inspect assert_equal 'Fri, 31 Dec 1999 15:00:00 AKST -09:00', @dt.in_current_time_zone.inspect end - with_time_zone 'Hawaii' do + Time.use_zone 'Hawaii' do assert_equal 'Fri, 31 Dec 1999 14:00:00 HST -10:00', @t.in_current_time_zone.inspect assert_equal 'Fri, 31 Dec 1999 14:00:00 HST -10:00', @dt.in_current_time_zone.inspect end - with_time_zone nil do + Time.use_zone nil do assert_equal @t, @t.in_current_time_zone assert_equal @dt, @dt.in_current_time_zone end @@ -189,7 +185,7 @@ uses_tzinfo 'TimeWithZoneTest' do def test_change_time_zone silence_warnings do # silence warnings raised by tzinfo gem - with_time_zone 'Eastern Time (US & Canada)' do + Time.use_zone 'Eastern Time (US & Canada)' do assert_equal 'Sat, 01 Jan 2000 00:00:00 AKST -09:00', @t.change_time_zone('Alaska').inspect assert_equal 'Sat, 01 Jan 2000 00:00:00 AKST -09:00', @dt.change_time_zone('Alaska').inspect assert_equal 'Sat, 01 Jan 2000 00:00:00 HST -10:00', @t.change_time_zone('Hawaii').inspect @@ -199,26 +195,44 @@ uses_tzinfo 'TimeWithZoneTest' do end def test_change_time_zone_to_current - with_time_zone 'Alaska' do + Time.use_zone 'Alaska' do assert_equal 'Sat, 01 Jan 2000 00:00:00 AKST -09:00', @t.change_time_zone_to_current.inspect assert_equal 'Sat, 01 Jan 2000 00:00:00 AKST -09:00', @dt.change_time_zone_to_current.inspect end - with_time_zone 'Hawaii' do + Time.use_zone 'Hawaii' do assert_equal 'Sat, 01 Jan 2000 00:00:00 HST -10:00', @t.change_time_zone_to_current.inspect assert_equal 'Sat, 01 Jan 2000 00:00:00 HST -10:00', @dt.change_time_zone_to_current.inspect end - with_time_zone nil do + Time.use_zone nil do assert_equal @t, @t.change_time_zone_to_current assert_equal @dt, @dt.change_time_zone_to_current end end - protected - def with_time_zone(zone) - old_zone, Time.zone = Time.zone, Time.get_zone(zone) - yield - ensure - Time.zone = old_zone + def test_use_zone + Time.zone = 'Alaska' + Time.use_zone 'Hawaii' do + assert_equal TimeZone['Hawaii'], Time.zone end + assert_equal TimeZone['Alaska'], Time.zone + end + + def test_use_zone_with_exception_raised + Time.zone = 'Alaska' + assert_raises RuntimeError do + Time.use_zone('Hawaii') { raise RuntimeError } + end + assert_equal TimeZone['Alaska'], Time.zone + end + + def test_time_zone_setter_is_thread_safe + Time.use_zone 'Paris' do + t1 = Thread.new { Time.zone = 'Alaska' } + t2 = Thread.new { Time.zone = 'Hawaii' } + assert_equal TimeZone['Paris'], Time.zone + assert_equal TimeZone['Alaska'], t1[:time_zone] + assert_equal TimeZone['Hawaii'], t2[:time_zone] + end + end end end -- cgit v1.2.3