如何使用 Python 将本地化时间戳转换为 UTC?
How to convert a localized timestamp to UTC using Python?
我需要将任意时区的 "localized" 时间戳转换为 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
我知道这个问题之前已经被问过很多次了,但是我对从任意时区进行时间戳的初始转换感到困惑,因为在构造初始 datetime
对象(如我的回答所述)。
如 pytz
documentation 中所述,标准 Python datetime.replace()
方法未正确考虑夏令时。您应该使用 pytz 的 timezone.localize()
方法。
另一个问题是,在根据输入时间戳创建 datetime
对象时,您必须显式定义 tz
信息。否则,假定您的时间戳是本地(系统)时间。正如 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())
A 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 标准库)不同的时区模型。这就是为什么您不能安全地使用日期时间对象的 replace
方法来设置时区的原因。如果你想让你的生活更轻松一点,看看dateutil
。您可以在这里安全地使用 replace
。
还要小心天真的日期时间对象。 Python 默认将它们视为 本地时间 ,参见例如this answer.
我需要将任意时区的 "localized" 时间戳转换为 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
我知道这个问题之前已经被问过很多次了,但是我对从任意时区进行时间戳的初始转换感到困惑,因为在构造初始 datetime
对象(如我的回答所述)。
如 pytz
documentation 中所述,标准 Python datetime.replace()
方法未正确考虑夏令时。您应该使用 pytz 的 timezone.localize()
方法。
另一个问题是,在根据输入时间戳创建 datetime
对象时,您必须显式定义 tz
信息。否则,假定您的时间戳是本地(系统)时间。正如 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())
A 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 标准库)不同的时区模型。这就是为什么您不能安全地使用日期时间对象的 replace
方法来设置时区的原因。如果你想让你的生活更轻松一点,看看dateutil
。您可以在这里安全地使用 replace
。
还要小心天真的日期时间对象。 Python 默认将它们视为 本地时间 ,参见例如this answer.