diff --git a/spec/std/time/time_spec.cr b/spec/std/time/time_spec.cr index 83e95bbadff7..b1f828c933ee 100644 --- a/spec/std/time/time_spec.cr +++ b/spec/std/time/time_spec.cr @@ -53,6 +53,28 @@ describe Time do end end + it "#initialize checks boundary at time min" do + {-5 * 3600, -1, 0, 1, 5 * 3600}.each do |offset| + seconds = -offset.to_i64 + Time.new(seconds: seconds + 1, nanoseconds: 0, location: Time::Location.fixed(offset)) + Time.new(seconds: seconds, nanoseconds: 0, location: Time::Location.fixed(offset)) + Time.expect_invalid do + Time.new(seconds: seconds - 1, nanoseconds: 0, location: Time::Location.fixed(offset)) + end + end + end + + it "#initialize checks boundary at time max" do + {-5 * 3600, -1, 0, 1, 5 * 3600}.each do |offset| + seconds = Time::MAX_SECONDS - offset.to_i64 + Time.new(seconds: seconds - 1, nanoseconds: 0, location: Time::Location.fixed(offset)) + Time.new(seconds: seconds, nanoseconds: 0, location: Time::Location.fixed(offset)) + Time.expect_invalid do + Time.new(seconds: seconds + 1, nanoseconds: 0, location: Time::Location.fixed(offset)) + end + end + end + it "initialize with .epoch" do seconds = 1439404155 time = Time.epoch(seconds) @@ -121,6 +143,37 @@ describe Time do end end + it "#add_span checks boundary at time min" do + {5 * 3600, 1, 0, -1, -5 * 3600}.each do |offset| + location = Time::Location.fixed(offset) + + time = Time.new(1, 1, 1, location: location) + time.add_span(0, 1).should eq Time.new(1, 1, 1, nanosecond: 1, location: location) + time.add_span(0, 0).should eq time + expect_raises(ArgumentError) do + time.add_span(0, -1) + end + end + end + + it "#add_span checks boundary at time max" do + {5 * 3600, 1, 0, -1, -5 * 3600}.each do |offset| + location = Time::Location.fixed(offset) + + time = Time.new(9999, 12, 31, 23, 59, 59, nanosecond: 999_999_999, location: location) + time.add_span(0, -1).should eq Time.new(9999, 12, 31, 23, 59, 59, nanosecond: 999_999_998, location: location) + time.add_span(0, 0).should eq time + expect_raises(ArgumentError) do + time.add_span(0, 1) + end + end + end + + it "adds zero span" do + time = Time.now + time.add_span(0, 0).should eq time + end + it "add days" do t1 = Time.utc(2002, 2, 25, 15, 25, 13) t1 = t1 + 3.days diff --git a/src/time.cr b/src/time.cr index 973888b8f0d9..6323505d752f 100644 --- a/src/time.cr +++ b/src/time.cr @@ -197,6 +197,10 @@ struct Time {% end %} def initialize(*, @seconds : Int64, @nanoseconds : Int32, @location : Location) + unless 0 <= offset_seconds <= MAX_SECONDS + raise ArgumentError.new "Invalid time: seconds out of range" + end + unless 0 <= @nanoseconds < NANOSECONDS_PER_SECOND raise ArgumentError.new "Invalid time: nanoseconds out of range" end @@ -303,10 +307,6 @@ struct Time nanoseconds += NANOSECONDS_PER_SECOND end - unless 0 <= seconds <= MAX_SECONDS - raise ArgumentError.new "Invalid time" - end - Time.new(seconds: seconds, nanoseconds: nanoseconds.to_i, location: location) end