summaryrefslogtreecommitdiff
path: root/spec/ruby/core/time/new_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/time/new_spec.rb')
-rw-r--r--spec/ruby/core/time/new_spec.rb343
1 files changed, 327 insertions, 16 deletions
diff --git a/spec/ruby/core/time/new_spec.rb b/spec/ruby/core/time/new_spec.rb
index 09b4d03a44..d686355270 100644
--- a/spec/ruby/core/time/new_spec.rb
+++ b/spec/ruby/core/time/new_spec.rb
@@ -58,6 +58,32 @@ describe "Time.new with a utc_offset argument" do
Time.new(2000, 1, 1, 0, 0, 0, "-04:10:43").utc_offset.should == -15043
end
+ ruby_bug '#13669', ''...'3.1' do
+ it "returns a Time with a UTC offset specified as +HH" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+05").utc_offset.should == 3600 * 5
+ end
+
+ it "returns a Time with a UTC offset specified as -HH" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-05").utc_offset.should == -3600 * 5
+ end
+
+ it "returns a Time with a UTC offset specified as +HHMM" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+0530").utc_offset.should == 19800
+ end
+
+ it "returns a Time with a UTC offset specified as -HHMM" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-0530").utc_offset.should == -19800
+ end
+
+ it "returns a Time with a UTC offset specified as +HHMMSS" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+053037").utc_offset.should == 19837
+ end
+
+ it "returns a Time with a UTC offset specified as -HHMMSS" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-053037").utc_offset.should == -19837
+ end
+ end
+
describe "with an argument that responds to #to_str" do
it "coerces using #to_str" do
o = mock('string')
@@ -66,6 +92,57 @@ describe "Time.new with a utc_offset argument" do
end
end
+ it "returns a Time with UTC offset specified as UTC" do
+ Time.new(2000, 1, 1, 0, 0, 0, "UTC").utc_offset.should == 0
+ end
+
+ it "returns a Time with UTC offset specified as a single letter military timezone" do
+ [
+ ["A", 3600],
+ ["B", 3600 * 2],
+ ["C", 3600 * 3],
+ ["D", 3600 * 4],
+ ["E", 3600 * 5],
+ ["F", 3600 * 6],
+ ["G", 3600 * 7],
+ ["H", 3600 * 8],
+ ["I", 3600 * 9],
+ # J is not supported
+ ["K", 3600 * 10],
+ ["L", 3600 * 11],
+ ["M", 3600 * 12],
+ ["N", 3600 * -1],
+ ["O", 3600 * -2],
+ ["P", 3600 * -3],
+ ["Q", 3600 * -4],
+ ["R", 3600 * -5],
+ ["S", 3600 * -6],
+ ["T", 3600 * -7],
+ ["U", 3600 * -8],
+ ["V", 3600 * -9],
+ ["W", 3600 * -10],
+ ["X", 3600 * -11],
+ ["Y", 3600 * -12],
+ ["Z", 0]
+ ].each do |letter, offset|
+ Time.new(2000, 1, 1, 0, 0, 0, letter).utc_offset.should == offset
+ end
+ end
+
+ ruby_version_is ""..."3.1" do
+ it "raises ArgumentError if the string argument is J" do
+ message = '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset'
+ -> { Time.new(2000, 1, 1, 0, 0, 0, "J") }.should raise_error(ArgumentError, message)
+ end
+ end
+
+ ruby_version_is "3.1" do
+ it "raises ArgumentError if the string argument is J" do
+ message = '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: J'
+ -> { Time.new(2000, 1, 1, 0, 0, 0, "J") }.should raise_error(ArgumentError, message)
+ end
+ end
+
it "returns a local Time if the argument is nil" do
with_timezone("PST", -8) do
t = Time.new(2000, 1, 1, 0, 0, 0, nil)
@@ -93,7 +170,12 @@ describe "Time.new with a utc_offset argument" do
end
it "raises ArgumentError if the String argument is not in an ASCII-compatible encoding" do
- -> { Time.new(2000, 1, 1, 0, 0, 0, "-04:10".encode("UTF-16LE")) }.should raise_error(ArgumentError)
+ # Don't check exception message - it was changed in previous CRuby versions:
+ # - "string contains null byte"
+ # - '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset'
+ -> {
+ Time.new(2000, 1, 1, 0, 0, 0, "-04:10".encode("UTF-16LE"))
+ }.should raise_error(ArgumentError)
end
it "raises ArgumentError if the argument represents a value less than or equal to -86400 seconds" do
@@ -106,19 +188,9 @@ describe "Time.new with a utc_offset argument" do
-> { Time.new(2000, 1, 1, 0, 0, 0, 86400) }.should raise_error(ArgumentError)
end
- it "raises ArgumentError if the seconds argument is negative" do
- -> { Time.new(2000, 1, 1, 0, 0, -1) }.should raise_error(ArgumentError)
- end
-
it "raises ArgumentError if the utc_offset argument is greater than or equal to 10e9" do
-> { Time.new(2000, 1, 1, 0, 0, 0, 1000000000) }.should raise_error(ArgumentError)
end
-
- it "raises ArgumentError if the month is greater than 12" do
- # For some reason MRI uses a different message for month in 13-15 and month>=16
- -> { Time.new(2000, 13, 1, 0, 0, 0, "+01:00") }.should raise_error(ArgumentError, /(mon|argument) out of range/)
- -> { Time.new(2000, 16, 1, 0, 0, 0, "+01:00") }.should raise_error(ArgumentError, "argument out of range")
- end
end
describe "Time.new with a timezone argument" do
@@ -128,10 +200,8 @@ describe "Time.new with a timezone argument" do
time.zone.should == zone
time.utc_offset.should == 5*3600+30*60
- ruby_version_is "3.0" do
- time.wday.should == 6
- time.yday.should == 1
- end
+ time.wday.should == 6
+ time.yday.should == 1
end
it "accepts timezone argument that must have #local_to_utc and #utc_to_local methods" do
@@ -288,7 +358,7 @@ describe "Time.new with a timezone argument" do
-> {
Marshal.dump(time)
- }.should raise_error(NoMethodError, /undefined method `name' for/)
+ }.should raise_error(NoMethodError, /undefined method [`']name' for/)
end
end
@@ -332,4 +402,245 @@ describe "Time.new with a timezone argument" do
end
end
end
+
+ ruby_version_is '3.1' do # https://bugs.ruby-lang.org/issues/17485
+ describe ":in keyword argument" do
+ it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "+05:00")
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "-09:00")
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "could be UTC offset as a number of seconds" do
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: 5*60*60)
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: -9*60*60)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "returns a Time with UTC offset specified as a single letter military timezone" do
+ Time.new(2000, 1, 1, 0, 0, 0, in: "W").utc_offset.should == 3600 * -10
+ end
+
+ it "could be a timezone object" do
+ zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
+
+ time.utc_offset.should == 5*3600+30*60
+ time.zone.should == zone
+
+ zone = TimeSpecs::TimezoneWithName.new(name: "PST")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == zone
+ end
+
+ it "allows omitting minor arguments" do
+ Time.new(2000, 1, 1, 12, 1, 1, in: "+05:00").should == Time.new(2000, 1, 1, 12, 1, 1, "+05:00")
+ Time.new(2000, 1, 1, 12, 1, in: "+05:00").should == Time.new(2000, 1, 1, 12, 1, 0, "+05:00")
+ Time.new(2000, 1, 1, 12, in: "+05:00").should == Time.new(2000, 1, 1, 12, 0, 0, "+05:00")
+ Time.new(2000, 1, 1, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
+ Time.new(2000, 1, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
+ Time.new(2000, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
+ Time.new(in: "+05:00").should be_close(Time.now.getlocal("+05:00"), TIME_TOLERANCE)
+ end
+
+ it "converts to a provided timezone if all the positional arguments are omitted" do
+ Time.new(in: "+05:00").utc_offset.should == 5*3600
+ end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.new(2000, 1, 1, 12, 0, 0, in: "+09:99") }.should raise_error(ArgumentError)
+ -> { Time.new(2000, 1, 1, 12, 0, 0, in: "ABC") }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if two offset arguments are given" do
+ -> {
+ Time.new(2000, 1, 1, 12, 0, 0, "+05:00", in: "+05:00")
+ }.should raise_error(ArgumentError, "timezone argument given as positional and keyword arguments")
+ end
+ end
+ end
+
+ ruby_version_is "3.2" do
+ describe "Time.new with a String argument" do
+ it "parses an ISO-8601 like format" do
+ t = Time.utc(2020, 12, 24, 15, 56, 17)
+
+ Time.new("2020-12-24T15:56:17Z").should == t
+ Time.new("2020-12-25 00:56:17 +09:00").should == t
+ Time.new("2020-12-25 00:57:47 +09:01:30").should == t
+ Time.new("2020-12-25 00:56:17 +0900").should == t
+ Time.new("2020-12-25 00:57:47 +090130").should == t
+ Time.new("2020-12-25T00:56:17+09:00").should == t
+ end
+
+ it "accepts precision keyword argument and truncates specified digits of sub-second part" do
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00").subsec.should == 0.123456789r
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: nil).subsec.should == 0.123456789876r
+ Time.new("2021-12-25 00:00:00 +09:00", precision: 0).subsec.should == 0
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: -1).subsec.should == 0.123456789876r
+ end
+
+ it "returns Time in local timezone if not provided in the String argument" do
+ Time.new("2021-12-25 00:00:00").zone.should == Time.new(2021, 12, 25).zone
+ Time.new("2021-12-25 00:00:00").utc_offset.should == Time.new(2021, 12, 25).utc_offset
+ end
+
+ it "returns Time in timezone specified in the String argument" do
+ Time.new("2021-12-25 00:00:00 +05:00").to_s.should == "2021-12-25 00:00:00 +0500"
+ end
+
+ it "returns Time in timezone specified in the String argument even if the in keyword argument provided" do
+ Time.new("2021-12-25 00:00:00 +09:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 +0900"
+ end
+
+ it "returns Time in timezone specified with in keyword argument if timezone isn't provided in the String argument" do
+ Time.new("2021-12-25 00:00:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 -0100"
+ end
+
+ it "converts precision keyword argument into Integer if is not nil" do
+ obj = Object.new
+ def obj.to_int; 3; end
+
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 1.2).subsec.should == 0.1r
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: obj).subsec.should == 0.123r
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 3r).subsec.should == 0.123r
+ end
+
+ ruby_version_is ""..."3.3" do
+ it "raise TypeError is can't convert precision keyword argument into Integer" do
+ -> {
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: "")
+ }.should raise_error(TypeError, "no implicit conversion from string")
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raise TypeError is can't convert precision keyword argument into Integer" do
+ -> {
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: "")
+ }.should raise_error(TypeError, "no implicit conversion of String into Integer")
+ end
+ end
+
+ it "raises ArgumentError if part of time string is missing" do
+ -> {
+ Time.new("2020-12-25 00:56 +09:00")
+ }.should raise_error(ArgumentError, "missing sec part: 00:56 ")
+
+ -> {
+ Time.new("2020-12-25 00 +09:00")
+ }.should raise_error(ArgumentError, "missing min part: 00 ")
+ end
+
+ it "raises ArgumentError if subsecond is missing after dot" do
+ -> {
+ Time.new("2020-12-25 00:56:17. +0900")
+ }.should raise_error(ArgumentError, "subsecond expected after dot: 00:56:17. ")
+ end
+
+ it "raises ArgumentError if String argument is not in the supported format" do
+ -> {
+ Time.new("021-12-25 00:00:00.123456 +09:00")
+ }.should raise_error(ArgumentError, "year must be 4 or more digits: 021")
+
+ -> {
+ Time.new("2020-012-25 00:56:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -012-25 00:\z/)
+
+ -> {
+ Time.new("2020-2-25 00:56:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -2-25 00:56\z/)
+
+ -> {
+ Time.new("2020-12-215 00:56:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits mday is expected after [`']-': -215 00:56:\z/)
+
+ -> {
+ Time.new("2020-12-25 000:56:17 +0900")
+ }.should raise_error(ArgumentError, "two digits hour is expected: 000:56:17 ")
+
+ -> {
+ Time.new("2020-12-25 0:56:17 +0900")
+ }.should raise_error(ArgumentError, "two digits hour is expected: 0:56:17 +0")
+
+ -> {
+ Time.new("2020-12-25 00:516:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :516:17 \+09\z/)
+
+ -> {
+ Time.new("2020-12-25 00:6:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :6:17 \+0900\z/)
+
+ -> {
+ Time.new("2020-12-25 00:56:137 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :137 \+0900\z/)
+
+ -> {
+ Time.new("2020-12-25 00:56:7 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :7 \+0900\z/)
+
+ -> {
+ Time.new("2020-12-25 00:56. +0900")
+ }.should raise_error(ArgumentError, "fraction min is not supported: 00:56.")
+
+ -> {
+ Time.new("2020-12-25 00. +0900")
+ }.should raise_error(ArgumentError, "fraction hour is not supported: 00.")
+ end
+
+ it "raises ArgumentError if date/time parts values are not valid" do
+ -> {
+ Time.new("2020-13-25 00:56:17 +09:00")
+ }.should raise_error(ArgumentError, "mon out of range")
+
+ -> {
+ Time.new("2020-12-32 00:56:17 +09:00")
+ }.should raise_error(ArgumentError, "mday out of range")
+
+ -> {
+ Time.new("2020-12-25 25:56:17 +09:00")
+ }.should raise_error(ArgumentError, "hour out of range")
+
+ -> {
+ Time.new("2020-12-25 00:61:17 +09:00")
+ }.should raise_error(ArgumentError, "min out of range")
+
+ -> {
+ Time.new("2020-12-25 00:56:61 +09:00")
+ }.should raise_error(ArgumentError, "sec out of range")
+
+ -> {
+ Time.new("2020-12-25 00:56:17 +23:59:60")
+ }.should raise_error(ArgumentError, "utc_offset out of range")
+
+ -> {
+ Time.new("2020-12-25 00:56:17 +24:00")
+ }.should raise_error(ArgumentError, "utc_offset out of range")
+
+ -> {
+ Time.new("2020-12-25 00:56:17 +23:61")
+ }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +23:61')
+ end
+
+ it "raises ArgumentError if string has not ascii-compatible encoding" do
+ -> {
+ Time.new("2021-11-31 00:00:60 +09:00".encode("utf-32le"))
+ }.should raise_error(ArgumentError, "time string should have ASCII compatible encoding")
+ end
+ end
+ end
end