【问题标题】:Converting datetime to POSIX time将日期时间转换为 POSIX 时间
【发布时间】:2020-11-19 21:57:23
【问题描述】:

如何在 python 中将日期时间或日期对象转换为 POSIX 时间戳?有一些方法可以根据时间戳创建日期时间对象,但我似乎没有找到任何明显的方法来执行相反的操作。

【问题讨论】:

  • 这个问题的答案不再是最新的。正如below 所指出的,您应该使用datetime.datetime 对象的.timestamp() 方法。请将其标记为正确答案。
  • 还要确保当您调用.timestamp() 时,您使用的是时区感知日期对象作为时区天真“are assumed to represent local time”。

标签: python datetime posix


【解决方案1】:
import time, datetime

d = datetime.datetime.now()
print time.mktime(d.timetuple())

【讨论】:

  • 谢谢。我知道这一定是非常简单的事情,但我想不通。
  • 好像根据平台的不同,time没有mktime方法
  • 请注意,这里给出的是本地时间,而不是 UTC。对于 UTC,请参阅 fixermark's answer
  • 准确地说:注意mktime 输入本地时间,输出没有时区——它是一个 Unix 时间戳,以秒为单位测量的持续时间(和总是从时代开始,从而给你时间)。 (datetime.now() 返回当前本地时间。)
  • 在夏令时转换期间有 50% 的机会返回错误结果。见Problems with Localtime
【解决方案2】:

对于 UTC 计算,calendar.timegmtime.gmtime 的倒数。

import calendar, datetime
d = datetime.datetime.utcnow()
print calendar.timegm(d.timetuple())

【讨论】:

  • 注意:calendar.timegm() 需要 UTC 输入,但结果(时间戳)不在任何时区。自纪元以来仅经过几秒钟(== 1969-12-31T19:00:00-05:00(纽约)== 1970-01-01T00:00:00Z(UTC)== 1970-01-01T03: 00:00+03:00(莫斯科))——一个固定的时间点。
  • 更正:由于闰秒,“自纪元以来的秒数”自 1970-01-01 00:00:00+00:00 以来没有经过 SI 秒。 utc_to_tai() function 可用于计算经过的 SI 秒数。
【解决方案3】:

请注意,Python 现在 (3.5.2) 在 datetime 对象中为此包含一个 built-in method

>>> import datetime
>>> now = datetime.datetime(2020, 11, 18, 18, 52, 47, 874766)
>>> now.timestamp() # Local time
1605743567.874766
>>> now.replace(tzinfo=datetime.timezone.utc).timestamp() # UTC
1605725567.874766 # 5 hours delta (I'm in UTC-5)

【讨论】:

  • 你确定这是正确的吗? now 是一个时区天真的日期时间对象,在其上调用 .timestamp 首先会假设该对象处于本地时间(这是隐式且幸运的),然后进行转换以提供符合 posix 的时间戳(自 UTC Unix 时间以来的秒数)。
  • @Marc 我不明白你的评论:我在调用now.timestamp() 旁边的示例中明确说# Local time。你能澄清一下问题是什么吗?
  • now.timestamp() 给你的是一个 posix 兼容的时间戳,它是一个正确的 utc Unix 纪元时间戳,因为 now 在这一点上是一个简单的时间戳,你的本地时区被隐式使用。在天真的日期时间对象 it will assume a local timezone(它是)上调用 .timestamp 并为您提供正确的 UTC unix 时间戳。但是,当您调用 replace 时,不会对 datetime 对象进行任何转换,它只会将 now 从幼稚 -> 感知转换。在大多数情况下,这似乎是错误的。
  • 哦,now 部分与此答案无关。随意编辑它以显示日期文字。
  • now 仅是相关的,因为它如何影响now.timestamp() 的输出。要将now 排除在此对话之外,我们可以使用datetime.datetime.now().replace(tzinfo=datetime.timezone.utc).timestamp() 这与datetime.datetime.utcnow().timestamp() 一样好。他们都有同样的问题,.timestamp() 很可能会假设错误的时区。时间很混乱,所以我可能是错的,但这就是我理解文档的方式。
【解决方案4】:

在 python 中,time.time() 可以将秒作为浮点数返回,其中包括带有微秒的小数部分。为了将日期时间转换回此表示,您必须添加微秒组件,因为直接时间元组不包含它。

import time, datetime

posix_now = time.time()

d = datetime.datetime.fromtimestamp(posix_now)
no_microseconds_time = time.mktime(d.timetuple())
has_microseconds_time = time.mktime(d.timetuple()) + d.microsecond * 0.000001

print posix_now
print no_microseconds_time
print has_microseconds_time

【讨论】:

  • 不要使用本地时间进行往返 (ts -> local -> ts)。它可能会在 DST 转换期间中断。您可以轻松扩展 timegm() 以包含微秒并将其用于 ts -> utc -> ts 转换。
【解决方案5】:

从 posix/epoch 到 datetime 时间戳以及相反的最佳转换:

this_time = datetime.datetime.utcnow() # datetime.datetime type
epoch_time = this_time.timestamp()      # posix time or epoch time
this_time = datetime.datetime.fromtimestamp(epoch_time)

【讨论】:

  • utcnow 输出一个时区天真的日期时间对象,当在其上运行 .timestamp() 时,python 将假定一个本地时区(即使它是 UTC 天真,而不是本地天真),这应该会给你不正确的反馈.
【解决方案6】:

视情况而定

你的 datetime 对象是时区感知还是天真?

时区感知

如果它知道这很简单

from datetime import datetime, timezone
aware_date = datetime.now(tz=timezone.utc)
posix_timestamp = aware_date.timestamp()

date.timestamp() 为您提供“POSIX 时间戳”

注意:更准确的称它为纪元/unix 时间戳为it may not be POSIX compliant

时区朴素

如果它不是时区感知(天真),那么您需要知道它最初位于哪个时区,以便我们可以使用 replace() 将其转换为时区感知日期对象。假设您已将其存储/检索为 UTC Naive。这里我们创建一个,作为示例:

from datetime import datetime, timezone
naive_date = datetime.utcnow()  # this date is naive, but is UTC based
aware_date = naive_date.replace(tzinfo=timezone.utc)  # this date is no longer naive

# now we do as we did with the last one

posix_timestamp = aware_date.timestamp()

最好尽快到达一个时区感知日期,以防止因幼稚日期而出现的问题(因为 Python 通常会认为它们是当地时间,可能会搞砸你)

注意:还要注意您对时代的理解,因为它取决于平台

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-20
    • 1970-01-01
    • 1970-01-01
    • 2017-08-29
    • 2011-07-05
    相关资源
    最近更新 更多