https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112019-07-31T19:27:48ZRuby Issue Tracking SystemRuby master - Feature #16031: Raise ArgumentError when creating Time objects with invalid day of month, instead of rolling into next monthhttps://bugs.ruby-lang.org/issues/16031?journal_id=803142019-07-31T19:27:48Zsawa (Tsuyoshi Sawada)
<ul></ul><p>Perhaps, an option to chose between the two kinds of behavior may be useful for both <code>Date</code> and <code>Time</code>. Something like <code>exception:</code> (<code>true</code> raises exception) or <code>rollover:</code> (<code>true</code> suppresses exception).</p> Ruby master - Feature #16031: Raise ArgumentError when creating Time objects with invalid day of month, instead of rolling into next monthhttps://bugs.ruby-lang.org/issues/16031?journal_id=860782020-06-10T20:40:16Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul><li><strong>Tracker</strong> changed from <i>Bug</i> to <i>Feature</i></li><li><strong>Subject</strong> changed from <i>Inconsistency between Date::strptime and Time::strptime at the end of a month</i> to <i>Raise ArgumentError when creating Time objects with invalid day of month, instead of rolling into next month</i></li><li><strong>ruby -v</strong> deleted (<del><i>ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin18]</i></del>)</li><li><strong>Backport</strong> deleted (<del><i>2.5: UNKNOWN, 2.6: UNKNOWN</i></del>)</li></ul><p>This is not related to <code>strptime</code> specifically, this is how Time behaves generally:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Time</span><span class="p">.</span><span class="nf">local</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">31</span><span class="p">)</span>
<span class="c1"># => 2020-03-02 00:00:00 -0800</span>
<span class="no">Time</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="s2">"2020-02-31"</span><span class="p">)</span>
<span class="c1"># => 2020-03-02 00:00:00 -0800</span>
</code></pre>
<p>This behavior isn't a bug, it is by design: <a href="https://github.com/ruby/ruby/blob/ee35a4dad30eaf74064d5c38bfdfb3550998bb8f/time.c#L3056-L3076" class="external">https://github.com/ruby/ruby/blob/ee35a4dad30eaf74064d5c38bfdfb3550998bb8f/time.c#L3056-L3076</a></p>
<p>So I'm switching this to a feature request to change Time to raise ArgumentError for invalid day of month, instead of rolling into the next month.</p> Ruby master - Feature #16031: Raise ArgumentError when creating Time objects with invalid day of month, instead of rolling into next monthhttps://bugs.ruby-lang.org/issues/16031?journal_id=862702020-06-20T02:11:30ZDan0042 (Daniel DeLorme)
<ul></ul><p>It's true that this behavior is due to how Time behaves generally, but I think this is a valid bug report specifically related to strptime. I don't think the OP was really asking for a change in the rollover behavior of Time#local, just that strptime should not behave like that.</p>
<p>As far as I understand the rollover is meant to deal with Time <em>arithmetic</em>, so we can change the year/month, and the day will automagically adjust. But for Time <em>parsing</em>, if you have the string "2019-02-31" it should fail parsing imho.</p> Ruby master - Feature #16031: Raise ArgumentError when creating Time objects with invalid day of month, instead of rolling into next monthhttps://bugs.ruby-lang.org/issues/16031?journal_id=862712020-06-20T04:23:29Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>Dan0042 (Daniel DeLorme) wrote in <a href="#note-3">#note-3</a>:</p>
<blockquote>
<p>It's true that this behavior is due to how Time behaves generally, but I think this is a valid bug report specifically related to strptime. I don't think the OP was really asking for a change in the rollover behavior of Time#local, just that strptime should not behave like that.</p>
<p>As far as I understand the rollover is meant to deal with Time <em>arithmetic</em>, so we can change the year/month, and the day will automagically adjust. But for Time <em>parsing</em>, if you have the string "2019-02-31" it should fail parsing imho.</p>
</blockquote>
<p>I disagree. <code>Time.parse</code> and <code>Time.strptime</code> should remain consistent with other Time constructors. Either all constructors should be strict and reject the dates, or none of the constructors should. Barring backwards compatibility issues, I think it would be best to make all constructors strict. However, I don't think the benefits of doing so outweigh the backwards compatibility break.</p>
<p>For what its worth, anyone doing time arithmetic at the day/year/month level is better off using Date/DateTime. Date's arithmetic makes more sense, clamping to the end of the month instead of spilling into the next month. It also offers a nicer API.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2001</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">31</span><span class="p">)</span> <span class="o">>></span> <span class="mi">1</span>
<span class="c1"># => #<Date: 2001-02-28 ((2451969j,0s,0n),+0s,2299161j)></span>
</code></pre>