From: "rwstauner (Randy Stauner) via ruby-core" Date: 2026-09-22T20:10:08+00:00 Subject: [ruby-core:126831] [Ruby Bug#22375] `Time.new(String)` can disagree with itself about the date Issue #22375 has been reported by rwstauner (Randy Stauner). ---------------------------------------- Bug #22375: `Time.new(String)` can disagree with itself about the date https://bugs.ruby-lang.org/issues/22375 * Author: rwstauner (Randy Stauner) * Status: Open * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- `Time.new("2026-02-30T00:00:00Z")` returns a `Time` object that is internally inconsistent. It shows as Feb 30 or Mar 2 depending on what methods are called: ```ruby t = Time.new("2026-02-30T00:00:00Z") # => 2026-02-30 00:00:00 UTC t.mon # => 2 t.day # => 30 (February 30 is invalid) t.to_i # => 1772409600 Time.utc(2026, 3, 2).to_i # => 1772409600 # (Mar 2 gives same #to_i result) t == Time.utc(2026, 3, 2) # => true t + 0 # => 2026-03-02 00:00:00 UTC # plus zero normalizes t # => 2026-02-30 00:00:00 UTC # still invalid t.to_a # => [0, 0, 0, 2, 3, 2026, 1, 61, false, "UTC"] # to_a shows Mar 2 t # => 2026-03-02 00:00:00 UTC # the to_a call appears to have normalized the object ``` The numeric constructor normalizes `Time.new(2026, 2, 30)` to March 2. A string with an offset other than Z (`+02:00`) also normalizes: ```ruby require "time" Time.new("2026-02-30T00:00:00+02:00") # => 2026-03-02 00:00:00 +0200 ``` This has been the behavior since at least Ruby 3.3.0. However, since [commit `77d0d22b`](https://github.com/ruby/ruby/commit/77d0d22b59e175a3f5ad64e53c0eaa7aa11eafcd) (2026-06-22), `Time.iso8601`, `Time.rfc3339`, and `Time.xmlschema` all parse by calling `Time.new(string)` instead of building from `Time.utc(y, m, d, ...)`. So they now inherit this behavior: ```ruby require "time" Time.iso8601("2026-02-30T00:00:00.000000000Z").iso8601(9) # => "2026-02-30T00:00:00.000000000Z" ``` Currently the test suite has a test that raises ArgumentError for an invalid month but we don't appear to have tests for invalid days. I think we should add a test for this case and fix Time.new(string) to normalize consistently. -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/