具有相同时区信息的两个 python 日期时间对象打印不同
Two python datetime objects having the same timezone information are printed differently
我想将 Python 的日期时间对象的时区从 US/Eastern 转换为 UTC。
我所做的是首先制作 US/Eastern 时区的 datetime 对象,将其转换为 UTC 时区,然后再将其转换回 US/Eastern 时区。预计第一个和最后一个 US/Eastern timezone datetime 对象是相同的。但是结果发现两者打印的不一样
我在这里错过了什么?
代码:
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'))
输出:
2021-07-01 04:00:00 LMT-0456
2021-07-01 04:56:00 EDT-0400
解决方案
正如@MrFuppes 指出的那样,使用 .localize 方法而不是 .replace 解决了如下问题
# Add local timezone information US/Eastern
time_local = tz_local.localize(time_naive)
生成
2021-07-01 04:00:00 EDT-0400
2021-07-01 04:00:00 EDT-0400
如果您可以使用 Python 3.9 或更高版本,请使用内置的 zoneinfo 库来避免“本地化陷阱”。例如:
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
如果 Python < 3.8,您还可以通过 backports, or you can use dateutil 使用 zoneinfo
来处理时区。两者都直接设置 tzinfo
是安全的;不需要额外的本地化步骤。
我想将 Python 的日期时间对象的时区从 US/Eastern 转换为 UTC。
我所做的是首先制作 US/Eastern 时区的 datetime 对象,将其转换为 UTC 时区,然后再将其转换回 US/Eastern 时区。预计第一个和最后一个 US/Eastern timezone datetime 对象是相同的。但是结果发现两者打印的不一样
我在这里错过了什么?
代码:
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'))
输出:
2021-07-01 04:00:00 LMT-0456
2021-07-01 04:56:00 EDT-0400
解决方案
正如@MrFuppes 指出的那样,使用 .localize 方法而不是 .replace 解决了如下问题
# Add local timezone information US/Eastern
time_local = tz_local.localize(time_naive)
生成
2021-07-01 04:00:00 EDT-0400
2021-07-01 04:00:00 EDT-0400
如果您可以使用 Python 3.9 或更高版本,请使用内置的 zoneinfo 库来避免“本地化陷阱”。例如:
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
如果 Python < 3.8,您还可以通过 backports, or you can use dateutil 使用 zoneinfo
来处理时区。两者都直接设置 tzinfo
是安全的;不需要额外的本地化步骤。