Class: TZInfo::TimeOrDateTime

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/tzinfo/time_or_datetime.rb

Overview

Used by TZInfo internally to represent either a Time, DateTime or an Integer timestamp (seconds since 1970-01-01 00:00:00).

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(timeOrDateTime) ⇒ TimeOrDateTime

Constructs a new TimeOrDateTime. timeOrDateTime can be a Time, DateTime or Integer. If using a Time or DateTime, any time zone information is ignored.

Integer timestamps must be within the range supported by Time on the platform being used.

[View source]

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/tzinfo/time_or_datetime.rb', line 17

def initialize(timeOrDateTime)
  @time = nil
  @datetime = nil
  @timestamp = nil
  
  if timeOrDateTime.is_a?(Time)
    @time = timeOrDateTime
    
    # Avoid using the slower Rational class unless necessary.
    nsec = RubyCoreSupport.time_nsec(@time)
    usec = nsec % 1000 == 0 ? nsec / 1000 : Rational(nsec, 1000)
    
    @time = Time.utc(@time.year, @time.mon, @time.mday, @time.hour, @time.min, @time.sec, usec) unless @time.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
    
    if !RubyCoreSupport.time_supports_64bit && (@timestamp > 2147483647 || @timestamp < -2147483648 || (@timestamp < 0 && !RubyCoreSupport.time_supports_negative))
      raise RangeError, 'Timestamp is outside the supported range of Time on this platform'
    end
    
    @orig = @timestamp
  end
end

Class Method Details

.wrap(timeOrDateTime) ⇒ Object

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.

The result of the block will be converted to the type of the originally passed in timeOrDateTime and then returned as the result of wrap.

timeOrDateTime can be a Time, DateTime, timestamp (Integer) or TimeOrDateTime. If a TimeOrDateTime is passed in, no new TimeOrDateTime will be constructed and the value passed to wrap will be used when calling the block.

[View source]

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/tzinfo/time_or_datetime.rb', line 313

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

Instance Method Details

#+(seconds) ⇒ Object

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.

[View source]

245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/tzinfo/time_or_datetime.rb', line 245

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
      TimeOrDateTime.new(@orig + seconds)
    end
  end
end

#-(seconds) ⇒ Object

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.

[View source]

262
263
264
# File 'lib/tzinfo/time_or_datetime.rb', line 262

def -(seconds)
  self + (-seconds)
end

#<=>(timeOrDateTime) ⇒ Object

Compares this TimeOrDateTime with another Time, DateTime, timestamp (Integer) or TimeOrDateTime. Returns -1, 0 or +1 depending whether the receiver is less than, equal to, or greater than timeOrDateTime.

Returns nil if the passed in timeOrDateTime is not comparable with TimeOrDateTime instances.

Comparisons involving a DateTime will be performed using DateTime#<=>. Comparisons that don’t involve a DateTime, but include a Time will be performed with Time#<=>. Otherwise comparisons will be performed with Integer#<=>.

[View source]

218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/tzinfo/time_or_datetime.rb', line 218

def <=>(timeOrDateTime)
  return nil unless timeOrDateTime.is_a?(TimeOrDateTime) || 
                    timeOrDateTime.is_a?(Time) ||
                    timeOrDateTime.is_a?(DateTime) ||
                    timeOrDateTime.respond_to?(:to_i)

  unless timeOrDateTime.is_a?(TimeOrDateTime)
    timeOrDateTime = TimeOrDateTime.wrap(timeOrDateTime)
  end
      
  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 its larger range of acceptable values on 32-bit systems).
    to_datetime <=> timeOrDateTime.to_datetime
  elsif @orig.is_a?(Time) || orig.is_a?(Time)
    to_time <=> timeOrDateTime.to_time
  else
    to_i <=> timeOrDateTime.to_i
  end
end

#add_with_convert(seconds) ⇒ Object

Similar to the + operator, but converts to a DateTime based TimeOrDateTime where the Time or Integer timestamp to go out of the allowed range for a Time, converts to a DateTime based TimeOrDateTime.

Note that the range of Time varies based on the platform.

[View source]

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/tzinfo/time_or_datetime.rb', line 271

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 > 2147483647 || result < -2147483648) && !RubyCoreSupport.time_supports_64bit) || (result < 0 && !RubyCoreSupport.time_supports_negative)
        result = TimeOrDateTime.new(to_datetime + OffsetRationals.rational_for_offset(seconds))
      else
        result = TimeOrDateTime.new(@orig + seconds)
      end
    end
  end
end

#eql?(todt) ⇒ Boolean

Returns true if todt represents the same time and was originally constructed with the same type (DateTime, Time or timestamp) as this TimeOrDateTime.

Returns:

  • (Boolean)
[View source]

293
294
295
# File 'lib/tzinfo/time_or_datetime.rb', line 293

def eql?(todt)
  todt.kind_of?(TimeOrDateTime) && to_orig.eql?(todt.to_orig)      
end

#hashObject

Returns a hash of this TimeOrDateTime.

