lib/tzinfo/timezone_period.rb in tzinfo-0.1.2 vs lib/tzinfo/timezone_period.rb in tzinfo-0.2.0
- old
+ new
@@ -1,7 +1,7 @@
#--
-# Copyright (c) 2005 Philip Ross
+# Copyright (c) 2005-2006 Philip Ross
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
@@ -18,73 +18,20 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#++
+require 'tzinfo/offset_rationals'
+require 'tzinfo/time_or_datetime'
+
module TZInfo
# A period of time in a timezone where the same offset from UTC applies.
+ #
+ # All the methods that take times accept instances of Time, DateTime or
+ # integer timestamps.
class TimezonePeriod
-
- # A cache of pre-reduced Rationals for each half-hour between -12 and +12.
- # This is used to save time when loading a TimezonePeriod.
- @@rational_cache = {
- -43200 => Rational.new!(-1,2),
- -41400 => Rational.new!(-23,48),
- -39600 => Rational.new!(-11,24),
- -37800 => Rational.new!(-7,16),
- -36000 => Rational.new!(-5,12),
- -34200 => Rational.new!(-19,48),
- -32400 => Rational.new!(-3,8),
- -30600 => Rational.new!(-17,48),
- -28800 => Rational.new!(-1,3),
- -27000 => Rational.new!(-5,16),
- -25200 => Rational.new!(-7,24),
- -23400 => Rational.new!(-13,48),
- -21600 => Rational.new!(-1,4),
- -19800 => Rational.new!(-11,48),
- -18000 => Rational.new!(-5,24),
- -16200 => Rational.new!(-3,16),
- -14400 => Rational.new!(-1,6),
- -12600 => Rational.new!(-7,48),
- -10800 => Rational.new!(-1,8),
- -9000 => Rational.new!(-5,48),
- -7200 => Rational.new!(-1,12),
- -5400 => Rational.new!(-1,16),
- -3600 => Rational.new!(-1,24),
- -1800 => Rational.new!(-1,48),
- 0 => Rational.new!(0,1),
- 1800 => Rational.new!(1,48),
- 3600 => Rational.new!(1,24),
- 5400 => Rational.new!(1,16),
- 7200 => Rational.new!(1,12),
- 9000 => Rational.new!(5,48),
- 10800 => Rational.new!(1,8),
- 12600 => Rational.new!(7,48),
- 14400 => Rational.new!(1,6),
- 16200 => Rational.new!(3,16),
- 18000 => Rational.new!(5,24),
- 19800 => Rational.new!(11,48),
- 21600 => Rational.new!(1,4),
- 23400 => Rational.new!(13,48),
- 25200 => Rational.new!(7,24),
- 27000 => Rational.new!(5,16),
- 28800 => Rational.new!(1,3),
- 30600 => Rational.new!(17,48),
- 32400 => Rational.new!(3,8),
- 34200 => Rational.new!(19,48),
- 36000 => Rational.new!(5,12),
- 37800 => Rational.new!(7,16),
- 39600 => Rational.new!(11,24),
- 41400 => Rational.new!(23,48),
- 43200 => Rational.new!(1,2)}
-
- # Start time of the period (UTC). May be nil if unbounded.
- attr_reader :utc_start
-
- # End time of the period (UTC). May be nil if unbounded.
- attr_reader :utc_end
-
+
# Base offset of the timezone from UTC (seconds).
attr_reader :utc_offset
# Offset from the local time where daylight savings is in effect (seconds).
# E.g.: utc_offset could be -5 hours. Normally, std_offset would be 0.
@@ -92,43 +39,59 @@
attr_reader :std_offset
# The identifier of this period, e.g. "GMT" (Greenwich Mean Time) or "BST"
# (British Summer Time) for "Europe/London". The returned identifier is a
# symbol.
- attr_reader :zone_identifier
+ attr_reader :zone_identifier
- # Start time of the period (local time). May be nil if unbounded.
- attr_reader :local_start
+ # Total offset from UTC (seconds). Equal to utc_offset + std_offset.
+ attr_reader :utc_total_offset
- # End time of the period (local time). May be nil if unbounded.
- attr_reader :local_end
-
# Initializes a new TimezonePeriod.
def initialize(utc_start, utc_end, utc_offset, std_offset, zone_identifier)
- @utc_start = utc_start
- @utc_end = utc_end
+ @utc_start = utc_start.nil? ? nil : TimeOrDateTime.wrap(utc_start)
+ @utc_end = utc_end.nil? ? nil : TimeOrDateTime.wrap(utc_end)
@utc_offset = utc_offset
@std_offset = std_offset
@zone_identifier = zone_identifier
@utc_total_offset = utc_offset + std_offset
- @utc_total_offset_rational = @@rational_cache[utc_total_offset]
- @utc_total_offset_rational = Rational(utc_total_offset, 86400) if @utc_total_offset_rational.nil?
-
- @local_start = utc_start.nil? ? nil : to_local(utc_start)
- @local_end = utc_end.nil? ? nil : to_local(utc_end)
+ @utc_total_offset_rational = nil
+
+ # Use add_with_convert to use DateTime based TimeOrDateTimes if we run
+ # off the range of Time.
+ @local_start = @utc_start.nil? ? nil : @utc_start.add_with_convert(@utc_total_offset)
+ @local_end = @utc_end.nil? ? nil : @utc_end.add_with_convert(@utc_total_offset)
end
-
- # Total offset from UTC (seconds). Equal to utc_offset + std_offset.
- def utc_total_offset
- @utc_total_offset
- end
-
+
# Total offset from UTC (days). Result is a Rational.
def utc_total_offset_rational
+ if @utc_total_offset_rational.nil?
+ @utc_total_offset_rational = OffsetRationals.rational_for_offset(@utc_total_offset)
+ end
@utc_total_offset_rational
end
+ # Start time of the period (UTC). May be nil if unbounded.
+ def utc_start
+ @utc_start.nil? ? nil : @utc_start.to_datetime
+ end
+
+ # End time of the period (UTC). May be nil if unbounded.
+ def utc_end
+ @utc_end.nil? ? nil : @utc_end.to_datetime
+ end
+
+ # Start time of the period (local time). May be nil if unbounded.
+ def local_start
+ @local_start.nil? ? nil : @local_start.to_datetime
+ end
+
+ # End time of the period (local time). May be nil if unbounded.
+ def local_end
+ @local_end.nil? ? nil : @local_end.to_datetime
+ end
+
# true if daylight savings is in effect for this period; otherwise false.
def dst?
std_offset != 0
end
@@ -136,40 +99,44 @@
def valid_for_utc?(utc)
utc_after_start?(utc) && utc_before_end?(utc)
end
# true if the given utc DateTime is after the start of the period (inclusive); otherwise false.
- def utc_after_start?(utc)
+ def utc_after_start?(utc)
@utc_start.nil? || @utc_start <= utc
end
# true if the given utc DateTime is before the end of the period (exclusive); otherwise false.
- def utc_before_end?(utc)
+ def utc_before_end?(utc)
@utc_end.nil? || @utc_end > utc
end
# true if this period is valid for the given local DateTime; otherwise false.
- def valid_for_local?(local)
+ def valid_for_local?(local)
local_after_start?(local) && local_before_end?(local)
end
# true if the given local DateTime is after the start of the period (inclusive); otherwise false.
- def local_after_start?(local)
+ def local_after_start?(local)
@local_start.nil? || @local_start <= local
end
# true if the given local DateTime is before the end of the period (exclusive); otherwise false.
- def local_before_end?(local)
+ def local_before_end?(local)
@local_end.nil? || @local_end > local
end
# Converts a UTC DateTime to local time based on the offset of this period.
def to_local(utc)
- utc + utc_total_offset_rational
+ TimeOrDateTime.wrap(utc) {|utc|
+ utc + utc_total_offset
+ }
end
# Converts a local DateTime to UTC based on the offset of this period.
def to_utc(local)
- local - utc_total_offset_rational
+ TimeOrDateTime.wrap(local) {|local|
+ local - utc_total_offset
+ }
end
end
end