1 # A +Time+ object represents a date and time:
3 # Time.new(2000, 1, 1, 0, 0, 0) # => 2000-01-01 00:00:00 -0600
5 # Although its value can be expressed as a single numeric
6 # (see {Epoch Seconds}[rdoc-ref:Time@Epoch+Seconds] below),
7 # it can be convenient to deal with the value by parts:
9 # t = Time.new(-2000, 1, 1, 0, 0, 0.0)
10 # # => -2000-01-01 00:00:00 -0600
19 # t = Time.new(2000, 12, 31, 23, 59, 59.5)
20 # # => 2000-12-31 23:59:59.5 -0600
31 # <i>Epoch seconds</i> is the exact number of seconds
32 # (including fractional subseconds) since the Unix Epoch, January 1, 1970.
34 # You can retrieve that value exactly using method Time.to_r:
36 # Time.at(0).to_r # => (0/1)
37 # Time.at(0.999999).to_r # => (9007190247541737/9007199254740992)
39 # Other retrieval methods such as Time#to_i and Time#to_f
40 # may return a value that rounds or truncates subseconds.
44 # A +Time+ object derived from the system clock
45 # (for example, by method Time.now)
46 # has the resolution supported by the system.
48 # == \Time Internal Representation
50 # Conceptually, Time class uses a rational value to represent the number of
51 # seconds from _Epoch_, 1970-01-01 00:00:00 UTC.
52 # There are no boundary or resolution limitations.
53 # The value can be obtained using Time#to_r.
55 # The Time class always uses the Gregorian calendar.
56 # I.e. the proleptic Gregorian calendar is used.
57 # Other calendars, such as Julian calendar, are not supported.
59 # The implementation uses a signed 63 bit integer, Integer (Bignum) object or
60 # Ratoinal object to represent a rational value.
61 # (The signed 63 bit integer is used regardless of 32 and 64 bit environments.)
62 # The value represents the number of nanoseconds from _Epoch_.
63 # The signed 63 bit integer can represent 1823-11-12 to 2116-02-20.
64 # When Integer or Rational object is used (before 1823, after 2116, under
65 # nanosecond), Time works slower than when the signed 63 bit integer is used.
67 # Ruby uses the C function +localtime+ and +gmtime+ to map between the number
68 # and 6-tuple (year,month,day,hour,minute,second).
69 # +localtime+ is used for local time and +gmtime+ is used for UTC.
71 # Integer and Rational has no range limit, but the localtime and
72 # gmtime has range limits due to the C types +time_t+ and <tt>struct tm</tt>.
73 # If that limit is exceeded, Ruby extrapolates the localtime function.
75 # +time_t+ can represent 1901-12-14 to 2038-01-19 if it is 32 bit signed integer,
76 # -292277022657-01-27 to 292277026596-12-05 if it is 64 bit signed integer.
77 # However +localtime+ on some platforms doesn't supports negative +time_t+ (before 1970).
79 # <tt>struct tm</tt> has _tm_year_ member to represent years.
80 # (<tt>tm_year = 0</tt> means the year 1900.)
81 # It is defined as +int+ in the C standard.
82 # _tm_year_ can represent years between -2147481748 to 2147485547 if +int+ is 32 bit.
84 # Ruby supports leap seconds as far as if the C function +localtime+ and
85 # +gmtime+ supports it.
86 # They use the tz database in most Unix systems.
87 # The tz database has timezones which supports leap seconds.
88 # For example, "Asia/Tokyo" doesn't support leap seconds but
89 # "right/Asia/Tokyo" supports leap seconds.
90 # So, Ruby supports leap seconds if the TZ environment variable is
91 # set to "right/Asia/Tokyo" in most Unix systems.
95 # All of these examples were done using the EST timezone which is GMT-5.
97 # === Creating a New +Time+ Instance
99 # You can create a new instance of Time with Time.new. This will use the
100 # current system time. Time.now is an alias for this. You can also
101 # pass parts of the time to Time.new such as year, month, minute, etc. When
102 # you want to construct a time this way you must pass at least a year. If you
103 # pass the year with nothing else time will default to January 1 of that year
104 # at 00:00:00 with the current system timezone. Here are some examples:
106 # Time.new(2002) #=> 2002-01-01 00:00:00 -0500
107 # Time.new(2002, 10) #=> 2002-10-01 00:00:00 -0500
108 # Time.new(2002, 10, 31) #=> 2002-10-31 00:00:00 -0500
110 # You can pass a UTC offset:
112 # Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200
114 # Or {a timezone object}[rdoc-ref:Time@Timezone+Objects]:
116 # zone = timezone("Europe/Athens") # Eastern European Time, UTC+2
117 # Time.new(2002, 10, 31, 2, 2, 2, zone) #=> 2002-10-31 02:02:02 +0200
119 # You can also use Time.local and Time.utc to infer
120 # local and UTC timezones instead of using the current system
123 # You can also create a new time using Time.at which takes the number of
124 # seconds (with subsecond) since the {Unix
125 # Epoch}[https://en.wikipedia.org/wiki/Unix_time].
127 # Time.at(628232400) #=> 1989-11-28 00:00:00 -0500
129 # === Working with an Instance of +Time+
131 # Once you have an instance of Time there is a multitude of things you can
132 # do with it. Below are some examples. For all of the following examples, we
133 # will work on the assumption that you have done the following:
135 # t = Time.new(1993, 02, 24, 12, 0, 0, "+09:00")
139 # t.monday? #=> false
141 # What year was that again?
145 # Was it daylight savings at the time?
149 # What's the day a year later?
151 # t + (60*60*24*365) #=> 1994-02-24 12:00:00 +0900
153 # How many seconds was that since the Unix Epoch?
155 # t.to_i #=> 730522800
157 # You can also do standard functions like compare two times.
159 # t1 = Time.new(2010)
160 # t2 = Time.new(2011)
167 # Time.new(2010,10,31).between?(t1, t2) #=> true
171 # First, what's elsewhere. Class +Time+:
173 # - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
174 # - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
176 # Here, class +Time+ provides methods that are useful for:
178 # - {Creating Time objects}[rdoc-ref:Time@Methods+for+Creating].
179 # - {Fetching Time values}[rdoc-ref:Time@Methods+for+Fetching].
180 # - {Querying a Time object}[rdoc-ref:Time@Methods+for+Querying].
181 # - {Comparing Time objects}[rdoc-ref:Time@Methods+for+Comparing].
182 # - {Converting a Time object}[rdoc-ref:Time@Methods+for+Converting].
183 # - {Rounding a Time}[rdoc-ref:Time@Methods+for+Rounding].
185 # === Methods for Creating
187 # - ::new: Returns a new time from specified arguments (year, month, etc.),
188 # including an optional timezone value.
189 # - ::local (aliased as ::mktime): Same as ::new, except the
190 # timezone is the local timezone.
191 # - ::utc (aliased as ::gm): Same as ::new, except the timezone is UTC.
192 # - ::at: Returns a new time based on seconds since epoch.
193 # - ::now: Returns a new time based on the current system time.
194 # - #+ (plus): Returns a new time increased by the given number of seconds.
195 # - #- (minus): Returns a new time decreased by the given number of seconds.
197 # === Methods for Fetching
199 # - #year: Returns the year of the time.
200 # - #month (aliased as #mon): Returns the month of the time.
201 # - #mday (aliased as #day): Returns the day of the month.
202 # - #hour: Returns the hours value for the time.
203 # - #min: Returns the minutes value for the time.
204 # - #sec: Returns the seconds value for the time.
205 # - #usec (aliased as #tv_usec): Returns the number of microseconds
206 # in the subseconds value of the time.
207 # - #nsec (aliased as #tv_nsec: Returns the number of nanoseconds
208 # in the subsecond part of the time.
209 # - #subsec: Returns the subseconds value for the time.
210 # - #wday: Returns the integer weekday value of the time (0 == Sunday).
211 # - #yday: Returns the integer yearday value of the time (1 == January 1).
212 # - #hash: Returns the integer hash value for the time.
213 # - #utc_offset (aliased as #gmt_offset and #gmtoff): Returns the offset
214 # in seconds between time and UTC.
215 # - #to_f: Returns the float number of seconds since epoch for the time.
216 # - #to_i (aliased as #tv_sec): Returns the integer number of seconds since epoch
218 # - #to_r: Returns the Rational number of seconds since epoch for the time.
219 # - #zone: Returns a string representation of the timezone of the time.
221 # === Methods for Querying
223 # - #utc? (aliased as #gmt?): Returns whether the time is UTC.
224 # - #dst? (aliased as #isdst): Returns whether the time is DST (daylight saving time).
225 # - #sunday?: Returns whether the time is a Sunday.
226 # - #monday?: Returns whether the time is a Monday.
227 # - #tuesday?: Returns whether the time is a Tuesday.
228 # - #wednesday?: Returns whether the time is a Wednesday.
229 # - #thursday?: Returns whether the time is a Thursday.
230 # - #friday?: Returns whether time is a Friday.
231 # - #saturday?: Returns whether the time is a Saturday.
233 # === Methods for Comparing
235 # - #<=>: Compares +self+ to another time.
236 # - #eql?: Returns whether the time is equal to another time.
238 # === Methods for Converting
240 # - #asctime (aliased as #ctime): Returns the time as a string.
241 # - #inspect: Returns the time in detail as a string.
242 # - #strftime: Returns the time as a string, according to a given format.
243 # - #to_a: Returns a 10-element array of values from the time.
244 # - #to_s: Returns a string representation of the time.
245 # - #getutc (aliased as #getgm): Returns a new time converted to UTC.
246 # - #getlocal: Returns a new time converted to local time.
247 # - #utc (aliased as #gmtime): Converts time to UTC in place.
248 # - #localtime: Converts time to local time in place.
249 # - #deconstruct_keys: Returns a hash of time components used in pattern-matching.
251 # === Methods for Rounding
253 # - #round:Returns a new time with subseconds rounded.
254 # - #ceil: Returns a new time with subseconds raised to a ceiling.
255 # - #floor: Returns a new time with subseconds lowered to a floor.
257 # For the forms of argument +zone+, see
258 # {Timezone Specifiers}[rdoc-ref:Time@Timezone+Specifiers].
260 # :include: doc/_timezones.rdoc
262 # Creates a new +Time+ object from the current system time.
263 # This is the same as Time.new without arguments.
265 # Time.now # => 2009-06-24 12:39:54 +0900
266 # Time.now(in: '+04:00') # => 2009-06-24 07:39:54 +0400
268 # For forms of argument +zone+, see
269 # {Timezone Specifiers}[rdoc-ref:Time@Timezone+Specifiers].
270 def self.now(in: nil)
271 Primitive.time_s_now(Primitive.arg!(:in))
274 # Returns a new +Time+ object based on the given arguments.
276 # Required argument +time+ may be either of:
278 # - A +Time+ object, whose value is the basis for the returned time;
279 # also influenced by optional keyword argument +in:+ (see below).
280 # - A numeric number of
281 # {Epoch seconds}[rdoc-ref:Time@Epoch+Seconds]
282 # for the returned time.
286 # t = Time.new(2000, 12, 31, 23, 59, 59) # => 2000-12-31 23:59:59 -0600
287 # secs = t.to_i # => 978328799
288 # Time.at(secs) # => 2000-12-31 23:59:59 -0600
289 # Time.at(secs + 0.5) # => 2000-12-31 23:59:59.5 -0600
290 # Time.at(1000000000) # => 2001-09-08 20:46:40 -0500
291 # Time.at(0) # => 1969-12-31 18:00:00 -0600
292 # Time.at(-1000000000) # => 1938-04-24 17:13:20 -0500
294 # Optional numeric argument +subsec+ and optional symbol argument +units+
295 # work together to specify subseconds for the returned time;
296 # argument +units+ specifies the units for +subsec+:
298 # - +:millisecond+: +subsec+ in milliseconds:
300 # Time.at(secs, 0, :millisecond) # => 2000-12-31 23:59:59 -0600
301 # Time.at(secs, 500, :millisecond) # => 2000-12-31 23:59:59.5 -0600
302 # Time.at(secs, 1000, :millisecond) # => 2001-01-01 00:00:00 -0600
303 # Time.at(secs, -1000, :millisecond) # => 2000-12-31 23:59:58 -0600
305 # - +:microsecond+ or +:usec+: +subsec+ in microseconds:
307 # Time.at(secs, 0, :microsecond) # => 2000-12-31 23:59:59 -0600
308 # Time.at(secs, 500000, :microsecond) # => 2000-12-31 23:59:59.5 -0600
309 # Time.at(secs, 1000000, :microsecond) # => 2001-01-01 00:00:00 -0600
310 # Time.at(secs, -1000000, :microsecond) # => 2000-12-31 23:59:58 -0600
312 # - +:nanosecond+ or +:nsec+: +subsec+ in nanoseconds:
314 # Time.at(secs, 0, :nanosecond) # => 2000-12-31 23:59:59 -0600
315 # Time.at(secs, 500000000, :nanosecond) # => 2000-12-31 23:59:59.5 -0600
316 # Time.at(secs, 1000000000, :nanosecond) # => 2001-01-01 00:00:00 -0600
317 # Time.at(secs, -1000000000, :nanosecond) # => 2000-12-31 23:59:58 -0600
320 # Optional keyword argument <tt>in: zone</tt> specifies the timezone
321 # for the returned time:
323 # Time.at(secs, in: '+12:00') # => 2001-01-01 17:59:59 +1200
324 # Time.at(secs, in: '-12:00') # => 2000-12-31 17:59:59 -1200
326 # For the forms of argument +zone+, see
327 # {Timezone Specifiers}[rdoc-ref:Time@Timezone+Specifiers].
329 def self.at(time, subsec = false, unit = :microsecond, in: nil)
330 if Primitive.mandatory_only?
331 Primitive.time_s_at1(time)
333 Primitive.time_s_at(time, subsec, unit, Primitive.arg!(:in))
338 # Time.new(year = nil, mon = nil, mday = nil, hour = nil, min = nil, sec = nil, zone = nil, in: nil, precision: 9)
340 # Returns a new +Time+ object based on the given arguments,
341 # by default in the local timezone.
343 # With no positional arguments, returns the value of Time.now:
345 # Time.new # => 2021-04-24 17:27:46.0512465 -0500
347 # With one string argument that represents a time, returns a new
348 # +Time+ object based on the given argument, in the local timezone.
350 # Time.new('2000-12-31 23:59:59.5') # => 2000-12-31 23:59:59.5 -0600
351 # Time.new('2000-12-31 23:59:59.5 +0900') # => 2000-12-31 23:59:59.5 +0900
352 # Time.new('2000-12-31 23:59:59.5', in: '+0900') # => 2000-12-31 23:59:59.5 +0900
353 # Time.new('2000-12-31 23:59:59.5') # => 2000-12-31 23:59:59.5 -0600
354 # Time.new('2000-12-31 23:59:59.56789', precision: 3) # => 2000-12-31 23:59:59.567 -0600
356 # With one to six arguments, returns a new +Time+ object
357 # based on the given arguments, in the local timezone.
359 # Time.new(2000, 1, 2, 3, 4, 5) # => 2000-01-02 03:04:05 -0600
361 # For the positional arguments (other than +zone+):
363 # - +year+: Year, with no range limits:
365 # Time.new(999999999) # => 999999999-01-01 00:00:00 -0600
366 # Time.new(-999999999) # => -999999999-01-01 00:00:00 -0600
368 # - +month+: Month in range (1..12), or case-insensitive
369 # 3-letter month name:
371 # Time.new(2000, 1) # => 2000-01-01 00:00:00 -0600
372 # Time.new(2000, 12) # => 2000-12-01 00:00:00 -0600
373 # Time.new(2000, 'jan') # => 2000-01-01 00:00:00 -0600
374 # Time.new(2000, 'JAN') # => 2000-01-01 00:00:00 -0600
376 # - +mday+: Month day in range(1..31):
378 # Time.new(2000, 1, 1) # => 2000-01-01 00:00:00 -0600
379 # Time.new(2000, 1, 31) # => 2000-01-31 00:00:00 -0600
381 # - +hour+: Hour in range (0..23), or 24 if +min+, +sec+, and +usec+
384 # Time.new(2000, 1, 1, 0) # => 2000-01-01 00:00:00 -0600
385 # Time.new(2000, 1, 1, 23) # => 2000-01-01 23:00:00 -0600
386 # Time.new(2000, 1, 1, 24) # => 2000-01-02 00:00:00 -0600
388 # - +min+: Minute in range (0..59):
390 # Time.new(2000, 1, 1, 0, 0) # => 2000-01-01 00:00:00 -0600
391 # Time.new(2000, 1, 1, 0, 59) # => 2000-01-01 00:59:00 -0600
393 # - +sec+: Second in range (0...61):
395 # Time.new(2000, 1, 1, 0, 0, 0) # => 2000-01-01 00:00:00 -0600
396 # Time.new(2000, 1, 1, 0, 0, 59) # => 2000-01-01 00:00:59 -0600
397 # Time.new(2000, 1, 1, 0, 0, 60) # => 2000-01-01 00:01:00 -0600
399 # +sec+ may be Float or Rational.
401 # Time.new(2000, 1, 1, 0, 0, 59.5) # => 2000-12-31 23:59:59.5 +0900
402 # Time.new(2000, 1, 1, 0, 0, 59.7r) # => 2000-12-31 23:59:59.7 +0900
404 # These values may be:
406 # - Integers, as above.
407 # - Numerics convertible to integers:
409 # Time.new(Float(0.0), Rational(1, 1), 1.0, 0.0, 0.0, 0.0)
410 # # => 0000-01-01 00:00:00 -0600
414 # a = %w[0 1 1 0 0 0]
415 # # => ["0", "1", "1", "0", "0", "0"]
416 # Time.new(*a) # => 0000-01-01 00:00:00 -0600
418 # When positional argument +zone+ or keyword argument +in:+ is given,
419 # the new +Time+ object is in the specified timezone.
420 # For the forms of argument +zone+, see
421 # {Timezone Specifiers}[rdoc-ref:Time@Timezone+Specifiers]:
423 # Time.new(2000, 1, 1, 0, 0, 0, '+12:00')
424 # # => 2000-01-01 00:00:00 +1200
425 # Time.new(2000, 1, 1, 0, 0, 0, in: '-12:00')
426 # # => 2000-01-01 00:00:00 -1200
427 # Time.new(in: '-12:00')
428 # # => 2022-08-23 08:49:26.1941467 -1200
430 # Since +in:+ keyword argument just provides the default, so if the
431 # first argument in single string form contains time zone information,
432 # this keyword argument will be silently ignored.
434 # Time.new('2000-01-01 00:00:00 +0100', in: '-0500').utc_offset # => 3600
436 # - +precision+: maximum effective digits in sub-second part, default is 9.
437 # More digits will be truncated, as other operations of +Time+.
438 # Ignored unless the first argument is a string.
440 def initialize(year = (now = true), mon = (str = year; nil), mday = nil, hour = nil, min = nil, sec = nil, zone = nil,
441 in: nil, precision: 9)
443 if Primitive.arg!(:in)
444 raise ArgumentError, "timezone argument given as positional and keyword arguments"
447 zone = Primitive.arg!(:in)
451 return Primitive.time_init_now(zone)
454 if str and Primitive.time_init_parse(str, zone, precision)
458 Primitive.time_init_args(year, mon, mday, hour, min, sec, zone)