Two python datetime objects having the same timezone information are printed differently

Question:

I’d like to convert timezone of a Python’s datetime object, from US/Eastern to UTC.

What I did was first making datetime object of US/Eastern timezone, converting it to UTC timezone, and converting it back to the US/Eastern timezone. It is expected the first and last US/Eastern timezone datetime objects are identical. But it turned out that the two are printed differently.

What am I missing here?

Code:

from datetime import datetime
import pytz

tz_local = pytz.timezone('US/Eastern')
tz_utc = pytz.utc

datestring = '20210701'
timestring = '04:00:00'
hour, minute, sec = timestring.split(':')
hour, minute, sec = list(map(int, [hour, minute, sec]))

# Make naive datetime object from raw strings
date_naive = datetime.strptime(datestring, '%Y%m%d')
time_naive = date_naive.replace(hour=hour, minute=minute, second=sec)

# Add local timezone information US/Eastern
time_local = time_naive.replace(tzinfo=tz_local)

# Convert to UTC timezone
time_utc = time_local.astimezone(tz_utc)

# Revert to US/Eastern Timezone
time_local_rev = time_utc.astimezone(tz_local)

print(time_local.strftime('%Y-%m-%d %H:%M:%S %Z%z'))
print(time_local_rev.strftime('%Y-%m-%d %H:%M:%S %Z%z'))

Outputs:

2021-07-01 04:00:00 LMT-0456
2021-07-01 04:56:00 EDT-0400

Solution

As @MrFuppes noted, using .localize method instead of .replace solved the issue as follows

# Add local timezone information US/Eastern
time_local = tz_local.localize(time_naive)

Generated

2021-07-01 04:00:00 EDT-0400
2021-07-01 04:00:00 EDT-0400
Asked By: hskim__

||

Answers:

If you can use Python 3.9 or higher, use the built-in zoneinfo library to avoid the "localize-trap". EX:

from datetime import datetime
from zoneinfo import ZoneInfo

tz_local = ZoneInfo('US/Eastern')
tz_utc = ZoneInfo('UTC')

datestring = '20210701'
timestring = '04:00:00'

# make a datetime object and set the time zone with replace:
dt_local = datetime.strptime(datestring+timestring, "%Y%m%d%H:%M:%S").replace(tzinfo=tz_local)

dt_utc = dt_local.astimezone(tz_utc)

print(dt_local)
# 2021-07-01 04:00:00-04:00
print(dt_utc)
# 2021-07-01 08:00:00+00:00

With Python < 3.8, you can also use zoneinfo via backports, or you can use dateutil to handle time zones. It’s safe to set tzinfo directly with both; no extra localize step needed.

Answered By: FObersteiner
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.