Python – Datetime не учитывает високосную секунду должным образом?

Я анализирую некоторые данные, которые имеют временную метку даты и времени високосной секунды 2012-06-30T23:59:60.209215. Я использовал следующий код для анализа этой строки и преобразования в объект даты и времени:

    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

Спасибо


person madtowneast    schedule 09.01.2014    source источник
comment
Где документация утверждает это? docs.python.org/2/library/datetime.html говорит: В отличие от time, модуль datetime не поддерживает дополнительные секунды.   -  person Wooble    schedule 09.01.2014
comment
docs.python.org/2/library/ указывает на docs.python.org/2/library/time.html# time.strptime, где docs.python.org/2 /library/time.html#time.strftime утверждает, что поддерживает дополнительные секунды   -  person madtowneast    schedule 09.01.2014
comment
Ах. Проблема не в разборе; это сделано time.strptime и работает нормально; проблема в том, что если секунды равны › 59, их нельзя преобразовать обратно в datetime.datetime.   -  person Wooble    schedule 09.01.2014
comment
несвязанный: int(frag) может возвращать неправильное количество микросекунд, например, .123 должно соответствовать 123000 микросекундам, а не 123.   -  person jfs    schedule 11.03.2015


Ответы (2)


Сделай это:

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
person Velimir Mlaker    schedule 09.01.2014
comment
примечание: круговое путешествие по местному времени может завершиться неудачей (например, во время перехода на летнее время), и это ненужно, поскольку мой ответ демонстрирует. - person jfs; 10.03.2015

В документации для %S говорится:

В отличие от модуля time, модуль 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
person jfs    schedule 09.01.2014
comment
Как это означает, что время в UTC? Я не вижу замыкающих Z или +00:00. - person Matt Johnson-Pint; 06.09.2014
comment
@MattJohnson: посмотрите время последней дополнительной секунды (это один и тот же момент времени по всему миру). - person jfs; 06.09.2014
comment
Ах! Очень хорошо! Тут ты меня подловил! :) - person Matt Johnson-Pint; 06.09.2014
comment
time_string.rpartition('.') должно быть time_string.partition('.'), так как если точки нет, то первая делает time_string пустой строкой, а ms получает нетривиальное значение. - person unutbu; 10.03.2015
comment
@unutbu: спасибо. Я не знаю, почему я использовал здесь .rpartition(). - person jfs; 10.03.2015