Home > Enterprise >  datetuil results in wrong utc offset when using lower case
datetuil results in wrong utc offset when using lower case

Time:02-15

I'm trying to convert dates into different timezones using dateutil. I've noticed, that using lower case letters when creating the tz objects is leading to incorrect timezones.

>>> from datetime import datetime
>>> from dateutil import tz

>>> tz.gettz('utc-6')
tzstr('utc-6')
>>> tz.gettz('UTC-6')
tzstr('UTC-6')

Up to this point, everything seems to be correct, however when passing the tzstr into a datetime object, the lower-case tzstr will apply the inverted offset. This happens to both, and -, for all offsets.

I used %z to show the applied offset, but the issue is affecting all datetime operations.

>>> datetime.now(tz.gettz('UTC-6')).strftime('%z')
'-0600'

>>> datetime.now(tz.gettz('utc-6')).strftime('%z')
' 0600'
>>> datetime.now(tz.gettz('utc-06')).strftime('%z')
' 0600'
>>>
>>> datetime.now(tz.gettz('utc-8')).strftime('%z')
' 0800'
>>>

Is there a big oversight by myself, or is it indeed a bug in the package? I couldn't find anything in the docs limiting the user input to capitalized UTC X.

(Python version is tags/v3.9.9:ccb0e6a on Windows and python-dateutil 2.8.2, but occurs as well on Linux with python 2.8.2)

CodePudding user response:

The dateutil library, by default, diverges from POSIX-style time zones, which "use an inverted offset format, so normally GMT 3 would be parsed as an offset 3 hours behind GMT. The tzstr time zone object will parse this as an offset 3 hours ahead of GMT" (dateutil documentation on dateutil.tz.tzstr()).

The library determines when to invert the offset by checking if your timezone abbreviation is either "UTC" or "GMT" (case sensitive), then multiplies the offset by -1. Because the check is case sensitive, the offset for "UTC-6" does properly get offset to -0600 but "utc-6" does not (tzstr source code).

# Here we break the compatibility with the TZ variable handling.
# GMT-3 actually *means* the timezone -3.
if res.stdabbr in ("GMT", "UTC") and not posix_offset:
    res.stdoffset *= -1

Regardless of if this was an intentional decision, with the current tzstr implementation, you should uppercase your timezone strings before passing them in to gettz().

  • Related