The new Time.new(String) API is nice... but we still need a stricter version of this
The Ruby 3.2 style
Time.new(String) API works very well so far, but since the original
Time.new(Integer, Integer, Integer...) API actually accepts String objects as its arguments, there's one ambiguous case as follows:
Time.new('20230123') #=> 20230123-01-01 00:00:00 +0900
Then the problem that I'm facing is that we cannot tell if
Time.new would parse the given String as ISO8601-ish or just a year, and in order to avoid this ambiguity, we still need to somehow parse the String beforehand in our application side (like we're doing this way in Ruby on Rails https://github.com/rails/rails/blob/c49b8270/activemodel/lib/active_model/type/helpers/time_value.rb#L64-L70), then dispatch to the new
Time.new only when the String is validated to be conforming the ISO format. Otherwise, if we just optimistically pass in given Strings to
Time.new, we'll occasionally get a Time object with an unintended buggy value.
Therefore, it unfortunately seems that my feature request on #16005 still continues... I have to keep proposing that we need either of the following:
A trustworthy version of ISO8601 parser method perhaps with another name than
.newthat accepts strict ISO8601-ish String only (but with the T delimiter, I still don't know what the proper name of this format is).
Time.new(Integer-ish, Integer-ish, Integer-ish...)not to accept Integer-ish Strings but to accept only Integers. But I can imagine that this direction is very unlikely acceptable, due to the incompatibility.
Updated by nobu (Nobuyoshi Nakada) 5 months ago
- File time_benchmark.rb time_benchmark.rb added
Kernel#Integer may be easier (and probably faster) than the Regexp.
Time.new(string) unless Integer(string, exception: false)
$ ruby time_benchmark.rb Warming up -------------------------------------- active_model 33.895k i/100ms time 78.272k i/100ms Calculating ------------------------------------- active_model 365.327k (± 0.9%) i/s - 1.830M in 5.010500s time 943.682k (± 1.0%) i/s - 4.775M in 5.060040s
fast_string_to_time seems having a bug on the negative offset calculation.
Updated by byroot (Jean Boussier) 5 months ago
A trustworthy version of ISO8601 parser method perhaps with another name than .new that accepts strict ISO8601-ish String only
Can we improve
Alternatively we could introduce a method based on https://www.rfc-editor.org/rfc/rfc3339. RFC 3339 is pretty much the date and time part of ISO8601 but publicly documented.
Updated by Eregon (Benoit Daloze) 5 months ago
I think a new method is cleaner. Or maybe reusing
It feels a hack for Time.new two wildly different things based on the number of arguments and as shown here it's ambiguous.
I had the same concerns when Time.new started supporting this, so "told you so" feeling here.
Updated by mame (Yusuke Endoh) 5 months ago
Discussed at the dev meeting. @naruse (Yui NARUSE) said "
Time.new("2023") is 1.9.2 feature. We can’t deprecate on 3.2.1. Need to continue the discussion for Ruby 3.3."
BTW Ruby 3.2.0 accidentally allows
Time.new(" \n\n 2023-01-01 00:00:00 \n\n "). All of these are considered a bug, so will be prohibited (fixed) in Ruby 3.2.1.