Найдите, прошло ли 24 часа между датами - Python

У меня есть следующий метод:

# last_updated is a datetime() object, representing the last time this program ran
def time_diff(last_updated):
  day_period = last_updated.replace(day=last_updated.day+1, hour=1,
                                     minute=0, second=0,
                                     microsecond=0)
   delta_time = day_period - last_updated
   hours = delta_time.seconds // 3600
   # make sure a period of 24hrs have passed before shuffling
   if hours >= 24:
      print "hello"
   else:
      print "do nothing"

Я хочу узнать, прошло ли с момента last_updated 24 часа, как это сделать в Python?

Ответ 1

Если last_updated - наивный объект datetime, представляющий время в UTC:

from datetime import datetime, timedelta

if (datetime.utcnow() - last_updated) > timedelta(1): 
    # more than 24 hours passed

Если last_updated - местное время (объект datetime с наивным (timezone-unaware)):

import time

DAY = 86400
now = time.time()
then = time.mktime(last_updated.timetuple())
if (now - then) > DAY:
    # more than 24 hours passed

Если last_updated является неоднозначным временем, например, временем перехода на конец DST (один раз в год во многих часовых поясах), существует вероятность, что mktime() возвращает неверный результат (например, на час).

time.mktime() также может потерпеть неудачу, если библиотека C time не использует базу данных хронологического времени на данной платформе, а смещение UTC для локального часового пояса отличается в last_updated по сравнению с текущим. Это может относиться к более трети всех часовых поясов за последний год. Linux, OS X, последние версии Windows имеют базу данных tz (я не знаю, будут ли старые версии Windows работать на такие прошлые даты).

Остерегайтесь: может возникнуть соблазн написать datetime.now() - last_updated (как и в случае с UTC), но он гарантированно завершится неудачей на всех платформах, если смещение UTC было разным в last_updated (это возможно во многих часовых поясах). Решение на основе mktime() может использовать базу данных tz по крайней мере на некоторых платформах и поэтому может обрабатывать изменения в смещении UTC по любой причине.

Для портативности вы можете установить базу данных tz. Он предоставляется модулем pytz в Python. tzlocal может вернуть часовой пояс pytz, соответствующий местному часовому поясу:

from datetime import datetime, timedelta
from tzlocal import get_localzone # $ pip install tzlocal

tz = get_localzone() # local timezone
then = tz.normalize(tz.localize(last_updated)) # make it timezone-aware
now = datetime.now(tz) # timezone-aware current time in the local timezone
if (now - then) > timedelta(1):
    # more than 24 hours passed

Он работает, даже если смещение UTC в прошлом было другим. Но он не может (а также time.mktime()) фиксировать неоднозначные времена (tz.localize() выбирает is_dst=False время по умолчанию). tz.normalize() вызывается для корректировки несуществующих времен, например, тех, которые соответствуют переходу на начало DST (это не должно влиять на результат).

В приведенном выше коде предполагается, что last_updated является наивным объектом datetime (без информации о часовом поясе). Если last_updated - это известный объект datetime, то его легко конвертировать в UTC:

from datetime import datetime, timedelta

then_in_utc = last_updated.replace(tzinfo=None) - last_updated.utcoffset()
if (datetime.utcnow() - then_in_utc) > timedelta(1):
    # more than 24 hours passed

Общее замечание: теперь вы должны понять, почему люди рекомендуют работать с временем UTC и использовать локальное время только для отображения.

Ответ 2

Просто, чтобы очистить наши вещи, потому что я не думаю, что мы все используем time Python lib. Когда вы используете datetime, особенно в Django, это очень распространенная практика, если вы выполните сравнение следующим образом:

if (now - then) > DAY:

он будет сильно сбой. Это связано с тем, что вы не можете сравнить datetime.timedelta с int.

Решением этого является преобразование ваших объектов в секунды.
Например:

from datetime import datetime

then = datetime_object
now = datetime.now()

if (now - then).total_seconds() > NUMBER_OF_SECONDS:
    # do something

Надеюсь, я помог тем, кто столкнулся с проблемами.
Приветствие