mirror of
https://github.com/github/rails.git
synced 2026-01-30 00:38:00 -05:00
TimeZone #local and #now correctly enforce DST rules
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@9007 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
*SVN*
|
||||
|
||||
* TimeZone #local and #now correctly enforce DST rules [Geoff Buesing]
|
||||
|
||||
* TimeWithZone instances correctly enforce DST rules. Adding TimeZone#period_for_utc [Geoff Buesing]
|
||||
|
||||
* test_time_with_datetime_fallback expects DateTime.local_offset instead of DateTime.now.offset [Geoff Buesing]
|
||||
|
||||
@@ -174,25 +174,32 @@ class TimeZone
|
||||
def to_s
|
||||
"(UTC#{formatted_offset}) #{name}"
|
||||
end
|
||||
|
||||
# Method for creating new ActiveSupport::TimeWithZone instance in time zone of self. Example:
|
||||
#
|
||||
# Time.zone = "Hawaii" # => "Hawaii"
|
||||
# Time.zone.local(2007, 2, 1, 15, 30, 45) # => Thu, 01 Feb 2007 15:30:45 HST -10:00
|
||||
def local(*args)
|
||||
Time.utc_time(*args).change_time_zone(self)
|
||||
end
|
||||
|
||||
begin # the following methods depend on the tzinfo gem
|
||||
require_library_or_gem "tzinfo" unless Object.const_defined?(:TZInfo)
|
||||
|
||||
# Method for creating new ActiveSupport::TimeWithZone instance in time zone of +self+. Example:
|
||||
#
|
||||
# Time.zone = "Hawaii" # => "Hawaii"
|
||||
# Time.zone.local(2007, 2, 1, 15, 30, 45) # => Thu, 01 Feb 2007 15:30:45 HST -10:00
|
||||
def local(*args)
|
||||
t = Time.utc_time(*args)
|
||||
begin
|
||||
result = local_to_utc(t)
|
||||
rescue TZInfo::PeriodNotFound
|
||||
t += 1.hour
|
||||
retry
|
||||
end
|
||||
result.in_time_zone(self)
|
||||
end
|
||||
|
||||
# Returns an ActiveSupport::TimeWithZone instance representing the current time
|
||||
# in the time zone represented by +self+. Example:
|
||||
#
|
||||
# Time.zone = 'Hawaii' # => "Hawaii"
|
||||
# Time.zone.now # => Wed, 23 Jan 2008 20:24:27 HST -10:00
|
||||
def now
|
||||
tzinfo.now.change_time_zone(self)
|
||||
Time.now.utc.in_time_zone(self)
|
||||
end
|
||||
|
||||
# Return the current date in this time zone.
|
||||
@@ -233,7 +240,7 @@ class TimeZone
|
||||
|
||||
rescue LoadError # Tzinfo gem is not available
|
||||
# re-raise LoadError only when a tzinfo-dependent method is called:
|
||||
%w(now today utc_to_local local_to_utc period_for_local tzinfo).each do |method|
|
||||
%w(local now today utc_to_local local_to_utc period_for_utc period_for_local tzinfo).each do |method|
|
||||
define_method(method) {|*args| raise LoadError, "TZInfo gem is required for TimeZone##{method}. `gem install tzinfo` and try again."}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -62,11 +62,32 @@ class TimeZoneTest < Test::Unit::TestCase
|
||||
|
||||
uses_mocha 'TestTimeZoneNowAndToday' do
|
||||
def test_now
|
||||
TZInfo::DataTimezone.any_instance.stubs(:now).returns(Time.utc(2000))
|
||||
zone = TimeZone['Eastern Time (US & Canada)']
|
||||
assert_instance_of ActiveSupport::TimeWithZone, zone.now
|
||||
assert_equal Time.utc(2000), zone.now.time
|
||||
assert_equal zone, zone.now.time_zone
|
||||
with_env_tz 'US/Eastern' do
|
||||
Time.stubs(:now).returns(Time.local(2000))
|
||||
zone = TimeZone['Eastern Time (US & Canada)']
|
||||
assert_instance_of ActiveSupport::TimeWithZone, zone.now
|
||||
assert_equal Time.utc(2000,1,1,5), zone.now.utc
|
||||
assert_equal Time.utc(2000), zone.now.time
|
||||
assert_equal zone, zone.now.time_zone
|
||||
end
|
||||
end
|
||||
|
||||
def test_now_enforces_spring_dst_rules
|
||||
with_env_tz 'US/Eastern' do
|
||||
Time.stubs(:now).returns(Time.local(2006,4,2,2)) # 2AM springs forward to 3AM
|
||||
zone = TimeZone['Eastern Time (US & Canada)']
|
||||
assert_equal Time.utc(2006,4,2,3), zone.now.time
|
||||
assert_equal true, zone.now.dst?
|
||||
end
|
||||
end
|
||||
|
||||
def test_now_enforces_fall_dst_rules
|
||||
with_env_tz 'US/Eastern' do
|
||||
Time.stubs(:now).returns(Time.local(2006,10,29,1)) # 1AM is ambiguous; could be DST or non-DST 1AM
|
||||
zone = TimeZone['Eastern Time (US & Canada)']
|
||||
assert_equal Time.utc(2006,10,29,1), zone.now.time # selects DST 1AM
|
||||
assert_equal true, zone.now.dst?
|
||||
end
|
||||
end
|
||||
|
||||
def test_today
|
||||
@@ -134,5 +155,42 @@ class TimeZoneTest < Test::Unit::TestCase
|
||||
assert_equal Time.utc(2007, 2, 5, 15, 30, 45), time.time
|
||||
assert_equal TimeZone["Hawaii"], time.time_zone
|
||||
end
|
||||
end
|
||||
|
||||
def test_local_enforces_spring_dst_rules
|
||||
zone = TimeZone['Eastern Time (US & Canada)']
|
||||
twz = zone.local(2006,4,2,1,59,59) # 1 second before DST start
|
||||
assert_equal Time.utc(2006,4,2,1,59,59), twz.time
|
||||
assert_equal Time.utc(2006,4,2,6,59,59), twz.utc
|
||||
assert_equal false, twz.dst?
|
||||
assert_equal 'EST', twz.zone
|
||||
twz2 = zone.local(2006,4,2,2) # 2AM does not exist because at 2AM, time springs forward to 3AM
|
||||
assert_equal Time.utc(2006,4,2,3), twz2.time # twz is created for 3AM
|
||||
assert_equal Time.utc(2006,4,2,7), twz2.utc
|
||||
assert_equal true, twz2.dst?
|
||||
assert_equal 'EDT', twz2.zone
|
||||
twz3 = zone.local(2006,4,2,2,30) # 2:30AM does not exist because at 2AM, time springs forward to 3AM
|
||||
assert_equal Time.utc(2006,4,2,3,30), twz3.time # twz is created for 3:30AM
|
||||
assert_equal Time.utc(2006,4,2,7,30), twz3.utc
|
||||
assert_equal true, twz3.dst?
|
||||
assert_equal 'EDT', twz3.zone
|
||||
end
|
||||
|
||||
def test_local_enforces_fall_dst_rules
|
||||
# 1AM during fall DST transition is ambiguous, it could be either DST or non-DST 1AM
|
||||
# Mirroring Time.local behavior, this method selects the DST time
|
||||
zone = TimeZone['Eastern Time (US & Canada)']
|
||||
twz = zone.local(2006,10,29,1)
|
||||
assert_equal Time.utc(2006,10,29,1), twz.time
|
||||
assert_equal Time.utc(2006,10,29,5), twz.utc
|
||||
assert_equal true, twz.dst?
|
||||
assert_equal 'EDT', twz.zone
|
||||
end
|
||||
|
||||
protected
|
||||
def with_env_tz(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
|
||||
|
||||
Reference in New Issue
Block a user