Python — сравнение даты и времени с использованием временных меток, timedelta

Я провел последний час, копаясь в документации по Python и отвечая на множество вопросов SO; пожалуйста, простите меня за то, что я еще один новичок в Python, пойманный в ловушку тайны разницы во времени в Python.

Моя цель – определить разницу между текущим временем и определенной датой/временем независимо от того, находится ли она в прошлом/будущем, и вернуть рабочий формат, например секунды.

Например, если введены значения 14:00 и 16:00 (сейчас), я бы хотел, чтобы было указано «-7200», что означает, что событие произошло два часа НАЗАД. Если входными данными являются пятница 16:00 (сейчас) и воскресенье 17:00, вывод должен быть «176400» секунд, что представляет два дня и 1 час с этого момента.

Вот что я пробовал...

  • Моя первая версия представляла собой функцию, которая брала временную метку строки и разбивала ее на несколько переменных, а затем сравнивала их. Это было неуклюже с множеством ошибок, и я думаю, что если бы я разместил его здесь, я был бы ответственен за рвоту программистов.

  • Я наткнулся на эту волшебную функцию timedelta и изучил документы и SO, но я не думаю, что она делает то, что я ищу.

  • У меня была идея преобразовать обе метки времени в секунды с начала эпохи, а затем вычесть, но это становится проблемой, если вычитание выполняется в неправильном порядке (разные случаи, если событие произойдет в будущем), и мне хочется добавить операторы if для проверки знак секунд будет неуклюжим, и его следует избегать.

Это мой текущий код (все еще нужно исправить для «двунаправленного» сравнения) из ранее решенного вопроса SO:

now = time.strftime("%a %b %d %H:%M:%S %Y")
then = time.ctime(os.path.getmtime("x.cache"))
tdelta = datetime.strptime(now, '%a %b %d %H:%M:%S %Y') - datetime.strptime(then, '%a %b %d %H:%M:%S %Y')

И я чувствую, что должен каким-то образом вытянуть из этого секунды, как в этом вопросе: Tython timedelta: не могу ли я просто получить в любой единице времени значение всей разницы?

Но я не понимаю, как соединить эти точки.

Как я могу это сделать?


person daltonf    schedule 26.08.2012    source источник


Ответы (3)


Вы должны быть в состоянии использовать

tdelta.total_seconds()

чтобы получить значение, которое вы ищете. Это связано с тем, что tdelta является объектом timedelta, как и любая разница между объектами datetime.

Пара замечаний:

  1. Использование strftime, за которым следует strptime, излишне. Вы должны получить текущую дату и время с помощью datetime.now.
  2. Точно так же использование time.ctime с последующим strptime требует больше усилий, чем необходимо. Вы должны иметь возможность получить другой объект datetime с помощью datetime.fromtimestamp.

Итак, ваш окончательный код может быть

now = datetime.now()
then = datetime.fromtimestamp(os.path.getmtime("x.cache"))
tdelta = now - then
seconds = tdelta.total_seconds()
person murgatroid99    schedule 26.08.2012
comment
Потрясающий. Большое спасибо за объяснение И подтверждение окончательного кода! - person daltonf; 26.08.2012
comment
seconds = (time.time() - os.path.getmtime("x.cache")). Код, использующий datetime.now(), может сломаться при переходе на летнее время. Используйте datetime.utcnow() и datetime.utcfromtimestamp(), если вы не можете использовать time.time(). - person jfs; 17.11.2013

Что не так с этим методом?

>>> from datetime import datetime
>>> a = datetime.now()
>>> b = datetime.now() # after a few seconds
>>> delta = a-b
>>> delta.total_seconds()
-6.655989

Обратите внимание, что total_seconds доступен только в Python 2.7 ‹, но согласно документации:

Эквивалентно (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 вычислено с включенным истинным делением.

что дает точно такой же результат.

person Yuval Adam    schedule 26.08.2012
comment
Кажется, он хочет вычислить разницу с произвольным временем, а не обязательно вычислять время выполнения программы. Другими словами, я не думаю, что он хочет вычислять только разницу между временами, возникающими во время выполнения программы. - person murgatroid99; 26.08.2012
comment
Очень просто - именно то, что мне нужно было сравнить 2 раза. Стоит отметить, что datetime.utcnow() может быть лучше. - person Dan O'Boyle; 23.09.2015

У меня была такая же проблема пару месяцев назад. То, что вы ищете, это datetime.timedelta и datetime.datetime.fromtimestamp(). Вот пример того, как использовать их для решения вашей проблемы.

import datetime
import time
t1 = time.time()
#do something to kill time or get t2 from somewhere
a = [i for i in range(1000)]
t2 = time.time()
#get the difference as datetime.timedelta object
diff=(datetime.datetime.fromtimestamp(t1) - datetime.datetime.fromtimestamp(t2))
#diff is negative as t2 is in the future compared to t2
print('difference is {0} seconds'.format(abs(diff.total_seconds())))
person MHardy    schedule 26.08.2012
comment
Почему бы не использовать datetime.now и избежать ненужного преобразования fromtimestamp? - person murgatroid99; 27.08.2012