summaryrefslogtreecommitdiff
path: root/test/ruby/test_time.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_time.rb')
-rw-r--r--test/ruby/test_time.rb594
1 files changed, 534 insertions, 60 deletions
diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb
index 188ec0da04..333edb8021 100644
--- a/test/ruby/test_time.rb
+++ b/test/ruby/test_time.rb
@@ -1,14 +1,12 @@
+# frozen_string_literal: false
require 'test/unit'
-require 'rational'
require 'delegate'
require 'timeout'
require 'delegate'
-require_relative 'envutil'
class TestTime < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
@@ -39,14 +37,133 @@ class TestTime < Test::Unit::TestCase
end
def test_new
+ assert_equal(Time.new(2000,1,1,0,0,0), Time.new(2000))
+ assert_equal(Time.new(2000,2,1,0,0,0), Time.new("2000", "Feb"))
assert_equal(Time.utc(2000,2,10), Time.new(2000,2,10, 11,0,0, 3600*11))
assert_equal(Time.utc(2000,2,10), Time.new(2000,2,9, 13,0,0, -3600*11))
+ assert_equal(Time.utc(2000,2,29,23,0,0), Time.new(2000, 3, 1, 0, 0, 0, 3600))
assert_equal(Time.utc(2000,2,10), Time.new(2000,2,10, 11,0,0, "+11:00"))
assert_equal(Rational(1,2), Time.new(2000,2,10, 11,0,5.5, "+11:00").subsec)
bug4090 = '[ruby-dev:42631]'
tm = [2001,2,28,23,59,30]
t = Time.new(*tm, "-12:00")
assert_equal([2001,2,28,23,59,30,-43200], [t.year, t.month, t.mday, t.hour, t.min, t.sec, t.gmt_offset], bug4090)
+ assert_raise(ArgumentError) { Time.new(2000,1,1, 0,0,0, "+01:60") }
+ msg = /invalid value for Integer/
+ assert_raise_with_message(ArgumentError, msg) { Time.new(2021, 1, 1, "+09:99") }
+ assert_raise_with_message(ArgumentError, msg) { Time.new(2021, 1, "+09:99") }
+ assert_raise_with_message(ArgumentError, msg) { Time.new(2021, "+09:99") }
+
+ assert_equal([0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], Time.new(2000, 1, 1, 0, 0, 0, "-00:00").to_a)
+ assert_equal([0, 0, 0, 2, 1, 2000, 0, 2, false, "UTC"], Time.new(2000, 1, 1, 24, 0, 0, "-00:00").to_a)
+ end
+
+ def test_new_from_string
+ assert_raise(ArgumentError) { Time.new(2021, 1, 1, "+09:99") }
+
+ t = Time.utc(2020, 12, 24, 15, 56, 17)
+ assert_equal(t, Time.new("2020-12-24T15:56:17Z"))
+ assert_equal(t, Time.new("2020-12-25 00:56:17 +09:00"))
+ assert_equal(t, Time.new("2020-12-25 00:57:47 +09:01:30"))
+ assert_equal(t, Time.new("2020-12-25 00:56:17 +0900"))
+ assert_equal(t, Time.new("2020-12-25 00:57:47 +090130"))
+ assert_equal(t, Time.new("2020-12-25T00:56:17+09:00"))
+ assert_raise_with_message(ArgumentError, /missing sec part/) {
+ Time.new("2020-12-25 00:56 +09:00")
+ }
+ assert_raise_with_message(ArgumentError, /missing min part/) {
+ Time.new("2020-12-25 00 +09:00")
+ }
+
+ assert_equal(Time.new(2021), Time.new("2021"))
+ assert_equal(Time.new(2021, 12, 25, in: "+09:00"), Time.new("2021-12-25+09:00"))
+ assert_equal(Time.new(2021, 12, 25, in: "+09:00"), Time.new("2021-12-25+09:00", in: "-01:00"))
+
+ assert_equal(0.123456r, Time.new("2021-12-25 00:00:00.123456 +09:00").subsec)
+ assert_equal(0.123456789r, Time.new("2021-12-25 00:00:00.123456789876 +09:00").subsec)
+ assert_equal(0.123r, Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 3).subsec)
+ assert_equal(0.123456789876r, Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: nil).subsec)
+ assert_raise_with_message(ArgumentError, "subsecond expected after dot: 00:56:17. ") {
+ Time.new("2020-12-25 00:56:17. +0900")
+ }
+ assert_raise_with_message(ArgumentError, /year must be 4 or more/) {
+ Time.new("021-12-25 00:00:00.123456 +09:00")
+ }
+ assert_raise_with_message(ArgumentError, /fraction min is.*56\./) {
+ Time.new("2020-12-25 00:56. +0900")
+ }
+ assert_raise_with_message(ArgumentError, /fraction hour is.*00\./) {
+ Time.new("2020-12-25 00. +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits sec.*:017\b/) {
+ Time.new("2020-12-25 00:56:017 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits sec.*:9\b/) {
+ Time.new("2020-12-25 00:56:9 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /sec out of range/) {
+ Time.new("2020-12-25 00:56:64 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits min.*:056\b/) {
+ Time.new("2020-12-25 00:056:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits min.*:5\b/) {
+ Time.new("2020-12-25 00:5:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /min out of range/) {
+ Time.new("2020-12-25 00:64:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits hour.*\b000\b/) {
+ Time.new("2020-12-25 000:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits hour.*\b0\b/) {
+ Time.new("2020-12-25 0:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /hour out of range/) {
+ Time.new("2020-12-25 33:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits mday.*\b025\b/) {
+ Time.new("2020-12-025 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits mday.*\b5\b/) {
+ Time.new("2020-12-5 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /mday out of range/) {
+ Time.new("2020-12-33 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits mon.*\b012\b/) {
+ Time.new("2020-012-25 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits mon.*\b1\b/) {
+ Time.new("2020-1-25 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /mon out of range/) {
+ Time.new("2020-17-25 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /no time information/) {
+ Time.new("2020-12")
+ }
+ assert_raise_with_message(ArgumentError, /no time information/) {
+ Time.new("2020-12-02")
+ }
+ assert_raise_with_message(ArgumentError, /can't parse/) {
+ Time.new(" 2020-12-02 00:00:00")
+ }
+ assert_raise_with_message(ArgumentError, /can't parse/) {
+ Time.new("2020-12-02 00:00:00 ")
+ }
+ assert_raise_with_message(ArgumentError, /utc_offset/) {
+ Time.new("2020-12-25 00:00:00 +0960")
+ }
+ assert_raise_with_message(ArgumentError, /utc_offset/) {
+ Time.new("2020-12-25 00:00:00 +09:60")
+ }
+ assert_raise_with_message(ArgumentError, /utc_offset/) {
+ Time.new("2020-12-25 00:00:00 +090060")
+ }
+ assert_raise_with_message(ArgumentError, /utc_offset/) {
+ Time.new("2020-12-25 00:00:00 +09:00:60")
+ }
end
def test_time_add()
@@ -56,14 +173,14 @@ class TestTime < Test::Unit::TestCase
Time.utc(2000, 3, 21, 0, 30))
assert_equal(0, (Time.at(1.1) + 0.9).usec)
- assert((Time.utc(2000, 4, 1) + 24).utc?)
- assert(!(Time.local(2000, 4, 1) + 24).utc?)
+ assert_predicate((Time.utc(2000, 4, 1) + 24), :utc?)
+ assert_not_predicate((Time.local(2000, 4, 1) + 24), :utc?)
t = Time.new(2000, 4, 1, 0, 0, 0, "+01:00") + 24
- assert(!t.utc?)
+ assert_not_predicate(t, :utc?)
assert_equal(3600, t.utc_offset)
t = Time.new(2000, 4, 1, 0, 0, 0, "+02:00") + 24
- assert(!t.utc?)
+ assert_not_predicate(t, :utc?)
assert_equal(7200, t.utc_offset)
end
@@ -108,6 +225,10 @@ class TestTime < Test::Unit::TestCase
assert_equal(78796800, Time.utc(1972, 7, 1, 0, 0, 0).tv_sec)
assert_equal(78796801, Time.utc(1972, 7, 1, 0, 0, 1).tv_sec)
assert_equal(946684800, Time.utc(2000, 1, 1, 0, 0, 0).tv_sec)
+
+ # Giveup to try 2nd test because some state is changed.
+ omit if Test::Unit::Runner.current_repeat_count > 0
+
assert_equal(0x7fffffff, Time.utc(2038, 1, 19, 3, 14, 7).tv_sec)
assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec)
else
@@ -172,7 +293,8 @@ class TestTime < Test::Unit::TestCase
assert_equal(100000, Time.at(0.0001).nsec)
assert_equal(10000, Time.at(0.00001).nsec)
assert_equal(3000, Time.at(0.000003).nsec)
- assert_equal(199, Time.at(0.0000002).nsec)
+ assert_equal(200, Time.at(0.0000002r).nsec)
+ assert_in_delta(200, Time.at(0.0000002).nsec, 1, "should be within FP error")
assert_equal(10, Time.at(0.00000001).nsec)
assert_equal(1, Time.at(0.000000001).nsec)
@@ -235,6 +357,21 @@ class TestTime < Test::Unit::TestCase
assert_equal(1, Time.at(0, 0.001).nsec)
end
+ def test_at_splat
+ assert_equal(Time.at(1, 2), Time.at(*[1, 2]))
+ end
+
+ def test_at_with_unit
+ assert_equal(123456789, Time.at(0, 123456789, :nanosecond).nsec)
+ assert_equal(123456789, Time.at(0, 123456789, :nsec).nsec)
+ assert_equal(123456000, Time.at(0, 123456, :microsecond).nsec)
+ assert_equal(123456000, Time.at(0, 123456, :usec).nsec)
+ assert_equal(123000000, Time.at(0, 123, :millisecond).nsec)
+ assert_raise(ArgumentError){ Time.at(0, 1, 2) }
+ assert_raise(ArgumentError){ Time.at(0, 1, :invalid) }
+ assert_raise(ArgumentError){ Time.at(0, 1, nil) }
+ end
+
def test_at_rational
assert_equal(1, Time.at(Rational(1,1) / 1000000000).nsec)
assert_equal(1, Time.at(1167609600 + Rational(1,1) / 1000000000).nsec)
@@ -307,12 +444,14 @@ class TestTime < Test::Unit::TestCase
in_timezone('JST-9') do
t = Time.local(2013, 2, 24)
assert_equal('JST', Time.local(2013, 2, 24).zone)
- assert_equal('JST', Marshal.load(Marshal.dump(t)).zone)
+ t = Marshal.load(Marshal.dump(t))
+ assert_equal('JST', t.zone)
+ assert_equal('JST', (t+1).zone, '[ruby-core:81892] [Bug #13710]')
end
end
def test_marshal_zone_gc
- assert_separately(%w(--disable-gems), <<-'end;', timeout: 30)
+ assert_separately([], <<-'end;', timeout: 30)
ENV["TZ"] = "JST-9"
s = Marshal.dump(Time.now)
t = Marshal.load(s)
@@ -333,16 +472,6 @@ class TestTime < Test::Unit::TestCase
"[ruby-dev:44827] [Bug #5586]")
end
- def test_security_error
- assert_raise(SecurityError) do
- Thread.new do
- t = Time.gm(2000)
- $SAFE = 4
- t.localtime
- end.join
- end
- end
-
Bug8795 = '[ruby-core:56648] [Bug #8795]'
def test_marshal_broken_offset
@@ -371,6 +500,21 @@ class TestTime < Test::Unit::TestCase
end
end
+ def test_marshal_broken_month
+ data = "\x04\x08u:\tTime\r\x20\x7c\x1e\xc0\x00\x00\x00\x00"
+ assert_equal(Time.utc(2022, 4, 1), Marshal.load(data))
+ end
+
+ def test_marshal_distant_past
+ assert_marshal_roundtrip(Time.utc(1890, 1, 1))
+ assert_marshal_roundtrip(Time.utc(-4.5e9, 1, 1))
+ end
+
+ def test_marshal_distant_future
+ assert_marshal_roundtrip(Time.utc(30000, 1, 1))
+ assert_marshal_roundtrip(Time.utc(5.67e9, 4, 8))
+ end
+
def test_at3
t2000 = get_t2000
assert_equal(t2000, Time.at(t2000))
@@ -403,8 +547,10 @@ class TestTime < Test::Unit::TestCase
def o.to_int; 0; end
def o.to_r; nil; end
assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) }
+ class << o; remove_method(:to_r); end
def o.to_r; ""; end
assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) }
+ class << o; remove_method(:to_r); end
def o.to_r; Rational(11); end
assert_equal(11, Time.gm(2000, 1, 1, 0, 0, o).sec)
o = Object.new
@@ -417,16 +563,25 @@ class TestTime < Test::Unit::TestCase
assert_equal(-4427700000, Time.utc(-4427700000,12,1).year)
assert_equal(-2**30+10, Time.utc(-2**30+10,1,1).year)
+
+ assert_raise(ArgumentError) { Time.gm(2000, 1, -1) }
+ assert_raise(ArgumentError) { Time.gm(2000, 1, 2**30 + 1) }
+ assert_raise(ArgumentError) { Time.gm(2000, 1, -2**30 + 1) }
end
def test_time_interval
- m = Mutex.new.lock
+ m = Thread::Mutex.new.lock
assert_nothing_raised {
Timeout.timeout(10) {
m.sleep(0)
}
}
assert_raise(ArgumentError) { m.sleep(-1) }
+ assert_raise(TypeError) { m.sleep("") }
+ assert_raise(TypeError) { sleep("") }
+ obj = eval("class C\u{1f5ff}; self; end").new
+ assert_raise_with_message(TypeError, /C\u{1f5ff}/) {m.sleep(obj)}
+ assert_raise_with_message(TypeError, /C\u{1f5ff}/) {sleep(obj)}
end
def test_to_f
@@ -434,6 +589,12 @@ class TestTime < Test::Unit::TestCase
assert_equal(946684800.0, t2000.to_f)
end
+ def test_to_f_accuracy
+ # https://bugs.ruby-lang.org/issues/10135#note-1
+ f = 1381089302.195
+ assert_equal(f, Time.at(f).to_f, "[ruby-core:64373] [Bug #10135] note-1")
+ end
+
def test_cmp
t2000 = get_t2000
assert_equal(-1, t2000 <=> Time.gm(2001))
@@ -443,14 +604,14 @@ class TestTime < Test::Unit::TestCase
def test_eql
t2000 = get_t2000
- assert(t2000.eql?(t2000))
- assert(!t2000.eql?(Time.gm(2001)))
+ assert_operator(t2000, :eql?, t2000)
+ assert_not_operator(t2000, :eql?, Time.gm(2001))
end
def test_utc_p
- assert(Time.gm(2000).gmt?)
- assert(!Time.local(2000).gmt?)
- assert(!Time.at(0).gmt?)
+ assert_predicate(Time.gm(2000), :gmt?)
+ assert_not_predicate(Time.local(2000), :gmt?)
+ assert_not_predicate(Time.at(0), :gmt?)
end
def test_hash
@@ -478,15 +639,15 @@ class TestTime < Test::Unit::TestCase
def test_localtime_gmtime
assert_nothing_raised do
t = Time.gm(2000)
- assert(t.gmt?)
+ assert_predicate(t, :gmt?)
t.localtime
- assert(!t.gmt?)
+ assert_not_predicate(t, :gmt?)
t.localtime
- assert(!t.gmt?)
+ assert_not_predicate(t, :gmt?)
t.gmtime
- assert(t.gmt?)
+ assert_predicate(t, :gmt?)
t.gmtime
- assert(t.gmt?)
+ assert_predicate(t, :gmt?)
end
t1 = Time.gm(2000)
@@ -495,6 +656,7 @@ class TestTime < Test::Unit::TestCase
t3 = t1.getlocal("-02:00")
assert_equal(t1, t3)
assert_equal(-7200, t3.utc_offset)
+ assert_equal([1999, 12, 31, 22, 0, 0], [t3.year, t3.mon, t3.mday, t3.hour, t3.min, t3.sec])
t1.localtime
assert_equal(t1, t2)
assert_equal(t1.gmt?, t2.gmt?)
@@ -527,17 +689,59 @@ class TestTime < Test::Unit::TestCase
assert_equal(Time.at(946684800).getlocal.to_s, Time.at(946684800).to_s)
end
+ def test_inspect
+ t2000 = get_t2000
+ assert_equal("2000-01-01 00:00:00 UTC", t2000.inspect)
+ assert_equal(Encoding::US_ASCII, t2000.inspect.encoding)
+ assert_kind_of(String, Time.at(946684800).getlocal.inspect)
+ assert_equal(Time.at(946684800).getlocal.inspect, Time.at(946684800).inspect)
+
+ t2000 = get_t2000 + 1/10r
+ assert_equal("2000-01-01 00:00:00.1 UTC", t2000.inspect)
+ t2000 = get_t2000 + 1/1000000000r
+ assert_equal("2000-01-01 00:00:00.000000001 UTC", t2000.inspect)
+ t2000 = get_t2000 + 1/10000000000r
+ assert_equal("2000-01-01 00:00:00 1/10000000000 UTC", t2000.inspect)
+ t2000 = get_t2000 + 0.1
+ assert_equal("2000-01-01 00:00:00 3602879701896397/36028797018963968 UTC", t2000.inspect)
+
+ t2000 = get_t2000
+ t2000 = t2000.localtime(9*3600)
+ assert_equal("2000-01-01 09:00:00 +0900", t2000.inspect)
+
+ t2000 = get_t2000.localtime(9*3600) + 1/10r
+ assert_equal("2000-01-01 09:00:00.1 +0900", t2000.inspect)
+
+ t2000 = get_t2000
+ assert_equal("2000-01-01 09:12:00 +0912", t2000.localtime(9*3600+12*60).inspect)
+ assert_equal("2000-01-01 09:12:34 +091234", t2000.localtime(9*3600+12*60+34).inspect)
+ end
+
+ def assert_zone_encoding(time)
+ zone = time.zone
+ assert_predicate(zone, :valid_encoding?)
+ if zone.ascii_only?
+ assert_equal(Encoding::US_ASCII, zone.encoding)
+ else
+ enc = Encoding.default_internal || Encoding.find('locale')
+ assert_equal(enc, zone.encoding)
+ end
+ end
+
def test_zone
- assert_equal(Encoding.find('locale'), Time.now.zone.encoding)
+ assert_zone_encoding Time.now
+ t = Time.now.utc
+ assert_equal("UTC", t.zone)
+ assert_nil(t.getlocal(0).zone)
+ assert_nil(t.getlocal("+02:00").zone)
end
- def test_plus_minus_succ
+ def test_plus_minus
t2000 = get_t2000
# assert_raise(RangeError) { t2000 + 10000000000 }
# assert_raise(RangeError) t2000 - 3094168449 }
# assert_raise(RangeError) { t2000 + 1200798848 }
assert_raise(TypeError) { t2000 + Time.now }
- assert_equal(t2000 + 1, t2000.succ)
end
def test_plus_type
@@ -577,15 +781,15 @@ class TestTime < Test::Unit::TestCase
assert_equal(1, t2000.yday)
assert_equal(false, t2000.isdst)
assert_equal("UTC", t2000.zone)
- assert_equal(Encoding.find("locale"), t2000.zone.encoding)
+ assert_zone_encoding(t2000)
assert_equal(0, t2000.gmt_offset)
- assert(!t2000.sunday?)
- assert(!t2000.monday?)
- assert(!t2000.tuesday?)
- assert(!t2000.wednesday?)
- assert(!t2000.thursday?)
- assert(!t2000.friday?)
- assert(t2000.saturday?)
+ assert_not_predicate(t2000, :sunday?)
+ assert_not_predicate(t2000, :monday?)
+ assert_not_predicate(t2000, :tuesday?)
+ assert_not_predicate(t2000, :wednesday?)
+ assert_not_predicate(t2000, :thursday?)
+ assert_not_predicate(t2000, :friday?)
+ assert_predicate(t2000, :saturday?)
assert_equal([0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], t2000.to_a)
t = Time.at(946684800).getlocal
@@ -599,7 +803,7 @@ class TestTime < Test::Unit::TestCase
assert_equal(t.yday, Time.at(946684800).yday)
assert_equal(t.isdst, Time.at(946684800).isdst)
assert_equal(t.zone, Time.at(946684800).zone)
- assert_equal(Encoding.find("locale"), Time.at(946684800).zone.encoding)
+ assert_zone_encoding(Time.at(946684800))
assert_equal(t.gmt_offset, Time.at(946684800).gmt_offset)
assert_equal(t.sunday?, Time.at(946684800).sunday?)
assert_equal(t.monday?, Time.at(946684800).monday?)
@@ -637,8 +841,12 @@ class TestTime < Test::Unit::TestCase
assert_equal("UTC", t2000.strftime("%Z"))
assert_equal("%", t2000.strftime("%%"))
assert_equal("0", t2000.strftime("%-S"))
+ assert_equal("12:00:00 AM", t2000.strftime("%r"))
+ assert_equal("Sat 2000-01-01T00:00:00", t2000.strftime("%3a %FT%T"))
- assert_equal("", t2000.strftime(""))
+ assert_warning(/strftime called with empty format string/) do
+ assert_equal("", t2000.strftime(""))
+ end
assert_equal("foo\0bar\x0000\x0000\x0000", t2000.strftime("foo\0bar\0%H\0%M\0%S"))
assert_equal("foo" * 1000, t2000.strftime("foo" * 1000))
@@ -664,6 +872,12 @@ class TestTime < Test::Unit::TestCase
t = Time.at(946684800, 123456.789)
assert_equal("946684800", t.strftime("%s"))
assert_equal("946684800", t.utc.strftime("%s"))
+
+ t = Time.at(10000000000000000000000)
+ assert_equal("<<10000000000000000000000>>", t.strftime("<<%s>>"))
+ assert_equal("<<010000000000000000000000>>", t.strftime("<<%24s>>"))
+ assert_equal("<<010000000000000000000000>>", t.strftime("<<%024s>>"))
+ assert_equal("<< 10000000000000000000000>>", t.strftime("<<%_24s>>"))
end
def test_strftime_zone
@@ -714,6 +928,13 @@ class TestTime < Test::Unit::TestCase
assert_equal(" 2", t.strftime("%l"))
assert_equal("02", t.strftime("%0l"))
assert_equal(" 2", t.strftime("%_l"))
+ assert_equal("MON", t.strftime("%^a"))
+ assert_equal("OCT", t.strftime("%^b"))
+
+ t = get_t2000
+ assert_equal("UTC", t.strftime("%^Z"))
+ assert_equal("utc", t.strftime("%#Z"))
+ assert_equal("SAT JAN 1 00:00:00 2000", t.strftime("%^c"))
end
def test_strftime_invalid_flags
@@ -733,6 +954,12 @@ class TestTime < Test::Unit::TestCase
t = Time.utc(-1,1,4)
assert_equal("-0001", t.strftime("%Y"))
assert_equal("-0001", t.strftime("%G"))
+
+ t = Time.utc(10000000000000000000000,1,1)
+ assert_equal("<<10000000000000000000000>>", t.strftime("<<%Y>>"))
+ assert_equal("<<010000000000000000000000>>", t.strftime("<<%24Y>>"))
+ assert_equal("<<010000000000000000000000>>", t.strftime("<<%024Y>>"))
+ assert_equal("<< 10000000000000000000000>>", t.strftime("<<%_24Y>>"))
end
def test_strftime_weeknum
@@ -796,8 +1023,14 @@ class TestTime < Test::Unit::TestCase
end
def test_strftime_too_wide
- bug4457 = '[ruby-dev:43285]'
- assert_raise(Errno::ERANGE, bug4457) {Time.now.strftime('%8192z')}
+ assert_equal(8192, Time.now.strftime('%8192z').size)
+ end
+
+ def test_strftime_wide_precision
+ t2000 = get_t2000
+ s = t2000.strftime("%28c")
+ assert_equal(28, s.size)
+ assert_equal(t2000.strftime("%c"), s.strip)
end
def test_strfimte_zoneoffset
@@ -813,6 +1046,17 @@ class TestTime < Test::Unit::TestCase
assert_equal("+09:00", t.strftime("%:z"))
assert_equal("+09:00:01", t.strftime("%::z"))
assert_equal("+09:00:01", t.strftime("%:::z"))
+
+ assert_equal("+0000", t2000.strftime("%z"))
+ assert_equal("-0000", t2000.strftime("%-z"))
+ assert_equal("-00:00", t2000.strftime("%-:z"))
+ assert_equal("-00:00:00", t2000.strftime("%-::z"))
+
+ t = t2000.getlocal("+00:00")
+ assert_equal("+0000", t.strftime("%z"))
+ assert_equal("+0000", t.strftime("%-z"))
+ assert_equal("+00:00", t.strftime("%-:z"))
+ assert_equal("+00:00:00", t.strftime("%-::z"))
end
def test_strftime_padding
@@ -919,6 +1163,63 @@ class TestTime < Test::Unit::TestCase
}
end
+ def test_floor
+ t = Time.utc(1999,12,31, 23,59,59)
+ t2 = (t+0.4).floor
+ assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+ t2 = (t+0.49).floor
+ assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+ t2 = (t+0.5).floor
+ assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+ t2 = (t+1.4).floor
+ assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+ t2 = (t+1.49).floor
+ assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+ t2 = (t+1.5).floor
+ assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+
+ t2 = (t+0.123456789).floor(4)
+ assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a)
+ assert_equal(Rational(1234,10000), t2.subsec)
+ end
+
+ def test_ceil
+ t = Time.utc(1999,12,31, 23,59,59)
+ t2 = (t+0.4).ceil
+ assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+ t2 = (t+0.49).ceil
+ assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+ t2 = (t+0.5).ceil
+ assert_equal([0,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+ t2 = (t+1.4).ceil
+ assert_equal([1,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+ t2 = (t+1.49).ceil
+ assert_equal([1,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+ t2 = (t+1.5).ceil
+ assert_equal([1,0,0, 1,1,2000, 6,1,false,"UTC"], t2.to_a)
+ assert_equal(0, t2.subsec)
+
+ t2 = (t+0.123456789).ceil(4)
+ assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a)
+ assert_equal(Rational(1235,10000), t2.subsec)
+
+ time = Time.utc(2016, 4, 23, 0, 0, 0.123456789r)
+ assert_equal(time, time.ceil(9))
+ assert_equal(time, time.ceil(10))
+ assert_equal(time, time.ceil(11))
+ end
+
def test_getlocal_dont_share_eigenclass
bug5012 = "[ruby-dev:44071]"
@@ -933,20 +1234,6 @@ class TestTime < Test::Unit::TestCase
assert_raise(NoMethodError, bug5012) { t1.m }
end
- def test_time_subclass
- bug5036 = '[ruby-dev:44122]'
- tc = Class.new(Time)
- tc.inspect
- t = tc.now
- error = assert_raise(SecurityError) do
- proc do
- $SAFE = 4
- t.gmtime
- end.call
- end
- assert_equal("Insecure: can't modify #{tc}", error.message, bug5036)
- end
-
def test_sec_str
bug6193 = '[ruby-core:43569]'
t = nil
@@ -1006,6 +1293,9 @@ class TestTime < Test::Unit::TestCase
end
def test_2038
+ # Giveup to try 2nd test because some state is changed.
+ omit if Test::Unit::Runner.current_repeat_count > 0
+
if no_leap_seconds?
assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec)
end
@@ -1023,6 +1313,29 @@ class TestTime < Test::Unit::TestCase
assert_equal(min, t.min)
assert_equal(sec, t.sec)
}
+ assert_equal(Time.local(2038,3,1), Time.local(2038,2,29))
+ assert_equal(Time.local(2038,3,2), Time.local(2038,2,30))
+ assert_equal(Time.local(2038,3,3), Time.local(2038,2,31))
+ assert_equal(Time.local(2040,2,29), Time.local(2040,2,29))
+ assert_equal(Time.local(2040,3,1), Time.local(2040,2,30))
+ assert_equal(Time.local(2040,3,2), Time.local(2040,2,31))
+ n = 2 ** 64
+ n += 400 - n % 400 # n is over 2^64 and multiple of 400
+ assert_equal(Time.local(n,2,29),Time.local(n,2,29))
+ assert_equal(Time.local(n,3,1), Time.local(n,2,30))
+ assert_equal(Time.local(n,3,2), Time.local(n,2,31))
+ n += 100
+ assert_equal(Time.local(n,3,1), Time.local(n,2,29))
+ assert_equal(Time.local(n,3,2), Time.local(n,2,30))
+ assert_equal(Time.local(n,3,3), Time.local(n,2,31))
+ n += 4
+ assert_equal(Time.local(n,2,29),Time.local(n,2,29))
+ assert_equal(Time.local(n,3,1), Time.local(n,2,30))
+ assert_equal(Time.local(n,3,2), Time.local(n,2,31))
+ n += 1
+ assert_equal(Time.local(n,3,1), Time.local(n,2,29))
+ assert_equal(Time.local(n,3,2), Time.local(n,2,30))
+ assert_equal(Time.local(n,3,3), Time.local(n,2,31))
end
def test_future
@@ -1041,4 +1354,165 @@ class TestTime < Test::Unit::TestCase
}
end
+ def test_getlocal_utc
+ t = Time.gm(2000)
+ assert_equal [00, 00, 00, 1, 1, 2000], (t1 = t.getlocal("UTC")).to_a[0, 6]
+ assert_predicate t1, :utc?
+ assert_equal [00, 00, 00, 1, 1, 2000], (t1 = t.getlocal("-0000")).to_a[0, 6]
+ assert_predicate t1, :utc?
+ assert_equal [00, 00, 00, 1, 1, 2000], (t1 = t.getlocal("+0000")).to_a[0, 6]
+ assert_not_predicate t1, :utc?
+ end
+
+ def test_getlocal_utc_offset
+ t = Time.gm(2000)
+ assert_equal [00, 30, 21, 31, 12, 1999], t.getlocal("-02:30").to_a[0, 6]
+ assert_equal [00, 00, 9, 1, 1, 2000], t.getlocal("+09:00").to_a[0, 6]
+ assert_equal [20, 29, 21, 31, 12, 1999], t.getlocal("-02:30:40").to_a[0, 6]
+ assert_equal [35, 10, 9, 1, 1, 2000], t.getlocal("+09:10:35").to_a[0, 6]
+ assert_equal [00, 30, 21, 31, 12, 1999], t.getlocal("-0230").to_a[0, 6]
+ assert_equal [00, 00, 9, 1, 1, 2000], t.getlocal("+0900").to_a[0, 6]
+ assert_equal [20, 29, 21, 31, 12, 1999], t.getlocal("-023040").to_a[0, 6]
+ assert_equal [35, 10, 9, 1, 1, 2000], t.getlocal("+091035").to_a[0, 6]
+ assert_raise(ArgumentError) {t.getlocal("-02:3040")}
+ assert_raise(ArgumentError) {t.getlocal("+0910:35")}
+ end
+
+ def test_getlocal_nil
+ now = Time.now
+ now2 = nil
+ now3 = nil
+ assert_nothing_raised {
+ now2 = now.getlocal
+ now3 = now.getlocal(nil)
+ }
+ assert_equal now2, now3
+ assert_equal now2.zone, now3.zone
+ end
+
+ def test_strftime_yearday_on_last_day_of_year
+ t = Time.utc(2015, 12, 31, 0, 0, 0)
+ assert_equal("365", t.strftime("%j"))
+ t = Time.utc(2016, 12, 31, 0, 0, 0)
+ assert_equal("366", t.strftime("%j"))
+
+ t = Time.utc(2015, 12, 30, 20, 0, 0).getlocal("+05:00")
+ assert_equal("365", t.strftime("%j"))
+ t = Time.utc(2016, 12, 30, 20, 0, 0).getlocal("+05:00")
+ assert_equal("366", t.strftime("%j"))
+
+ t = Time.utc(2016, 1, 1, 1, 0, 0).getlocal("-05:00")
+ assert_equal("365", t.strftime("%j"))
+ t = Time.utc(2017, 1, 1, 1, 0, 0).getlocal("-05:00")
+ assert_equal("366", t.strftime("%j"))
+ end
+
+ def test_num_exact_error
+ bad = EnvUtil.labeled_class("BadValue").new
+ x = EnvUtil.labeled_class("Inexact") do
+ def to_s; "Inexact"; end
+ define_method(:to_int) {bad}
+ define_method(:to_r) {bad}
+ end.new
+ assert_raise_with_message(TypeError, /Inexact/) {Time.at(x)}
+ end
+
+ def test_memsize
+ # Time objects are common in some code, try to keep them small
+ omit "Time object size test" if /^(?:i.?86|x86_64)-linux/ !~ RUBY_PLATFORM
+ omit "GC is in debug" if GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD] > 0
+ omit "memsize is not accurate due to using malloc_usable_size" if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+ omit "Only run this test on 64-bit" if RbConfig::SIZEOF["void*"] != 8
+
+ require 'objspace'
+ t = Time.at(0)
+ sizeof_timew =
+ if RbConfig::SIZEOF.key?("uint64_t") && RbConfig::SIZEOF["long"] * 2 <= RbConfig::SIZEOF["uint64_t"]
+ RbConfig::SIZEOF["uint64_t"]
+ else
+ RbConfig::SIZEOF["void*"] # Same size as VALUE
+ end
+ sizeof_vtm = RbConfig::SIZEOF["void*"] * 4 + 8
+ expect = GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] + sizeof_timew + sizeof_vtm
+ assert_operator ObjectSpace.memsize_of(t), :<=, expect
+ rescue LoadError => e
+ omit "failed to load objspace: #{e.message}"
+ end
+
+ def test_deconstruct_keys
+ t = in_timezone('JST-9') { Time.local(2022, 10, 16, 14, 1, 30, 500) }
+ assert_equal(
+ {year: 2022, month: 10, day: 16, wday: 0, yday: 289,
+ hour: 14, min: 1, sec: 30, subsec: 1/2000r, dst: false, zone: 'JST'},
+ t.deconstruct_keys(nil)
+ )
+
+ assert_equal(
+ {year: 2022, month: 10, sec: 30},
+ t.deconstruct_keys(%i[year month sec nonexistent])
+ )
+ end
+
+ def test_parse_zero_bigint
+ assert_equal 0, Time.new("2020-10-28T16:48:07.000Z").nsec, '[Bug #19390]'
+ end
+
+ def test_xmlschema_encode
+ [:xmlschema, :iso8601].each do |method|
+ bug6100 = '[ruby-core:42997]'
+
+ t = Time.utc(2001, 4, 17, 19, 23, 17, 300000)
+ assert_equal("2001-04-17T19:23:17Z", t.__send__(method))
+ assert_equal("2001-04-17T19:23:17.3Z", t.__send__(method, 1))
+ assert_equal("2001-04-17T19:23:17.300000Z", t.__send__(method, 6))
+ assert_equal("2001-04-17T19:23:17.3000000Z", t.__send__(method, 7))
+ assert_equal("2001-04-17T19:23:17.3Z", t.__send__(method, 1.9), bug6100)
+
+ t = Time.utc(2001, 4, 17, 19, 23, 17, 123456)
+ assert_equal("2001-04-17T19:23:17.1234560Z", t.__send__(method, 7))
+ assert_equal("2001-04-17T19:23:17.123456Z", t.__send__(method, 6))
+ assert_equal("2001-04-17T19:23:17.12345Z", t.__send__(method, 5))
+ assert_equal("2001-04-17T19:23:17.1Z", t.__send__(method, 1))
+ assert_equal("2001-04-17T19:23:17.1Z", t.__send__(method, 1.9), bug6100)
+
+ t = Time.at(2.quo(3)).getlocal("+09:00")
+ assert_equal("1970-01-01T09:00:00.666+09:00", t.__send__(method, 3))
+ assert_equal("1970-01-01T09:00:00.6666666666+09:00", t.__send__(method, 10))
+ assert_equal("1970-01-01T09:00:00.66666666666666666666+09:00", t.__send__(method, 20))
+ assert_equal("1970-01-01T09:00:00.6+09:00", t.__send__(method, 1.1), bug6100)
+ assert_equal("1970-01-01T09:00:00.666+09:00", t.__send__(method, 3.2), bug6100)
+
+ t = Time.at(123456789.quo(9999999999)).getlocal("+09:00")
+ assert_equal("1970-01-01T09:00:00.012+09:00", t.__send__(method, 3))
+ assert_equal("1970-01-01T09:00:00.012345678+09:00", t.__send__(method, 9))
+ assert_equal("1970-01-01T09:00:00.0123456789+09:00", t.__send__(method, 10))
+ assert_equal("1970-01-01T09:00:00.0123456789012345678+09:00", t.__send__(method, 19))
+ assert_equal("1970-01-01T09:00:00.01234567890123456789+09:00", t.__send__(method, 20))
+ assert_equal("1970-01-01T09:00:00.012+09:00", t.__send__(method, 3.8), bug6100)
+
+ t = Time.utc(1)
+ assert_equal("0001-01-01T00:00:00Z", t.__send__(method))
+
+ begin
+ Time.at(-1)
+ rescue ArgumentError
+ # ignore
+ else
+ t = Time.utc(1960, 12, 31, 23, 0, 0, 123456)
+ assert_equal("1960-12-31T23:00:00.123456Z", t.__send__(method, 6))
+ end
+
+ t = get_t2000.getlocal("-09:30") # Pacific/Marquesas
+ assert_equal("1999-12-31T14:30:00-09:30", t.__send__(method))
+
+ assert_equal("10000-01-01T00:00:00Z", Time.utc(10000).__send__(method))
+ assert_equal("9999-01-01T00:00:00Z", Time.utc(9999).__send__(method))
+ assert_equal("0001-01-01T00:00:00Z", Time.utc(1).__send__(method)) # 1 AD
+ assert_equal("0000-01-01T00:00:00Z", Time.utc(0).__send__(method)) # 1 BC
+ assert_equal("-0001-01-01T00:00:00Z", Time.utc(-1).__send__(method)) # 2 BC
+ assert_equal("-0004-01-01T00:00:00Z", Time.utc(-4).__send__(method)) # 5 BC
+ assert_equal("-9999-01-01T00:00:00Z", Time.utc(-9999).__send__(method))
+ assert_equal("-10000-01-01T00:00:00Z", Time.utc(-10000).__send__(method))
+ end
+ end
end