我该如何在Python中将日期或时间对象转换为POSIX时间戳?有一些方法可以从时间戳创建一个日期时间对象,但似乎没有明显的方法来完成相反的操作。
import time, datetime
d = datetime.datetime.now()
print time.mktime(d.timetuple())
mktime
期望输入 本地时间,并且输出没有时区 - 它是一个Unix时间戳,表示以秒为单位的持续时间(始终从纪元开始,因此可以给出时间)。 (datetime.now()
返回当前本地时间。) - Thanatostimetuple()
步骤中,日期时间将被截断为秒。因此,通过进行此转换会丢失精度。 - Shaun对于UTC计算,calendar.timegm
是time.gmtime
的反函数。
import calendar, datetime
d = datetime.datetime.utcnow()
print calendar.timegm(d.timetuple())
calendar.timegm()
函数需要 UTC 时间作为输入,但是其结果(时间戳)并不带有任何时区信息。它仅表示自 1970 年 1 月 1 日 00:00:00 (UTC) 起经过的秒数,相当于一个固定的时间点(即“时代”起始日)== 1969-12-31T19:00:00-05:00 (纽约)== 1970-01-01T00:00:00Z(UTC)== 1970-01-01T03:00:00+03:00 (莫斯科)。 - jfs请注意,Python现在(3.5.2)在datetime
对象中包含了一个内置方法以用于此功能:
>>> 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时间以来的秒数)。 - Marcnow.timestamp()
旁边的示例中,我明确地说“#本地时间”。你能澄清一下问题吗? - Clémentnow.timestamp()
给出的是符合 POSIX 标准的时间戳,因为此时 now
是一个本地时区隐式使用的原始时间戳,所以它是一个正确的 UTC Unix 纪元时间戳。当在原始日期时间对象上调用 .timestamp
时,它会假定为本地时区(这就是它的默认值),并给出一个正确的 UTC Unix 时间戳。然而,当你调用 replace
时,日期时间对象不会进行任何转换,它只会将 now
从原始状态转换为有意识的状态。在大多数情况下,这似乎是错误的。 - Marc在Python中,time.time()函数可以返回包括微秒在内的浮点数秒数。为了将datetime转换回这种表示形式,您需要添加微秒组件,因为直接使用timetuple函数不包含它。
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
你的日期时间对象是时区感知还是无意识的?
如果它是时区感知的,那就简单了。
from datetime import datetime, timezone
aware_date = datetime.now(tz=timezone.utc)
posix_timestamp = aware_date.timestamp()
当你使用date.timestamp()时,它会给你一个"POSIX时间戳"
注意:更准确的称呼应该是纪元/Unix时间戳,因为它可能不符合POSIX标准
如果它没有时区信息(即无关),那么你需要知道它最初所在的时区,以便我们可以使用replace()将其转换为有时区信息的日期对象。假设你已将其存储/检索为UTC无关的时间。这里我们创建一个示例:
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通常会假定它们是本地时间并可能导致错误)而引起的问题。
注意:同时要小心理解纪元,因为它与平台有关。
最佳的posix/epoch时间戳与日期时间之间的转换方法:
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 无关的,而不是本地无关的),这将给您带来错误的反馈。 - Marc
datetime.datetime
对象的.timestamp()
方法,如下所示below。请将其标记为正确答案。 - Giorgio Balestrieri.timestamp()
时,使用的是带有时区信息的日期对象,因为时区无关的日期对象"被认为代表本地时间"。 - Marc