Вопрос-Ответ

Find if 24 hrs have passed between datetimes

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

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

# 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"

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

Переведено автоматически
Ответ 1

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

from datetime import datetime, timedelta

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

If last_updated - это местное время (наивный (не зависящий от часового пояса) объект datetime):

import time

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

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

time.mktime() также может произойти сбой, если time библиотека C не использует базу данных исторических часовых поясов на данной платформе и смещение 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(hours=24):
# more than 24 hours passed

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

Приведенный выше код предполагает, что 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(hours=24):
# more than 24 hours passed

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

Ответ 2

Просто чтобы прояснить некоторые моменты, потому что я не думаю, что все мы используем time библиотеку Python. При использовании 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

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

Приветствия

python datetime