如何使用Python将本地化的时间戳转换为UTC?

时间:2020-05-30 20:47:10

标签: python datetime pytz

我需要将任意时区中的“本地化”时间戳转换为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 }}对象(如我的回答所述)。

2 个答案:

答案 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

旁注:pytzdatetime模块(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())