我需要将任意时区中的“本地化”时间戳转换为unix时间戳(以UTC为单位)。
>>> import pytz
# This represents 2019-09-11T16:14:00 (US/Central) or 2019-09-11T21:14:00 UTC!
>>> local_timestamp = 1568218440
>>> tz = pytz.timezone("US/Central")
>>> my_unix_timestamp = unix_timestamp(local_timestamp, tz)
>>> print(my_unix_timestamp)
1568236440 # 2019-09-11T21:14:00
我知道这个问题已经被问过很多次了,但是我一直对从任意时区进行时间戳的初始转换感到困惑,因为在构造初始{{1时,必须显式设置tz
}}对象(如我的回答所述)。
答案 0 :(得分:1)
timestamp (POSIX)绝不能本地化;它应始终引用UTC。否则,由于模棱两可会导致严重的头痛。仅datetime
对象应被本地化(可感知tz),即包含时区信息(tzinfo!= None)。示例:
from datetime import datetime, timezone
import dateutil
datetime.fromisoformat('2019-09-11T21:14:00').replace(tzinfo=timezone.utc).timestamp()
# 1568236440.0
datetime.fromisoformat('2019-09-11T16:14:00').replace(tzinfo=dateutil.tz.gettz("US/Central")).timestamp()
# 1568236440.0
旁注:pytz
与datetime
模块(Python标准库)使用的时区模型不同。这就是为什么您不能安全地使用datetime对象的replace
方法来设置时区的原因。如果您想让自己的生活更轻松一点,请查看dateutil
。您可以在此处安全使用replace
。
还应注意朴素的datetime对象。 Python默认将它们视为本地时间,请参见例如this answer。
答案 1 :(得分:0)
如pytz
documentation中所述,标准的Python datetime.replace()
方法无法正确考虑夏令时。您应该使用pytz的timezone.localize()
方法。
另一个难题是,根据输入时间戳创建tz
对象时,必须显式定义datetime
信息。否则,假定您的时间戳是本地(系统)时间。如datetime
documentation中所述,出于这个原因,您应避免使用datetime.utcfromtimestamp()
。
所以:
from datetime import datetime, timezone
def unix_timestamp(local_timestamp, local_timezone):
"""turn the input timestamp into a UTC `datetime` object, even though
the timestamp is not in UTC time, we must do this to construct a datetime
object with the proper date/time values"""
dt_fake_utc = datetime.fromtimestamp(local_timestamp, tz=timezone.utc)
"""remove the (incorrect) timezone info that we supplied """
dt_naive = dt_fake_utc.replace(tzinfo=None)
"""localize the datetime object to our `timezone`. You cannot use
datetime.replace() here, because it does not account for daylight savings
time"""
dt_local = local_timezone.localize(dt_naive)
"""Convert our datetime object back to a timestamp"""
return int(dt_local.timestamp())