summaryrefslogtreecommitdiff
path: root/timev.rb
diff options
context:
space:
mode:
Diffstat (limited to 'timev.rb')
-rw-r--r--timev.rb357
1 files changed, 232 insertions, 125 deletions
diff --git a/timev.rb b/timev.rb
index 1be675df35..22f46b9729 100644
--- a/timev.rb
+++ b/timev.rb
@@ -1,25 +1,55 @@
-# Time is an abstraction of dates and times. Time is stored internally as
-# the number of seconds with subsecond since the _Epoch_,
-# 1970-01-01 00:00:00 UTC.
+# A +Time+ object represents a date and time:
#
-# The Time class treats GMT
-# (Greenwich Mean Time) and UTC (Coordinated Universal Time) as equivalent.
-# GMT is the older way of referring to these baseline times but persists in
-# the names of calls on POSIX systems.
+# Time.new(2000, 1, 1, 0, 0, 0) # => 2000-01-01 00:00:00 -0600
#
-# Note: A \Time object uses the resolution available on your system clock.
+# Although its value can be expressed as a single numeric
+# (see {Epoch Seconds}[rdoc-ref:Time@Epoch+Seconds] below),
+# it can be convenient to deal with the value by parts:
#
-# All times may have subsecond. Be aware of this fact when comparing times
-# with each other -- times that are apparently equal when displayed may be
-# different when compared.
-# (Since Ruby 2.7.0, Time#inspect shows subsecond but
-# Time#to_s still doesn't show subsecond.)
+# t = Time.new(-2000, 1, 1, 0, 0, 0.0)
+# # => -2000-01-01 00:00:00 -0600
+# t.year # => -2000
+# t.month # => 1
+# t.mday # => 1
+# t.hour # => 0
+# t.min # => 0
+# t.sec # => 0
+# t.subsec # => 0
+#
+# t = Time.new(2000, 12, 31, 23, 59, 59.5)
+# # => 2000-12-31 23:59:59.5 -0600
+# t.year # => 2000
+# t.month # => 12
+# t.mday # => 31
+# t.hour # => 23
+# t.min # => 59
+# t.sec # => 59
+# t.subsec # => (1/2)
+#
+# == Epoch Seconds
+#
+# <i>Epoch seconds</i> is the exact number of seconds
+# (including fractional subseconds) since the Unix Epoch, January 1, 1970.
+#
+# You can retrieve that value exactly using method Time.to_r:
+#
+# Time.at(0).to_r # => (0/1)
+# Time.at(0.999999).to_r # => (9007190247541737/9007199254740992)
+#
+# Other retrieval methods such as Time#to_i and Time#to_f
+# may return a value that rounds or truncates subseconds.
+#
+# == \Time Resolution
+#
+# A +Time+ object derived from the system clock
+# (for example, by method Time.now)
+# has the resolution supported by the system.
#
# == Examples
#
# All of these examples were done using the EST timezone which is GMT-5.
#
-# === Creating a New \Time Instance
+# === Creating a New +Time+ Instance
#
# You can create a new instance of Time with Time.new. This will use the
# current system time. Time.now is an alias for this. You can also
@@ -36,7 +66,7 @@
#
# Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200
#
-# Or a timezone object:
+# Or {a timezone object}[rdoc-ref:Time@Timezone+Objects]:
#
# zone = timezone("Europe/Athens") # Eastern European Time, UTC+2
# Time.new(2002, 10, 31, 2, 2, 2, zone) #=> 2002-10-31 02:02:02 +0200
@@ -51,7 +81,7 @@
#
# Time.at(628232400) #=> 1989-11-28 00:00:00 -0500
#
-# === Working with an Instance of \Time
+# === Working with an Instance of +Time+
#
# Once you have an instance of Time there is a multitude of things you can
# do with it. Below are some examples. For all of the following examples, we
@@ -93,19 +123,19 @@
#
# == What's Here
#
-# First, what's elsewhere. \Class \Time:
+# First, what's elsewhere. \Class +Time+:
#
-# - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
-# - Includes {module Comparable}[Comparable.html#module-Comparable-label-What-27s+Here].
+# - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+# - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
#
-# Here, class \Time provides methods that are useful for:
+# Here, class +Time+ provides methods that are useful for:
#
-# - {Creating \Time objects}[#class-Time-label-Methods+for+Creating].
-# - {Fetching \Time values}[#class-Time-label-Methods+for+Fetching].
-# - {Querying a \Time object}[#class-Time-label-Methods+for+Querying].
-# - {Comparing \Time objects}[#class-Time-label-Methods+for+Comparing].
-# - {Converting a \Time object}[#class-Time-label-Methods+for+Converting].
-# - {Rounding a \Time}[#class-Time-label-Methods+for+Rounding].
+# - {Creating +Time+ objects}[rdoc-ref:Time@Methods+for+Creating].
+# - {Fetching +Time+ values}[rdoc-ref:Time@Methods+for+Fetching].
+# - {Querying a +Time+ object}[rdoc-ref:Time@Methods+for+Querying].
+# - {Comparing +Time+ objects}[rdoc-ref:Time@Methods+for+Comparing].
+# - {Converting a +Time+ object}[rdoc-ref:Time@Methods+for+Converting].
+# - {Rounding a +Time+}[rdoc-ref:Time@Methods+for+Rounding].
#
# === Methods for Creating
#
@@ -117,8 +147,7 @@
# - ::at: Returns a new time based on seconds since epoch.
# - ::now: Returns a new time based on the current system time.
# - #+ (plus): Returns a new time increased by the given number of seconds.
-# - {-}[#method-i-2D] (minus): Returns a new time
-# decreased by the given number of seconds.
+# - #- (minus): Returns a new time decreased by the given number of seconds.
#
# === Methods for Fetching
#
@@ -158,7 +187,7 @@
#
# === Methods for Comparing
#
-# - {#<=>}[#method-i-3C-3D-3E]: Compares +self+ to another time.
+# - #<=>: Compares +self+ to another time.
# - #eql?: Returns whether the time is equal to another time.
#
# === Methods for Converting
@@ -172,6 +201,7 @@
# - #getlocal: Returns a new time converted to local time.
# - #utc (aliased as #gmtime): Converts time to UTC in place.
# - #localtime: Converts time to local time in place.
+# - #deconstruct_keys: Returns a hash of time components used in pattern-matching.
#
# === Methods for Rounding
#
@@ -179,130 +209,207 @@
# - #ceil: Returns a new time with subseconds raised to a ceiling.
# - #floor: Returns a new time with subseconds lowered to a floor.
#
-# == Timezone Argument
+# For the forms of argument +zone+, see
+# {Timezone Specifiers}[rdoc-ref:Time@Timezone+Specifiers].
#
-# A timezone argument must have +local_to_utc+ and +utc_to_local+
-# methods, and may have +name+, +abbr+, and +dst?+ methods.
-#
-# The +local_to_utc+ method should convert a Time-like object from
-# the timezone to UTC, and +utc_to_local+ is the opposite. The
-# result also should be a Time or Time-like object (not necessary to
-# be the same class). The #zone of the result is just ignored.
-# Time-like argument to these methods is similar to a Time object in
-# UTC without subsecond; it has attribute readers for the parts,
-# e.g. #year, #month, and so on, and epoch time readers, #to_i. The
-# subsecond attributes are fixed as 0, and #utc_offset, #zone,
-# #isdst, and their aliases are same as a Time object in UTC.
-# Also #to_time, #+, and #- methods are defined.
-#
-# The +name+ method is used for marshaling. If this method is not
-# defined on a timezone object, Time objects using that timezone
-# object can not be dumped by Marshal.
-#
-# The +abbr+ method is used by '%Z' in #strftime.
-#
-# The +dst?+ method is called with a +Time+ value and should return whether
-# the +Time+ value is in daylight savings time in the zone.
-#
-# === Auto Conversion to Timezone
-#
-# At loading marshaled data, a timezone name will be converted to a timezone
-# object by +find_timezone+ class method, if the method is defined.
-#
-# Similarly, that class method will be called when a timezone argument does
-# not have the necessary methods mentioned above.
+# :include: doc/_timezones.rdoc
class Time
- # Creates a new \Time object from the current system time.
+ # Creates a new +Time+ object from the current system time.
# This is the same as Time.new without arguments.
#
# Time.now # => 2009-06-24 12:39:54 +0900
# Time.now(in: '+04:00') # => 2009-06-24 07:39:54 +0400
#
- # Parameter:
- # :include: doc/time/in.rdoc
+ # For forms of argument +zone+, see
+ # {Timezone Specifiers}[rdoc-ref:Time@Timezone+Specifiers].
def self.now(in: nil)
- new(in: __builtin.arg!(:in))
+ Primitive.time_s_now(Primitive.arg!(:in))
end
- # _Time_
- #
- # This form accepts a \Time object +time+
- # and optional keyword argument +in+:
- #
- # Time.at(Time.new) # => 2021-04-26 08:52:31.6023486 -0500
- # Time.at(Time.new, in: '+09:00') # => 2021-04-26 22:52:31.6023486 +0900
- #
- # _Seconds_
- #
- # This form accepts a numeric number of seconds +sec+
- # and optional keyword argument +in+:
- #
- # Time.at(946702800) # => 1999-12-31 23:00:00 -0600
- # Time.at(946702800, in: '+09:00') # => 2000-01-01 14:00:00 +0900
- #
- # <em>Seconds with Subseconds and Units</em>
- #
- # This form accepts an integer number of seconds +sec_i+,
- # a numeric number of milliseconds +msec+,
- # a symbol argument for the subsecond unit type (defaulting to :usec),
- # and an optional keyword argument +in+:
- #
- # Time.at(946702800, 500, :millisecond) # => 1999-12-31 23:00:00.5 -0600
- # Time.at(946702800, 500, :millisecond, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900
- # Time.at(946702800, 500000) # => 1999-12-31 23:00:00.5 -0600
- # Time.at(946702800, 500000, :usec) # => 1999-12-31 23:00:00.5 -0600
- # Time.at(946702800, 500000, :microsecond) # => 1999-12-31 23:00:00.5 -0600
- # Time.at(946702800, 500000, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900
- # Time.at(946702800, 500000, :usec, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900
- # Time.at(946702800, 500000, :microsecond, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900
- # Time.at(946702800, 500000000, :nsec) # => 1999-12-31 23:00:00.5 -0600
- # Time.at(946702800, 500000000, :nanosecond) # => 1999-12-31 23:00:00.5 -0600
- # Time.at(946702800, 500000000, :nsec, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900
- # Time.at(946702800, 500000000, :nanosecond, in: '+09:00') # => 2000-01-01 14:00:00.5 +0900
- #
- # Parameters:
- # :include: doc/time/sec_i.rdoc
- # :include: doc/time/msec.rdoc
- # :include: doc/time/usec.rdoc
- # :include: doc/time/nsec.rdoc
- # :include: doc/time/in.rdoc
- #
- def self.at(time, subsec = (nosubsec = true), unit = (nounit = true), in: nil)
- __builtin.time_s_at(time, subsec, unit, __builtin.arg!(:in), nosubsec, nounit)
+ # Returns a new +Time+ object based on the given arguments.
+ #
+ # Required argument +time+ may be either of:
+ #
+ # - A +Time+ object, whose value is the basis for the returned time;
+ # also influenced by optional keyword argument +in:+ (see below).
+ # - A numeric number of
+ # {Epoch seconds}[rdoc-ref:Time@Epoch+Seconds]
+ # for the returned time.
+ #
+ # Examples:
+ #
+ # t = Time.new(2000, 12, 31, 23, 59, 59) # => 2000-12-31 23:59:59 -0600
+ # secs = t.to_i # => 978328799
+ # Time.at(secs) # => 2000-12-31 23:59:59 -0600
+ # Time.at(secs + 0.5) # => 2000-12-31 23:59:59.5 -0600
+ # Time.at(1000000000) # => 2001-09-08 20:46:40 -0500
+ # Time.at(0) # => 1969-12-31 18:00:00 -0600
+ # Time.at(-1000000000) # => 1938-04-24 17:13:20 -0500
+ #
+ # Optional numeric argument +subsec+ and optional symbol argument +units+
+ # work together to specify subseconds for the returned time;
+ # argument +units+ specifies the units for +subsec+:
+ #
+ # - +:millisecond+: +subsec+ in milliseconds:
+ #
+ # Time.at(secs, 0, :millisecond) # => 2000-12-31 23:59:59 -0600
+ # Time.at(secs, 500, :millisecond) # => 2000-12-31 23:59:59.5 -0600
+ # Time.at(secs, 1000, :millisecond) # => 2001-01-01 00:00:00 -0600
+ # Time.at(secs, -1000, :millisecond) # => 2000-12-31 23:59:58 -0600
+ #
+ # - +:microsecond+ or +:usec+: +subsec+ in microseconds:
+ #
+ # Time.at(secs, 0, :microsecond) # => 2000-12-31 23:59:59 -0600
+ # Time.at(secs, 500000, :microsecond) # => 2000-12-31 23:59:59.5 -0600
+ # Time.at(secs, 1000000, :microsecond) # => 2001-01-01 00:00:00 -0600
+ # Time.at(secs, -1000000, :microsecond) # => 2000-12-31 23:59:58 -0600
+ #
+ # - +:nanosecond+ or +:nsec+: +subsec+ in nanoseconds:
+ #
+ # Time.at(secs, 0, :nanosecond) # => 2000-12-31 23:59:59 -0600
+ # Time.at(secs, 500000000, :nanosecond) # => 2000-12-31 23:59:59.5 -0600
+ # Time.at(secs, 1000000000, :nanosecond) # => 2001-01-01 00:00:00 -0600
+ # Time.at(secs, -1000000000, :nanosecond) # => 2000-12-31 23:59:58 -0600
+ #
+ #
+ # Optional keyword argument <tt>in: zone</tt> specifies the timezone
+ # for the returned time:
+ #
+ # Time.at(secs, in: '+12:00') # => 2001-01-01 17:59:59 +1200
+ # Time.at(secs, in: '-12:00') # => 2000-12-31 17:59:59 -1200
+ #
+ # For the forms of argument +zone+, see
+ # {Timezone Specifiers}[rdoc-ref:Time@Timezone+Specifiers].
+ #
+ def self.at(time, subsec = false, unit = :microsecond, in: nil)
+ if Primitive.mandatory_only?
+ Primitive.time_s_at1(time)
+ else
+ Primitive.time_s_at(time, subsec, unit, Primitive.arg!(:in))
+ end
end
- # Returns a new \Time object based the on given arguments.
+ # call-seq:
+ # Time.new(year = nil, mon = nil, mday = nil, hour = nil, min = nil, sec = nil, zone = nil, in: nil, precision: 9)
+ #
+ # Returns a new +Time+ object based on the given arguments,
+ # by default in the local timezone.
#
# With no positional arguments, returns the value of Time.now:
#
- # Time.new # => 2021-04-24 17:27:46.0512465 -0500
+ # Time.new # => 2021-04-24 17:27:46.0512465 -0500
+ #
+ # With one string argument that represents a time, returns a new
+ # +Time+ object based on the given argument, in the local timezone.
+ #
+ # Time.new('2000-12-31 23:59:59.5') # => 2000-12-31 23:59:59.5 -0600
+ # Time.new('2000-12-31 23:59:59.5 +0900') # => 2000-12-31 23:59:59.5 +0900
+ # Time.new('2000-12-31 23:59:59.5', in: '+0900') # => 2000-12-31 23:59:59.5 +0900
+ # Time.new('2000-12-31 23:59:59.5') # => 2000-12-31 23:59:59.5 -0600
+ # Time.new('2000-12-31 23:59:59.56789', precision: 3) # => 2000-12-31 23:59:59.567 -0600
+ #
+ # With one to six arguments, returns a new +Time+ object
+ # based on the given arguments, in the local timezone.
+ #
+ # Time.new(2000, 1, 2, 3, 4, 5) # => 2000-01-02 03:04:05 -0600
+ #
+ # For the positional arguments (other than +zone+):
+ #
+ # - +year+: Year, with no range limits:
+ #
+ # Time.new(999999999) # => 999999999-01-01 00:00:00 -0600
+ # Time.new(-999999999) # => -999999999-01-01 00:00:00 -0600
+ #
+ # - +month+: Month in range (1..12), or case-insensitive
+ # 3-letter month name:
+ #
+ # Time.new(2000, 1) # => 2000-01-01 00:00:00 -0600
+ # Time.new(2000, 12) # => 2000-12-01 00:00:00 -0600
+ # Time.new(2000, 'jan') # => 2000-01-01 00:00:00 -0600
+ # Time.new(2000, 'JAN') # => 2000-01-01 00:00:00 -0600
+ #
+ # - +mday+: Month day in range(1..31):
+ #
+ # Time.new(2000, 1, 1) # => 2000-01-01 00:00:00 -0600
+ # Time.new(2000, 1, 31) # => 2000-01-31 00:00:00 -0600
+ #
+ # - +hour+: Hour in range (0..23), or 24 if +min+, +sec+, and +usec+
+ # are zero:
#
- # Otherwise, returns a new \Time object based on the given parameters:
+ # Time.new(2000, 1, 1, 0) # => 2000-01-01 00:00:00 -0600
+ # Time.new(2000, 1, 1, 23) # => 2000-01-01 23:00:00 -0600
+ # Time.new(2000, 1, 1, 24) # => 2000-01-02 00:00:00 -0600
#
- # Time.new(2000) # => 2000-01-01 00:00:00 -0600
- # Time.new(2000, 12, 31, 23, 59, 59.5) # => 2000-12-31 23:59:59.5 -0600
- # Time.new(2000, 12, 31, 23, 59, 59.5, '+09:00') # => 2000-12-31 23:59:59.5 +0900
+ # - +min+: Minute in range (0..59):
#
- # Parameters:
+ # Time.new(2000, 1, 1, 0, 0) # => 2000-01-01 00:00:00 -0600
+ # Time.new(2000, 1, 1, 0, 59) # => 2000-01-01 00:59:00 -0600
#
- # :include: doc/time/year.rdoc
- # :include: doc/time/mon-min.rdoc
- # :include: doc/time/sec.rdoc
- # :include: doc/time/zone_and_in.rdoc
+ # - +sec+: Second in range (0...61):
#
- def initialize(year = (now = true), mon = nil, mday = nil, hour = nil, min = nil, sec = nil, zone = nil, in: nil)
+ # Time.new(2000, 1, 1, 0, 0, 0) # => 2000-01-01 00:00:00 -0600
+ # Time.new(2000, 1, 1, 0, 0, 59) # => 2000-01-01 00:00:59 -0600
+ # Time.new(2000, 1, 1, 0, 0, 60) # => 2000-01-01 00:01:00 -0600
+ #
+ # +sec+ may be Float or Rational.
+ #
+ # Time.new(2000, 1, 1, 0, 0, 59.5) # => 2000-12-31 23:59:59.5 +0900
+ # Time.new(2000, 1, 1, 0, 0, 59.7r) # => 2000-12-31 23:59:59.7 +0900
+ #
+ # These values may be:
+ #
+ # - Integers, as above.
+ # - Numerics convertible to integers:
+ #
+ # Time.new(Float(0.0), Rational(1, 1), 1.0, 0.0, 0.0, 0.0)
+ # # => 0000-01-01 00:00:00 -0600
+ #
+ # - String integers:
+ #
+ # a = %w[0 1 1 0 0 0]
+ # # => ["0", "1", "1", "0", "0", "0"]
+ # Time.new(*a) # => 0000-01-01 00:00:00 -0600
+ #
+ # When positional argument +zone+ or keyword argument +in:+ is given,
+ # the new +Time+ object is in the specified timezone.
+ # For the forms of argument +zone+, see
+ # {Timezone Specifiers}[rdoc-ref:Time@Timezone+Specifiers]:
+ #
+ # Time.new(2000, 1, 1, 0, 0, 0, '+12:00')
+ # # => 2000-01-01 00:00:00 +1200
+ # Time.new(2000, 1, 1, 0, 0, 0, in: '-12:00')
+ # # => 2000-01-01 00:00:00 -1200
+ # Time.new(in: '-12:00')
+ # # => 2022-08-23 08:49:26.1941467 -1200
+ #
+ # Since +in:+ keyword argument just provides the default, so if the
+ # first argument in single string form contains time zone information,
+ # this keyword argument will be silently ignored.
+ #
+ # Time.new('2000-01-01 00:00:00 +0100', in: '-0500').utc_offset # => 3600
+ #
+ # - +precision+: maximum effective digits in sub-second part, default is 9.
+ # More digits will be truncated, as other operations of +Time+.
+ # Ignored unless the first argument is a string.
+ #
+ def initialize(year = (now = true), mon = (str = year; nil), mday = nil, hour = nil, min = nil, sec = nil, zone = nil,
+ in: nil, precision: 9)
if zone
- if __builtin.arg!(:in)
+ if Primitive.arg!(:in)
raise ArgumentError, "timezone argument given as positional and keyword arguments"
end
else
- zone = __builtin.arg!(:in)
+ zone = Primitive.arg!(:in)
end
if now
- return __builtin.time_init_now(zone)
+ return Primitive.time_init_now(zone)
+ end
+
+ if str and Primitive.time_init_parse(str, zone, precision)
+ return self
end
- __builtin.time_init_args(year, mon, mday, hour, min, sec, zone)
+ Primitive.time_init_args(year, mon, mday, hour, min, sec, zone)
end
end