Changeset 9040
- Timestamp:
- 03/17/08 02:40:28 (4 months ago)
- Files:
-
- trunk/activesupport/CHANGELOG (modified) (1 diff)
- trunk/activesupport/lib/active_support/time_with_zone.rb (modified) (3 diffs)
- trunk/activesupport/lib/active_support/values/time_zone.rb (modified) (1 diff)
- trunk/activesupport/test/core_ext/time_with_zone_test.rb (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/activesupport/CHANGELOG
r9013 r9040 1 1 *SVN* 2 3 * TimeWithZone caches TZInfo::TimezonePeriod used for time conversion so that it can be reused, and enforces DST rules correctly when instance is created from a local time [Geoff Buesing] 2 4 3 5 * Fixed that BufferedLogger should create its own directory if one doesn't already exist #11285 [lotswholetime] trunk/activesupport/lib/active_support/time_with_zone.rb
r9008 r9040 6 6 attr_reader :time_zone 7 7 8 def initialize(utc_time, time_zone, local_time = nil) 9 @utc = utc_time 10 @time = local_time 11 @time_zone = time_zone 8 def initialize(utc_time, time_zone, local_time = nil, period = nil) 9 @utc, @time_zone, @time = utc_time, time_zone, local_time 10 @period = @utc ? period : get_period_and_ensure_valid_local_time 12 11 end 13 12 14 13 # Returns a Time instance that represents the time in time_zone 15 14 def time 16 @time ||= time_zone.utc_to_local(@utc)15 @time ||= utc_to_local 17 16 end 18 17 19 18 # Returns a Time instance that represents the time in UTC 20 19 def utc 21 @utc ||= time_zone.local_to_utc(@time)20 @utc ||= local_to_utc 22 21 end 23 22 alias_method :comparable_time, :utc … … 26 25 alias_method :gmtime, :utc 27 26 28 # Returns the underlying TZInfo::TimezonePeriod for the local time27 # Returns the underlying TZInfo::TimezonePeriod 29 28 def period 30 @period ||= time_zone.period_for_utc( utc)29 @period ||= time_zone.period_for_utc(@utc) 31 30 end 32 31 … … 215 214 result 216 215 end 216 217 private 218 def get_period_and_ensure_valid_local_time 219 @time_zone.period_for_local(@time) 220 rescue ::TZInfo::PeriodNotFound 221 # time is in the "spring forward" hour gap, so we're moving the time forward one hour and trying again 222 @time += 1.hour 223 retry 224 end 225 226 # Replicating logic from TZInfo::Timezone#utc_to_local because we want to cache the period in an instance variable for reuse 227 def utc_to_local 228 ::TZInfo::TimeOrDateTime.wrap(utc) {|utc| period.to_local(utc)} 229 end 230 231 # Replicating logic from TZInfo::Timezone#local_to_utc because we want to cache the period in an instance variable for reuse 232 def local_to_utc 233 ::TZInfo::TimeOrDateTime.wrap(time) {|time| period.to_utc(time)} 234 end 217 235 end 218 236 end trunk/activesupport/lib/active_support/values/time_zone.rb
r9007 r9040 184 184 # Time.zone.local(2007, 2, 1, 15, 30, 45) # => Thu, 01 Feb 2007 15:30:45 HST -10:00 185 185 def local(*args) 186 t = Time.utc_time(*args) 187 begin 188 result = local_to_utc(t) 189 rescue TZInfo::PeriodNotFound 190 t += 1.hour 191 retry 192 end 193 result.in_time_zone(self) 186 time = Time.utc_time(*args) 187 ActiveSupport::TimeWithZone.new(nil, self, time) 194 188 end 195 189 trunk/activesupport/test/core_ext/time_with_zone_test.rb
r9008 r9040 256 256 assert_equal 17, twz.sec 257 257 assert_equal 500, twz.usec 258 end 259 260 def test_utc_to_local_conversion_saves_period_in_instance_variable 261 assert_nil @twz.instance_variable_get('@period') 262 @twz.time 263 assert_kind_of TZInfo::TimezonePeriod, @twz.instance_variable_get('@period') 264 end 265 266 def test_instance_created_with_local_time_returns_correct_utc_time 267 twz = ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(1999, 12, 31, 19)) 268 assert_equal Time.utc(2000), twz.utc 269 end 270 271 def test_instance_created_with_local_time_enforces_spring_dst_rules 272 twz = ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2006,4,2,2)) # first second of DST 273 assert_equal Time.utc(2006,4,2,3), twz.time # springs forward to 3AM 274 assert_equal true, twz.dst? 275 assert_equal 'EDT', twz.zone 276 end 277 278 def test_instance_created_with_local_time_enforces_fall_dst_rules 279 twz = ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2006,10,29,1)) # 1AM can be either DST or non-DST; we'll pick DST 280 assert_equal Time.utc(2006,10,29,1), twz.time 281 assert_equal true, twz.dst? 282 assert_equal 'EDT', twz.zone 258 283 end 259 284 end