~michaelforrest/use-case-mapper/trunk

« back to all changes in this revision

Viewing changes to vendor/rails/activesupport/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/time_or_datetime.rb

  • Committer: Richard Lee (Canonical)
  • Date: 2010-10-15 15:17:58 UTC
  • mfrom: (190.1.3 use-case-mapper)
  • Revision ID: richard.lee@canonical.com-20101015151758-wcvmfxrexsongf9d
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
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