Skip to content

Conversation

@jbrockmendel
Copy link
Contributor

Current incorrect behavior:

>>> parser.parse('2017-12-05 08:38 EST')
datetime.datetime(2017, 12, 5, 8, 38)

This PR raises instead of silently dropping this timezone information.

This surfaces two test failures that look like false-positives slipped through and got assigned to res.tzname. Thats the "WIP" part of the PR.

___________________________________________ ParserTest.testFuzzyIgnoreAMPM ___________________________________________
[...]
timestr = 'Jan 29, 1945 14:45 AM I going to see you there?'
res = _result(year=1945, month=1, day=29, hour=14, minute=45, tzname=u'I')

___________________________________________ ParserTest.testRandomFormat26 ____________________________________________
[...]
timestr = '5:50 A.M. on June 13, 1990'
_result(year=1990, month=6, day=13, hour=5, minute=50, tzname=u'M', ampm=0)

@pganssle
Copy link
Member

pganssle commented Dec 5, 2017

Broadly speaking I'm in favor of this, but I'll note that the behavior of datetime.strptime's %Z directive is to silently drop time zones, weirdly. I think we will want to have a workaround in place to get the old behavior back quickly.

Maybe some sort of tzinfos wrapper object that silently drops any unrecognized time zones?

@jbrockmendel
Copy link
Contributor Author

I haven't given any thought to the strptime implications. For the moment I'm planning to focus on the two errors this turned up.

Maybe some sort of tzinfos wrapper object that silently drops any unrecognized time zones?

Do you mean an option that allows users to restore the current behavior?

@pganssle
Copy link
Member

pganssle commented Dec 5, 2017

I haven't given any thought to the strptime implications. For the moment I'm planning to focus on the two errors this turned up.

It really has no implications for strptime, it's just that that may indicate that people are expecting this kind of behavior (or that both datetime and dateutil made the same unfortunate and surprising choice). It should probably give us pause, though, since we don't know how many people are relying on this behavior.

Do you mean an option that allows users to restore the current behavior?

Yes, though I wasn't thinking of a keyword argument. Maybe it's too abstruse, but I was thinking of something roughly like this (this is for the case that tzinfos is a dict, though we'd have to handle all cases).

def tzinfoswrapper(tzinfos, drop_missing=True):
    return tzinfos.get if drop_missing else tzinfos

That will return a tzinfo for any specified zones and None for anything else (silently dropping the time zone). Then you could pass tzinfoswrapper(tzinfos) instead of tzinfos, and you'll get the old behavior. Either way, we need an easy way to do this.

@jbrockmendel
Copy link
Contributor Author

The tzinfoswrapper idea could be another shortcuttable-default in the same vein as #575.

I think the correct order to do things is to merge #554 (or another equivalent fix to that problem), then this.

@jbrockmendel
Copy link
Contributor Author

Just changed raise to a warning per brief discussion in #541.

def jump(self, name):
return name.lower() in self._jump

def weekday(self, name):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should raise a specific warning type so that it can be easily ignored by people who don't want to see this message. I suggest subclassing maybe RuntimeWarning, maybe UnknownTimezoneWarning(RuntimeWarning)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I wouldn't specify ValueError in the message. Just say it will raise an error.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I wouldn't specify ValueError in the message. Just say it will raise an error.

But the error (in the future) will be a ValueError (or a subclass), so the users seeing it can already prepare for it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wagner-certat It might be a ValueError, but probably it will be a subclass. I'm not quite sure how they would "prepare for it" using just the information that it might raise a ValueError, though, since that would catch nearly all the errors raised by parse.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, I also catch all ValueErrors already now.

@pganssle pganssle modified the milestones: Feature release, 2.7.0 Dec 15, 2017
def testRandomFormat26(self):
self.assertEqual(parse("5:50 A.M. on June 13, 1990"),
datetime(1990, 6, 13, 5, 50))
with pytest.warns(UserWarning, match="identified but not understood"):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I guess I didn't notice this in the first round of review. This is one of those xfail-ish tests I guess.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yah, I think this is part of what motivated the PR about checking for 1-character timezones more carefully (and from there discussion about keeping "A.M." in one piece in timelex.split...). Hopefully we'll be able to get rid of this line before long.

@pganssle
Copy link
Member

@jbrockmendel Is this still WIP or is it ready to merge?

@jbrockmendel
Copy link
Contributor Author

Is this still WIP or is it ready to merge?

I haven't implemented the suggestion to make a specific subclass UnknownTimezoneWarning. If you're OK leaving that for a follow-up, then I think this is good to go.

@pganssle
Copy link
Member

@jbrockmendel I'll wait for now, but if it gets close to release time (which should be soon-ish) if it's not done I'll just add that myself.

@pganssle
Copy link
Member

@jbrockmendel At this point we're just blocking on this, #613 and #571 for the 2.7.0 release. I think I might push #571 to 2.7.1 just to get this ridiculous number of changes out the door. Like I said, I can make the required changes right before merge, but just pinging in case you've forgotten about this one.

@jbrockmendel
Copy link
Contributor Author

This has fallen off my radar screen, will likely stay that way for a while longer. I'll make a note to circle back Feb 1, but feel free to run with it if that's too long a wait.

@pganssle pganssle changed the title WIP: raise on unidentified tz Warn on unidentified tz Mar 11, 2018
@pganssle
Copy link
Member

@jbrockmendel Planning on cutting a release today, do you want to review my changes?

@jbrockmendel
Copy link
Contributor Author

I'll take a look.

@pganssle pganssle mentioned this pull request Mar 11, 2018
@pganssle
Copy link
Member

OK, this is the last blocker, so as soon as the rebased version passes CI I'm going to merge.

@jbrockmendel
Copy link
Contributor Author

LGTM

@pganssle pganssle merged commit 65d66b2 into dateutil:master Mar 11, 2018
@Harmon758
Copy link

While #575 is possibly in development, are there any plans to add the tzinfoswrapper idea or another easy way to restore the old behavior?
I'd rather not have to temporarily filter/suppress the warning until I can catch an exception in a future version.

@pganssle
Copy link
Member

pganssle commented Apr 8, 2018

@Harmon758 Your comment made me realize that there actually isn't a good way to get the old behavior, so I've opened #661 as a first pass.

The warning is a specific warning class so that it should be easy to filter out if you don't care about it, so for now filtering out the behavior is the way to get the old behavior. There will be a clear way to opt in to the old behavior before the final switch happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants