diff options
Diffstat (limited to 'activesupport/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/time_or_datetime.rb')
-rw-r--r-- | activesupport/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/time_or_datetime.rb | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/time_or_datetime.rb b/activesupport/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/time_or_datetime.rb new file mode 100644 index 0000000000..264517f3ee --- /dev/null +++ b/activesupport/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/time_or_datetime.rb @@ -0,0 +1,292 @@ +#-- +# Copyright (c) 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 +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# 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 'date' +require 'time' +require 'tzinfo/offset_rationals' + +module TZInfo + # Used by TZInfo internally to represent either a Time, DateTime or integer + # timestamp (seconds since 1970-01-01 00:00:00). + class TimeOrDateTime #:nodoc: + include Comparable + + # Constructs a new TimeOrDateTime. timeOrDateTime can be a Time, DateTime + # or an integer. If using a Time or DateTime, any time zone information is + # ignored. + def initialize(timeOrDateTime) + @time = nil + @datetime = nil + @timestamp = nil + + if timeOrDateTime.is_a?(Time) + @time = timeOrDateTime + @time = Time.utc(@time.year, @time.mon, @time.mday, @time.hour, @time.min, @time.sec) unless @time.zone == 'UTC' + @orig = @time + elsif timeOrDateTime.is_a?(DateTime) + @datetime = timeOrDateTime + @datetime = @datetime.new_offset(0) unless @datetime.offset == 0 + @orig = @datetime + else + @timestamp = timeOrDateTime.to_i + @orig = @timestamp + end + end + + # Returns the time as a Time. + def to_time + unless @time + if @timestamp + @time = Time.at(@timestamp).utc + else + @time = Time.utc(year, mon, mday, hour, min, sec) + end + end + + @time + end + + # Returns the time as a DateTime. + def to_datetime + unless @datetime + @datetime = DateTime.new(year, mon, mday, hour, min, sec) + end + + @datetime + end + + # Returns the time as an integer timestamp. + def to_i + unless @timestamp + @timestamp = to_time.to_i + end + + @timestamp + end + + # Returns the time as the original time passed to new. + def to_orig + @orig + end + + # Returns a string representation of the TimeOrDateTime. + def to_s + if @orig.is_a?(Time) + "Time: #{@orig.to_s}" + elsif @orig.is_a?(DateTime) + "DateTime: #{@orig.to_s}" + else + "Timestamp: #{@orig.to_s}" + end + end + + # Returns internal object state as a programmer-readable string. + def inspect + "#<#{self.class}: #{@orig.inspect}>" + end + + # Returns the year. + def year + if @time + @time.year + elsif @datetime + @datetime.year + else + to_time.year + end + end + + # Returns the month of the year (1..12). + def mon + if @time + @time.mon + elsif @datetime + @datetime.mon + else + to_time.mon + end + end + alias :month :mon + + # Returns the day of the month (1..n). + def mday + if @time + @time.mday + elsif @datetime + @datetime.mday + else + to_time.mday + end + end + alias :day :mday + + # Returns the hour of the day (0..23). + def hour + if @time + @time.hour + elsif @datetime + @datetime.hour + else + to_time.hour + end + end + + # Returns the minute of the hour (0..59). + def min + if @time + @time.min + elsif @datetime + @datetime.min + else + to_time.min + end + end + + # Returns the second of the minute (0..60). (60 for a leap second). + def sec + if @time + @time.sec + elsif @datetime + @datetime.sec + else + to_time.sec + end + end + + # Compares this TimeOrDateTime with another Time, DateTime, integer + # timestamp or TimeOrDateTime. Returns -1, 0 or +1 depending whether the + # receiver is less than, equal to, or greater than timeOrDateTime. + # + # Milliseconds and smaller units are ignored in the comparison. + def <=>(timeOrDateTime) + if timeOrDateTime.is_a?(TimeOrDateTime) + orig = timeOrDateTime.to_orig + + if @orig.is_a?(DateTime) || orig.is_a?(DateTime) + # If either is a DateTime, assume it is there for a reason + # (i.e. for range). + to_datetime <=> timeOrDateTime.to_datetime + elsif orig.is_a?(Time) + to_time <=> timeOrDateTime.to_time + else + to_i <=> timeOrDateTime.to_i + end + elsif @orig.is_a?(DateTime) || timeOrDateTime.is_a?(DateTime) + # If either is a DateTime, assume it is there for a reason + # (i.e. for range). + to_datetime <=> TimeOrDateTime.wrap(timeOrDateTime).to_datetime + elsif timeOrDateTime.is_a?(Time) + to_time <=> timeOrDateTime + else + to_i <=> timeOrDateTime.to_i + end + end + + # Adds a number of seconds to the TimeOrDateTime. Returns a new + # TimeOrDateTime, preserving what the original constructed type was. + # If the original type is a Time and the resulting calculation goes out of + # range for Times, then an exception will be raised by the Time class. + def +(seconds) + if seconds == 0 + self + else + if @orig.is_a?(DateTime) + TimeOrDateTime.new(@orig + OffsetRationals.rational_for_offset(seconds)) + else + # + defined for Time and integer timestamps + TimeOrDateTime.new(@orig + seconds) + end + end + end + + # Subtracts a number of seconds from the TimeOrDateTime. Returns a new + # TimeOrDateTime, preserving what the original constructed type was. + # If the original type is a Time and the resulting calculation goes out of + # range for Times, then an exception will be raised by the Time class. + def -(seconds) + self + (-seconds) + end + + # Similar to the + operator, but for cases where adding would cause a + # timestamp or time to go out of the allowed range, converts to a DateTime + # based TimeOrDateTime. + def add_with_convert(seconds) + if seconds == 0 + self + else + if @orig.is_a?(DateTime) + TimeOrDateTime.new(@orig + OffsetRationals.rational_for_offset(seconds)) + else + # A Time or timestamp. + result = to_i + seconds + + if result < 0 || result > 2147483647 + result = TimeOrDateTime.new(to_datetime + OffsetRationals.rational_for_offset(seconds)) + else + result = TimeOrDateTime.new(@orig + seconds) + end + end + end + end + + # Returns true if todt represents the same time and was originally + # constructed with the same type (DateTime, Time or timestamp) as this + # TimeOrDateTime. + def eql?(todt) + todt.respond_to?(:to_orig) && to_orig.eql?(todt.to_orig) + end + + # Returns a hash of this TimeOrDateTime. + def hash + @orig.hash + end + + # If no block is given, returns a TimeOrDateTime wrapping the given + # timeOrDateTime. If a block is specified, a TimeOrDateTime is constructed + # and passed to the block. The result of the block must be a TimeOrDateTime. + # to_orig will be called on the result and the result of to_orig will be + # returned. + # + # timeOrDateTime can be a Time, DateTime, integer timestamp or TimeOrDateTime. + # If a TimeOrDateTime is passed in, no new TimeOrDateTime will be constructed, + # the passed in value will be used. + def self.wrap(timeOrDateTime) + t = timeOrDateTime.is_a?(TimeOrDateTime) ? timeOrDateTime : TimeOrDateTime.new(timeOrDateTime) + + if block_given? + t = yield t + + if timeOrDateTime.is_a?(TimeOrDateTime) + t + elsif timeOrDateTime.is_a?(Time) + t.to_time + elsif timeOrDateTime.is_a?(DateTime) + t.to_datetime + else + t.to_i + end + else + t + end + end + end +end |