时区时间戳怪异

Posted

技术标签:

【中文标题】时区时间戳怪异【英文标题】:Timezone Timestamp Weirdness 【发布时间】:2021-04-13 07:52:22 【问题描述】:

我发现 Python 中不同时区的行为非常奇怪。以下代码:

import datetime as dtm
import pytz


def test_tz():
    america_ny_tz: dtm.tzinfo = pytz.timezone("America/New_York")
    est_tz: dtm.tzinfo = pytz.timezone("EST5EDT")

    today = dtm.date.today()

    ny_dtm = dtm.datetime(
        year=today.year, month=today.month, day=today.day, tzinfo=america_ny_tz
    )
    est_dtm = dtm.datetime(
        year=today.year, month=today.month, day=today.day, tzinfo=est_tz
    )

    print(f"New York: ny_dtm.timestamp(), EST: est_dtm.timestamp()")


if __name__ == "__main__":
    test_tz()

输出:

New York: 1609995360.0, EST: 1609995600.0

您可能会注意到,差异大约是 4 分钟,人们不得不假设时间应该是相同的。

我是否错误地访问了时区信息,或者我认为时区信息应该相同?

在 Linux、Ubuntu 20.04 上运行,但在 18.04 上的行为是相同的。

附:我没有尝试过其他语言或不同的操作系统来查看行为是否相同。

【问题讨论】:

关于您的 p.s.,您遇到的问题是特定于库的,而不是特定于操作系统的。在 Windows 上遇到同样的问题 ;-) 顺便说一下,请注意数据库中 Olson 先生的 this comment - EST5EDT 已过时。 @MrFuppes 我知道EST5EDT 已过时,但仍在使用中,因此是我的问题。 【参考方案1】:

这似乎是因为一个时区使用本地标准时间,而另一个时区是 UTC(世界协调时间)的偏移量。

>>> pytz.timezone("America/New_York")
<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>
>>> pytz.timezone("EST5EDT")
<DstTzInfo 'EST5EDT' EST-1 day, 19:00:00 STD>
>>> pytz.timezone("LMT")

来自https://www.timeanddate.com/time/local-mean-time.html

当地标准时间在许多国家被正式用作民用时间 在 19 世纪。每个城市都有不同的当地时间 按其经度,每度相差 4 分钟 经度。这等于在 New 上 50 英里或 81 公里的距离 约克的纬度。

【讨论】:

如果您不调用 localize,pytz 会回退到使用其数据库中时区的第一个条目——恰好是 LMT。 @MrFuppes 应该停在late 19th century【参考方案2】:

您需要正确本地化 - 使用pytz 的时区对象,在创建日期时间对象时直接设置tzinfo正确的方法。我是in the docs:

该库仅支持两种构建本地化时间的方法。第一种是使用pytz库提供的localize()方法。

建立本地化时间的第二种方法是使用标准 astimezone() 方法转换现有本地化时间


另一方面,如果您碰巧使用 Python 3.9+,则可以使用标准库中的 zoneinfo 模块让您的生活更轻松 - 请参阅 the docs / using-zoneinfo 或 example usage here。

【讨论】:

以上是关于时区时间戳怪异的主要内容,如果未能解决你的问题,请参考以下文章

Debezium 时间戳问题,无法转换为本地时区

在没有时区的时间戳的字段上加入没有时区的 generate_series 时间戳时遇到问题

时区、时间戳、 时区、格林威治(GMT)、协调世界时(UTC)的关系

不同时区转换时间戳

数据类型“带时区的时间戳”中的时区存储

Postgres 通过时区转换防止时间戳