Project

General

Profile

Feature #16031

Raise ArgumentError when creating Time objects with invalid day of month, instead of rolling into next month

Added by aliism (Ali Ismayilov) 11 months ago. Updated 20 days ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:94079]

Description

When parsing an invalid date, like February 31 or November 31, I get different results from Date and Time classes.

require 'date'
require 'time'

Date.strptime('2019-02-31', '%Y-%m-%d')
# Traceback (most recent call last):
#         5: from /Users/ali/.rbenv/versions/2.6.3/bin/irb:23:in `<main>'
#         4: from /Users/ali/.rbenv/versions/2.6.3/bin/irb:23:in `load'
#         3: from /Users/ali/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
#         2: from (irb):5
#         1: from (irb):5:in `strptime'
# ArgumentError (invalid date)

Time.strptime('2019-02-31', '%Y-%m-%d')
# => 2019-03-03 00:00:00 +0100

I'd expect Time class to throw ArgumentError, just like the Date class.

Updated by sawa (Tsuyoshi Sawada) 11 months ago

Perhaps, an option to chose between the two kinds of behavior may be useful for both Date and Time. Something like exception: (true raises exception) or rollover: (true suppresses exception).

Updated by jeremyevans0 (Jeremy Evans) 29 days ago

  • Backport deleted (2.5: UNKNOWN, 2.6: UNKNOWN)
  • ruby -v deleted (ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin18])
  • Subject changed from Inconsistency between Date::strptime and Time::strptime at the end of a month to Raise ArgumentError when creating Time objects with invalid day of month, instead of rolling into next month
  • Tracker changed from Bug to Feature

This is not related to strptime specifically, this is how Time behaves generally:

Time.local(2020, 2, 31)
# => 2020-03-02 00:00:00 -0800
Time.parse("2020-02-31")
# => 2020-03-02 00:00:00 -0800

This behavior isn't a bug, it is by design: https://github.com/ruby/ruby/blob/ee35a4dad30eaf74064d5c38bfdfb3550998bb8f/time.c#L3056-L3076

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.

Updated by Dan0042 (Daniel DeLorme) 20 days ago

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.

As far as I understand the rollover is meant to deal with Time arithmetic, so we can change the year/month, and the day will automagically adjust. But for Time parsing, if you have the string "2019-02-31" it should fail parsing imho.

Updated by jeremyevans0 (Jeremy Evans) 20 days ago

Dan0042 (Daniel DeLorme) wrote in #note-3:

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.

As far as I understand the rollover is meant to deal with Time arithmetic, so we can change the year/month, and the day will automagically adjust. But for Time parsing, if you have the string "2019-02-31" it should fail parsing imho.

I disagree. Time.parse and Time.strptime 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.

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.

Date.new(2001, 1, 31) >> 1
# => #<Date: 2001-02-28 ((2451969j,0s,0n),+0s,2299161j)>

Also available in: Atom PDF