问题 Python - 日期时间不能正确计算闰秒?


我正在解析一些具有leapsecond timestampe datetime的数据 2012-06-30T23:59:60.209215。我使用以下代码来解析该字符串并转换为datetime对象:

    nofrag, frag = t.split('.')
    nofrag_dt = datetime.datetime.strptime(nofrag, "%Y-%m-%dT%H:%M:%S")
    dt = nofrag_dt.replace(microsecond=int(frag))

Python文档声称这不应该是一个问题 %S 接受 [0, 61]。但是,我在上面的时间戳中得到了这个错误

nofrag_dt = datetime.datetime.strptime(nofrag, "%Y-%m-%dT%H:%M:%S")
ValueError: second must be in 0..59

谢谢


12167
2018-01-09 17:55


起源

文件在哪里声称? docs.python.org/2/library/datetime.html 说“与时间模块不同,日期时间模块不支持闰秒。” - Wooble
docs.python.org/2/library/... 指着 docs.python.org/2/library/time.html#time.strptime,哪里 docs.python.org/2/library/time.html#time.strftime 声称支持闰秒 - madtowneast
啊。问题不在于解析;这是由 time.strptime 工作正常;问题是,如果秒数> 59,则无法将其转换回a datetime.datetime。 - Wooble
unlrelated: int(frag) 可能返回错误的微秒数,例如, .123 应该对应 123000 微秒,不是 123。 - jfs


答案:


做这个:

import time
import datetime 
t = '2012-06-30T23:59:60.209215'
nofrag, frag = t.split('.')
nofrag_dt = time.strptime(nofrag, "%Y-%m-%dT%H:%M:%S")
ts = datetime.datetime.fromtimestamp(time.mktime(nofrag_dt))
dt = ts.replace(microsecond=int(frag))
print(dt)

输出是:

2012-07-01 00:00:00.209215

1
2018-01-09 19:16



注意:通过本地时间的往返可能会失败(例如,在DST过渡期间)并且它是 不必要 如 我的回答表明。 - jfs


的文档 %S 说

与时间模块不同,datetime模块不支持闰秒。

时间字符串 "2012-06-30T23:59:60.209215" 暗示时间是UTC(这是目前的最后一个闰秒):

import time
from calendar import timegm
from datetime import datetime, timedelta

time_string = '2012-06-30T23:59:60.209215'
time_string, dot, us = time_string.partition('.')
utc_time_tuple = time.strptime(time_string, "%Y-%m-%dT%H:%M:%S")
dt = datetime(1970, 1, 1) + timedelta(seconds=timegm(utc_time_tuple))
if dot:
    dt = dt.replace(microsecond=datetime.strptime(us, '%f').microsecond)
print(dt)
# -> 2012-07-01 00:00:00.209215

8
2018-01-09 19:35



它是如何暗示时间是UTC的?我看不到拖尾 Z 要么 +00:00。 - Matt Johnson
@MattJohnson:查看最后一次闰秒的时间(这是世界各地的同一时刻)。 - jfs
啊!非常好!你让我在那里! :) - Matt Johnson
time_string.rpartition('.') 应该 time_string.partition('.')因为如果没有点,那么前者就会产生 time_string 空字符串和 ms 获得非平凡的价值。 - unutbu
@unutbu:谢谢。我不知道为什么我用过 .rpartition() 这里。 - jfs