Search code examples
pythondatetimepytz

Printing datetime as pytz.timezone("Etc/GMT-5") yields incorrect result


Consider the following example, where I take a naive datetime, make it timezone aware in UTC, and then convert to UTC-5:

d1 = datetime.datetime(2019,3,7, 7,45)

d2 = pytz.utc.localize(d1)
print(f'UTC  : {d2}')

d3 = d2.astimezone(pytz.timezone('Etc/GMT-5'))
print(f'UTC-5: {d3}')

The output of this is:

UTC  : 2019-03-07 07:45:00+00:00
UTC-5: 2019-03-07 12:45:00+05:00

I would have expected the UTC-5 time to be 02:45, but the 5 hour offset is being added to UTC, rather than subtracted.

Questions:

  • Why is the 'Etc/GMT-5' offset applied to UTC +5 hours instead of -5 hours?
  • How can I convert from UTC to UTC-5?

Solution

  • You are using pytz, not just Python's datetime. Like dateutil, pytz uses the Olson tz database.

    The Olson tz database defines Etc/GMT+N timezones which conform with the POSIX style:

    those zone names beginning with "Etc/GMT" have their sign reversed from the standard ISO 8601 convention. In the "Etc" area, zones west of GMT have a positive sign and those east have a negative sign in their name (e.g "Etc/GMT-14" is 14 hours ahead of GMT.)


    So, to convert UTC to a timezone with offset -5 you could use Etc/GMT+5:

    import datetime as DT
    import pytz
    
    naive = DT.datetime(2019, 3, 7, 7, 45)
    utc = pytz.utc
    gmt5 = pytz.timezone('Etc/GMT+5')
    print(utc.localize(naive).astimezone(gmt5))
    
    # 2019-03-07 02:45:00-05:00