python3 datetime.timestamp() 没有给出正确的 POSIX 时间

发布于 2025-01-19 09:53:09 字数 1599 浏览 0 评论 0 原文

我正在调试一些DateTime功能,特别是在本地时间和UTC之间转换。我正在使用的程序将仅在Linux和Mac上运行,但我希望看到一个跨平台解决方案。我正在使用dateTime.timestamp()在数据库中存储的几秒钟内生成UTC时间戳,但在转换为和FRO时会注意到一些非常不稳定的行为。

根据Python文档,DateTime.timestamp()应该返回代表POSIX(UTC)时间为秒数以来秒的浮点。据我了解...对于TZ Naive对象(或已经在UTC中定位的对象),这将是总数几秒钟。对于TZ Aware对象,这次应自动从给定的TZ转换为UTC。

为了测试这种行为,我在2000年1月1日创建了一个tz-nive dateTime对象。然后,这次将其定位为美国/太平洋,并使用.astimezone()转换为UTC。这是一些设置代码:

import datetime, time
from pytz import timezone

tz_pac = timezone("US/Pacific")
tz_utc = timezone("UTC")
start_tuple = (2000, 1, 1, 0, 0, 0)
naive_time_obj = datetime.datetime(*start_tuple, tzinfo = None)
pac_time_obj = tz_pac.localize(naive_time_obj)
utc_time_obj = pac_time_obj.astimezone(tz_utc)

naive_seconds = int(naive_time_obj.strftime("%s"))
pac_seconds = int(pac_time_obj.strftime("%s"))
utc_seconds = int(utc_time_obj.strftime("%s"))

print("Naive\tseconds:", naive_seconds, "\ttimestamp:", naive_time_obj.timestamp(), "\trepr:", naive_time_obj)
print("PAC\tseconds:", pac_seconds, "\ttimestamp:", pac_time_obj.timestamp(), "\trepr:", pac_time_obj)
print("UTC\tseconds:", utc_seconds, "\ttimestamp:", utc_time_obj.timestamp(), "\trepr:", utc_time_obj)

我要得到的:

Naive    seconds: 946713600     timestamp: 946713600.0     repr: 2000-01-01 00:00:00
PAC      seconds: 946713600     timestamp: 946713600.0     repr: 2000-01-01 00:00:00-08:00
UTC      seconds: 946742400     timestamp: 946713600.0     repr: 2000-01-01 08:00:00+00:00

Naive对象的输出是有道理的,因为没有时区信息可转换。对于PAC局部化对象,我希望时间戳从几秒钟转换为TZ,但它们是平等的。对于UTC本地化对象,我希望秒和时间戳相等,但是进行了转换。我想念什么?

I'm debugging some datetime functionality, specifically converting between local time and UTC. The program I'm working on will only be running on Linux and Mac but I would like to see a cross-platform solution. I'm using datetime.timestamp() to generate a utc timestamp in seconds to be stored in a database but am noticing some very erratic behavior when converting to and fro.

According to the python docs, datetime.timestamp() is supposed to return a float representing POSIX(UTC) time as seconds since the epoch. As I understand... For a tz naive object (or one already localized in UTC), this would just be total seconds. For a tz aware object, this time should be automatically be converted from the given tz to utc.

To test this behavior, I create a tz-naive datetime object at Jan, 1 2000. This time is then localized as US/Pacific and also converted to UTC with .astimezone(). Here's some setup code:

import datetime, time
from pytz import timezone

tz_pac = timezone("US/Pacific")
tz_utc = timezone("UTC")
start_tuple = (2000, 1, 1, 0, 0, 0)
naive_time_obj = datetime.datetime(*start_tuple, tzinfo = None)
pac_time_obj = tz_pac.localize(naive_time_obj)
utc_time_obj = pac_time_obj.astimezone(tz_utc)

naive_seconds = int(naive_time_obj.strftime("%s"))
pac_seconds = int(pac_time_obj.strftime("%s"))
utc_seconds = int(utc_time_obj.strftime("%s"))

print("Naive\tseconds:", naive_seconds, "\ttimestamp:", naive_time_obj.timestamp(), "\trepr:", naive_time_obj)
print("PAC\tseconds:", pac_seconds, "\ttimestamp:", pac_time_obj.timestamp(), "\trepr:", pac_time_obj)
print("UTC\tseconds:", utc_seconds, "\ttimestamp:", utc_time_obj.timestamp(), "\trepr:", utc_time_obj)

And here's what I'm getting:

Naive    seconds: 946713600     timestamp: 946713600.0     repr: 2000-01-01 00:00:00
PAC      seconds: 946713600     timestamp: 946713600.0     repr: 2000-01-01 00:00:00-08:00
UTC      seconds: 946742400     timestamp: 946713600.0     repr: 2000-01-01 08:00:00+00:00

Output for the naive object makes sense as there is no timezone info to convert with. For the PAC localized object, I expect timestamp to be tz converted from seconds, but instead they are equal. For the UTC localized object, I expect seconds and timestamp to be equal, but a conversion has taken place. What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淡紫姑娘! 2025-01-26 09:53:09

有几点:

  • Unix 时间戳(又名 POSIX 时间戳)总是< /em> 以 UTC 表示(在任何平台/语言上),因为它们代表一个不同的时刻。将表示形式转换为另一个时区不会改变该时刻。


  • %s 不应在 Python 中使用。它受您当地时区的影响。有关更多详细信息,请参阅此答案

  • Python 的 timestamp 方法将正确给出aware datetime 实例的即时信息,但对于naive 实例,它们假定以当地时间为准。因此,在计算时间戳之前完成本地到 UTC 的转换。 文档对此进行了介绍,其中表示:< /p>
    <块引用>

    假定 Naive datetime 实例表示本地时间,并且此方法依赖于平台 C mktime() 函数来执行转换。

    就您而言,naive_time_obj.timestamp() 仅匹配其他时间戳,因为您的本地时区可能也是太平洋时间。如果您在不同的本地时区下运行此代码,您将获得不同的值。

  • 在输出的最后一列中,所有三个值都显示正确的表示形式,因此转换正确进行。

A few things:

  • Unix Timestamps (aka POSIX Timestamps) are always in terms of UTC (on any platform/language) because they're representing a distinct instant in time. Converting the representation to another time zone doesn't change that instant.

  • %s should not be used in Python. It's influenced by your local time zone. See this answer for more details.

  • Python's timestamp method will correctly give the instant for aware datetime instances, but for naive instances, they are assumed to be in terms of local time. Thus a local-to-utc conversion is done before calculating the timestamp. This is covered in the docs which says:

    Naive datetime instances are assumed to represent local time and this method relies on the platform C mktime() function to perform the conversion.

    In your case, the naive_time_obj.timestamp() only matches the other timestamps because your local time zone is likely also Pacific time. If you ran this code under a different local time zone, you'd get a different value.

  • In the last column of your output, all three values are showing the correct representation, and thus the conversion occurred properly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文