[View source]

298
299
300
# File 'lib/tzinfo/time_or_datetime.rb', line 298

def hash
  @orig.hash
end

#hourObject

Returns the hour of the day (0..23).

[View source]

158
159
160
161
162
163
164
165
166
# File 'lib/tzinfo/time_or_datetime.rb', line 158

def hour
  if @time
    @time.hour
  elsif @datetime
    @datetime.hour
  else
    to_time.hour
  end
end

#inspectObject

Returns internal object state as a programmer-readable string.

[View source]

118
119
120
# File 'lib/tzinfo/time_or_datetime.rb', line 118

def inspect
  "#<#{self.class}: #{@orig.inspect}>"
end

#mdayObject Also known as: day

Returns the day of the month (1..n).

[View source]

146
147
148
149
150
151
152
153
154
# File 'lib/tzinfo/time_or_datetime.rb', line 146

def mday
  if @time
    @time.mday
  elsif @datetime
    @datetime.mday
  else
    to_time.mday
  end
end

#minObject

Returns the minute of the hour (0..59).

[View source]

169
170
171
172
173
174
175
176
177
# File 'lib/tzinfo/time_or_datetime.rb', line 169

def min
  if @time
    @time.min
  elsif @datetime
    @datetime.min
  else
    to_time.min
  end
end

#monObject Also known as: month

Returns the month of the year (1..12).

[View source]

134
135
136
137
138
139
140
141
142
# File 'lib/tzinfo/time_or_datetime.rb', line 134

def mon
  if @time
    @time.mon
  elsif @datetime
    @datetime.mon
  else
    to_time.mon
  end
end

#secObject

Returns the second of the minute (0..60). (60 for a leap second).

[View source]

180
181
182
183
184
185
186
187
188
# File 'lib/tzinfo/time_or_datetime.rb', line 180

def sec
  if @time
    @time.sec
  elsif @datetime
    @datetime.sec
  else
    to_time.sec
  end
end

#to_datetimeObject

Returns the time as a DateTime.

When converting from a Time, the result is truncated to microsecond precision.

[View source]

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/tzinfo/time_or_datetime.rb', line 71

def to_datetime
  # Thread-safety: It is possible that the value of @datetime may be 
  # calculated multiple times in concurrently executing threads. It is not 
  # worth the overhead of locking to ensure that @datetime is only 
  # calculated once.

  unless @datetime
    # Avoid using Rational unless necessary.
    u = usec
    s = u == 0 ? sec : Rational(sec * 1000000 + u, 1000000)
    @datetime = RubyCoreSupport.datetime_new(year, mon, mday, hour, min, s)
  end
  
  @datetime
end

#to_iObject

Returns the time as an integer timestamp.

[View source]

88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/tzinfo/time_or_datetime.rb', line 88

def to_i
  # Thread-safety: It is possible that the value of @timestamp may be 
  # calculated multiple times in concurrently executing threads. It is not 
  # worth the overhead of locking to ensure that @timestamp is only 
  # calculated once.

  unless @timestamp
    @timestamp = to_time.to_i
  end
  
  @timestamp
end

#to_origObject

Returns the time as the original time passed to new.

[View source]

102
103
104
# File 'lib/tzinfo/time_or_datetime.rb', line 102

def to_orig
  @orig
end

#to_sObject

Returns a string representation of the TimeOrDateTime.

[View source]

107
108
109
110
111
112
113
114
115
# File 'lib/tzinfo/time_or_datetime.rb', line 107

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

#to_timeObject

Returns the time as a Time.

When converting from a DateTime, the result is truncated to microsecond precision.

[View source]

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/tzinfo/time_or_datetime.rb', line 50

def to_time
  # Thread-safety: It is possible that the value of @time may be 
  # calculated multiple times in concurrently executing threads. It is not 
  # worth the overhead of locking to ensure that @time is only 
  # calculated once.

  unless @time
    if @timestamp
      @time = Time.at(@timestamp).utc
    else
      @time = Time.utc(year, mon, mday, hour, min, sec, usec)
    end
  end
  
  @time      
end

#usecObject

Returns the number of microseconds for the time.

[View source]

191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/tzinfo/time_or_datetime.rb', line 191

def usec      
  if @time
    @time.usec
  elsif @datetime
    # Ruby 1.8 has sec_fraction (of which the documentation says
    # 'I do NOT recommend you to use this method'). sec_fraction no longer
    # exists in Ruby 1.9.
    
    # Calculate the sec_fraction from the day_fraction.
    ((@datetime.day_fraction - OffsetRationals.rational_for_offset(@datetime.hour * 3600 + @datetime.min * 60 + @datetime.sec)) * 86400000000).to_i
  else 
    0
  end
end

#yearObject

Returns the year.

[View source]

123
124
125
126
127
128
129
130
131
# File 'lib/tzinfo/time_or_datetime.rb', line 123

def year
  if @time
    @time.year
  elsif @datetime
    @datetime.year
  else
    to_time.year
  end
end