File: active_support/vendor/tzinfo-0.3.12/tzinfo/time_or_datetime.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: TZInfo#27
  class: TimeOrDateTime#30
includes
  Comparable ( Builtin-Module )
inherits from
  Object ( Builtin-Module )
has properties
method: initialize / 1 #36
method: to_time #56
method: to_datetime #69
method: to_i #78
method: to_orig #87
method: to_s #92
method: inspect #103
method: year #108
method: mon #119
alias: month mon #128
method: mday #131
alias: day mday #140
method: hour #143
method: min #154
method: sec #165
method: <=> / 1 #180
method: + / 1 #208
method: - / 1 #225
method: add_with_convert / 1 #232
method: eql? / 1 #254
method: hash #259
class method: wrap / 1 #272

Class Hierarchy

Object ( Builtin-Module )
  TimeOrDateTime ( TZInfo ) #30

Code

   1  #--
   2  # Copyright (c) 2006 Philip Ross
   3  # 
   4  # Permission is hereby granted, free of charge, to any person obtaining a copy
   5  # of this software and associated documentation files (the "Software"), to deal
   6  # in the Software without restriction, including without limitation the rights
   7  # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   8  # copies of the Software, and to permit persons to whom the Software is
   9  # furnished to do so, subject to the following conditions:
  10  # 
  11  # The above copyright notice and this permission notice shall be included in all
  12  # copies or substantial portions of the Software.
  13  #
  14  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15  # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16  # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17  # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20  # THE SOFTWARE.
  21  #++
  22 
  23  require 'date'
  24  require 'time'
  25  require 'tzinfo/offset_rationals'
  26 
  27  module TZInfo
  28    # Used by TZInfo internally to represent either a Time, DateTime or integer
  29    # timestamp (seconds since 1970-01-01 00:00:00).
  30    class TimeOrDateTime #:nodoc:
  31      include Comparable
  32      
  33      # Constructs a new TimeOrDateTime. timeOrDateTime can be a Time, DateTime
  34      # or an integer. If using a Time or DateTime, any time zone information is 
  35      # ignored.
  36      def initialize(timeOrDateTime)
  37        @time = nil
  38        @datetime = nil
  39        @timestamp = nil
  40        
  41        if timeOrDateTime.is_a?(Time)
  42          @time = timeOrDateTime        
  43          @time = Time.utc(@time.year, @time.mon, @time.mday, @time.hour, @time.min, @time.sec) unless @time.zone == 'UTC'        
  44          @orig = @time
  45        elsif timeOrDateTime.is_a?(DateTime)
  46          @datetime = timeOrDateTime
  47          @datetime = @datetime.new_offset(0) unless @datetime.offset == 0
  48          @orig = @datetime
  49        else
  50          @timestamp = timeOrDateTime.to_i
  51          @orig = @timestamp
  52        end
  53      end
  54      
  55      # Returns the time as a Time.
  56      def to_time
  57        unless @time        
  58          if @timestamp 
  59            @time = Time.at(@timestamp).utc
  60          else
  61            @time = Time.utc(year, mon, mday, hour, min, sec)
  62          end
  63        end
  64        
  65        @time      
  66      end
  67      
  68      # Returns the time as a DateTime.
  69      def to_datetime
  70        unless @datetime
  71          @datetime = DateTime.new(year, mon, mday, hour, min, sec)
  72        end
  73        
  74        @datetime
  75      end
  76      
  77      # Returns the time as an integer timestamp.
  78      def to_i
  79        unless @timestamp
  80          @timestamp = to_time.to_i
  81        end
  82        
  83        @timestamp
  84      end
  85      
  86      # Returns the time as the original time passed to new.
  87      def to_orig
  88        @orig
  89      end
  90      
  91      # Returns a string representation of the TimeOrDateTime.
  92      def to_s
  93        if @orig.is_a?(Time)
  94          "Time: #{@orig.to_s}"
  95        elsif @orig.is_a?(DateTime)
  96          "DateTime: #{@orig.to_s}"
  97        else
  98          "Timestamp: #{@orig.to_s}"
  99        end
 100      end
 101      
 102      # Returns internal object state as a programmer-readable string.
 103      def inspect
 104        "#<#{self.class}: #{@orig.inspect}>"
 105      end
 106      
 107      # Returns the year.
 108      def year
 109        if @time
 110          @time.year
 111        elsif @datetime
 112          @datetime.year
 113        else
 114          to_time.year
 115        end
 116      end
 117      
 118      # Returns the month of the year (1..12).
 119      def mon
 120        if @time
 121          @time.mon
 122        elsif @datetime
 123          @datetime.mon
 124        else
 125          to_time.mon
 126        end
 127      end
 128      alias :month :mon
 129      
 130      # Returns the day of the month (1..n).
 131      def mday
 132        if @time
 133          @time.mday
 134        elsif @datetime
 135          @datetime.mday
 136        else
 137          to_time.mday
 138        end
 139      end
 140      alias :day :mday
 141      
 142      # Returns the hour of the day (0..23).
 143      def hour
 144        if @time
 145          @time.hour
 146        elsif @datetime
 147          @datetime.hour
 148        else
 149          to_time.hour
 150        end
 151      end
 152      
 153      # Returns the minute of the hour (0..59).
 154      def min
 155        if @time
 156          @time.min
 157        elsif @datetime
 158          @datetime.min
 159        else
 160          to_time.min
 161        end
 162      end
 163      
 164      # Returns the second of the minute (0..60). (60 for a leap second).
 165      def sec
 166        if @time
 167          @time.sec
 168        elsif @datetime
 169          @datetime.sec
 170        else
 171          to_time.sec
 172        end
 173      end
 174      
 175      # Compares this TimeOrDateTime with another Time, DateTime, integer
 176      # timestamp or TimeOrDateTime. Returns -1, 0 or +1 depending whether the 
 177      # receiver is less than, equal to, or greater than timeOrDateTime.
 178      #
 179      # Milliseconds and smaller units are ignored in the comparison.
 180      def <=>(timeOrDateTime)
 181        if timeOrDateTime.is_a?(TimeOrDateTime)            
 182          orig = timeOrDateTime.to_orig
 183          
 184          if @orig.is_a?(DateTime) || orig.is_a?(DateTime)
 185            # If either is a DateTime, assume it is there for a reason 
 186            # (i.e. for range).
 187            to_datetime <=> timeOrDateTime.to_datetime
 188          elsif orig.is_a?(Time)
 189            to_time <=> timeOrDateTime.to_time
 190          else
 191            to_i <=> timeOrDateTime.to_i
 192          end        
 193        elsif @orig.is_a?(DateTime) || timeOrDateTime.is_a?(DateTime)
 194          # If either is a DateTime, assume it is there for a reason 
 195          # (i.e. for range).        
 196          to_datetime <=> TimeOrDateTime.wrap(timeOrDateTime).to_datetime
 197        elsif timeOrDateTime.is_a?(Time)
 198          to_time <=> timeOrDateTime
 199        else
 200          to_i <=> timeOrDateTime.to_i
 201        end
 202      end
 203      
 204      # Adds a number of seconds to the TimeOrDateTime. Returns a new 
 205      # TimeOrDateTime, preserving what the original constructed type was.
 206      # If the original type is a Time and the resulting calculation goes out of
 207      # range for Times, then an exception will be raised by the Time class.
 208      def +(seconds)
 209        if seconds == 0
 210          self
 211        else
 212          if @orig.is_a?(DateTime)
 213            TimeOrDateTime.new(@orig + OffsetRationals.rational_for_offset(seconds))
 214          else
 215            # + defined for Time and integer timestamps
 216            TimeOrDateTime.new(@orig + seconds)
 217          end
 218        end
 219      end
 220      
 221      # Subtracts a number of seconds from the TimeOrDateTime. Returns a new 
 222      # TimeOrDateTime, preserving what the original constructed type was.
 223      # If the original type is a Time and the resulting calculation goes out of
 224      # range for Times, then an exception will be raised by the Time class.
 225      def -(seconds)
 226        self + (-seconds)
 227      end
 228     
 229      # Similar to the + operator, but for cases where adding would cause a 
 230      # timestamp or time to go out of the allowed range, converts to a DateTime
 231      # based TimeOrDateTime.
 232      def add_with_convert(seconds)
 233        if seconds == 0
 234          self
 235        else
 236          if @orig.is_a?(DateTime)
 237            TimeOrDateTime.new(@orig + OffsetRationals.rational_for_offset(seconds))
 238          else
 239            # A Time or timestamp.
 240            result = to_i + seconds
 241            
 242            if result < 0 || result > 2147483647
 243              result = TimeOrDateTime.new(to_datetime + OffsetRationals.rational_for_offset(seconds))
 244            else
 245              result = TimeOrDateTime.new(@orig + seconds)
 246            end
 247          end
 248        end
 249      end
 250      
 251      # Returns true if todt represents the same time and was originally 
 252      # constructed with the same type (DateTime, Time or timestamp) as this 
 253      # TimeOrDateTime.
 254      def eql?(todt)
 255        todt.respond_to?(:to_orig) && to_orig.eql?(todt.to_orig)      
 256      end
 257      
 258      # Returns a hash of this TimeOrDateTime.
 259      def hash
 260        @orig.hash
 261      end
 262      
 263      # If no block is given, returns a TimeOrDateTime wrapping the given 
 264      # timeOrDateTime. If a block is specified, a TimeOrDateTime is constructed
 265      # and passed to the block. The result of the block must be a TimeOrDateTime.
 266      # to_orig will be called on the result and the result of to_orig will be
 267      # returned.
 268      #
 269      # timeOrDateTime can be a Time, DateTime, integer timestamp or TimeOrDateTime.
 270      # If a TimeOrDateTime is passed in, no new TimeOrDateTime will be constructed,
 271      # the passed in value will be used.
 272      def self.wrap(timeOrDateTime)      
 273        t = timeOrDateTime.is_a?(TimeOrDateTime) ? timeOrDateTime : TimeOrDateTime.new(timeOrDateTime)        
 274        
 275        if block_given?
 276          t = yield t
 277          
 278          if timeOrDateTime.is_a?(TimeOrDateTime)
 279            t          
 280          elsif timeOrDateTime.is_a?(Time)
 281            t.to_time
 282          elsif timeOrDateTime.is_a?(DateTime)
 283            t.to_datetime
 284          else
 285            t.to_i
 286          end        
 287        else
 288          t
 289        end
 290      end
 291    end
 292  end