sdispater / pendulum

Python datetimes made easy
https://pendulum.eustace.io
MIT License
6.28k stars 386 forks source link

Strict ISO8601 parsing option? #260

Open techdragon opened 6 years ago

techdragon commented 6 years ago

Pendulum is incorrectly parsing ISO 8601 strings without timezone information.

pendulum.parse('2018-08-02T15:00')
Out[16]: DateTime(2018, 8, 2, 15, 0, 0, tzinfo=Timezone('UTC'))

"If no UTC relation information is given with a time representation, the time is assumed to be in local time." Wikipedia

If you have a copy of ISO8601:2004 or the more easily obtained ISO8601:2016 drafts, the equivalent ISO description of this behaviour is a little way into section 4.3.2 "The zone designator is empty if use is made of local time..."

Pendulum should either assume the current local time zone producing a DateTime object using the local timezone and the input time. Alternatively if we don't want to assume the local time zone is the correct one, it should raise an error indicating the insufficient information. It should not, as it currently is doing, assume UTC.

Edit: If the choice is made to assume local time, I'd like to tack on a feature request, some sort of flag or alternative parse function that does throw an error if there is no explicit timezone information either supplied to the function or in the formatted time string input itself. Some sort of strict mode / no assumptions allowed mode

sdispater commented 6 years ago

Thanks for your interest in Pendulum.

I know that it differs from the official spec but Pendulum is all about sensible defaults. So, I wanted to make the parse() method deterministic by defaulting to UTC if no timezone information could be found. This way you don't get surprises when you parse a datetime.

Assuming local time can lead to undesired behavior and race conditions.

If you want strings with no timezone information to be parsed as local time, you can pass the tz keyword argument and set it to local:

>>> import pendulum
>>> pendulum.parse('2018-08-02T15:00', tz="local")
DateTime(2018, 8, 2, 15, 0, 0, tzinfo=Timezone('America/Guayaquil'))

Note that it is safe to do so since if a timezone offset is specified it will be preferred over the tz timezone:

>>> import pendulum
>>> pendulum.parse('2018-08-02T15:00+01:30', tz="local")
DateTime(2018, 8, 2, 15, 0, 0, tzinfo=Timezone('+01:30'))
techdragon commented 6 years ago

@sdispater I'm not just interested, I'm a fan and already use Pendulum in production code. Its an excellent library that I routinely recommend to other people. I do understand the desire to have sensible defaults and as you show, per usual, pendulum doesn't disappoint when it comes to sensible behaviour, timezone in the string to be parsed taking precedent over the tz keyword argument is exactly how I would want to do things.

However, despite all this wonderfully sensible behaviour, I would still like to ask for some kind of strict mode or standards compliance mode. Sometimes you just really want to throw an error at the first sign of trouble rather than use any sort of default or assumption. 😃

Edit: I've updated the title to reflect that this is now effectively a feature request.

0dminnimda commented 2 years ago

Any updates on this?