pythonpython-datetimepytz

isoformat function of datetime module in python returns incorrect offset


So I have -

timezone = pytz.timezone('Asia/Kolkata')
one_time_stamp = '2017-06-01 05:30:00'

zoned_time_stamp = datetime.datetime.strptime(one_time_stamp, '%Y-%m-%d %H:%M:%S')

#This outputs 2017-06-01 05:30:00 which is fine.
print(zoned_time_stamp)

#notice timezone added
non_iso_zoned_ts = zoned_time_stamp.replace(microsecond=0, tzinfo=timezone)
# This outputs 2017-06-01 05:30:00 which is fine.
print(zoned_time_stamp)

iso_date = non_iso_zoned_ts.isoformat()
#This outputs 2017-06-01T05:30:00+05:53 which is incorrect. Ideally it should be 2017-06-01T05:30:00+05:30
print(iso_date)

Now I wonder why isoformat is adding an offset of 05:53 where as timezone Asia/Kolkata is +05:30. ref - https://www.zeitverschiebung.net/en/timezone/asia--kolkata


Solution

  • It's almost always wrong to just tack on a pytz instance for the tzinfo when creating a datetime. The correct way to convert a naive datetime into a timezone aware instance using pytz is with the zone's localize method:

    zone.localize(dt)
    

    Output for your case:

    >>> print(timezone.localize(zoned_time_stamp))
    2017-06-01 05:30:00+05:30
    

    It's quite clearly documented that passing a pytz instance in tzinfo is not a supported way of creating a localized datetime. However, that's also such a commonly seen mistake in Python code - guess many users don't read the docs!

    To understand why the incorrect approach showed what it did (weird +05:53 offset), refer to pytz: The Fastest Footgun in the West by Paul Ganssle.