3

I am getting a very strange bug in python.

from dateutil import parser
string = "March 2008"
parser.parse(string)
 datetime.datetime(2008, 3, 30, 0, 0)
string = "February 2008"
parser.parse(string)

Traceback (most recent call last):

File "", line 1, in File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/dateutil/parser.py", line 697, in parse return DEFAULTPARSER.parse(timestr, **kwargs) File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/dateutil/parser.py", line 310, in parse ret = default.replace(**repl) ValueError: day is out of range for month

I understand that I can add a day to my string to make the parser work, but I have no idea why dateutil does not work without the day for February, while it works for every other month.

Andrew
  • 4,953
  • 15
  • 40
  • 58
user3696321
  • 137
  • 8

2 Answers2

4

This was a fun one.

From dateutil.parser:

    def parse(self, timestr, default=None,
                ignoretz=False, tzinfos=None,
                **kwargs):
    if not default:
        default = datetime.datetime.now().replace(hour=0, minute=0,
                                                  second=0, microsecond=0)

Basically, if you don't supply a day, any date string lacking a day will default to the current day. Which as it happens, is the 30th today, which of course February does not have. This could probably be regarded as a bug in dateutil.

Mark Whitfield
  • 2,470
  • 1
  • 12
  • 12
  • If you feel like modifying the source on your system, in the param list for `.replace()` just add `day=1,` to the beginning and it will always return the first of the month. – MattDMo Jul 30 '14 at 19:25
  • 1
    @MattDMo no need to modify the source, you can pass your own `default` parameter to `parse` with any `datetime` object you'd like. And I see this is documented behavior so it shouldn't be considered a bug. – Mark Ransom Jul 30 '14 at 20:07
  • @MarkRansom that's true. This behavior may be documented, but it sure is non-intuitive, at least for me. – MattDMo Jul 30 '14 at 20:09
  • You can do something like this: `p = lambda d: parser.parse( d, default = tsdt.GetDate("2015 Jan 1") )` – ashkan Aug 31 '15 at 20:40
1

The problem is that any fields that aren't present in the parsed string are taken from the current date.

Notice that "March 2008" returned March 30th 2008, because you ran it on July 30th 2014.

Similarly, just "March" will give you March 30th 2014.

So, "February 2008" will give you February 30th 2008, which is of course invalid.

abarnert
  • 354,177
  • 51
  • 601
  • 671