Python: учитывая дату и день недели, найдите дату следующего появления данного дня недели

Это немного сложно объяснить, поэтому я извиняюсь, если это не имеет особого смысла.

У меня есть программа, где я делаю некоторые планирования. Одна из его настроек — запускать задачу еженедельно в определенные дни. Например, еженедельно в понедельник, среду и пятницу.

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

На самом деле у меня есть день недели как соответствующее целое число из date.weekday(), поэтому в этом случае у меня есть 2, что представляет среду.

Как лучше всего справиться с чем-то подобным? Я чувствую, что должно быть довольно простое решение, но оно не приходит в голову. Я думал об использовании объекта календаря для поиска нужного дня недели, но это кажется излишним.


person Jon    schedule 03.01.2012    source источник


Ответы (4)


Используйте timedelta, чтобы добавить дату. Например, можно использовать некоторую дату d в качестве запланированной даты для текущей задачи и некоторый день next_day (следующий день, когда вы хотите запустить задачу).

from datetime import date, timedelta
...
n = (next_day - d.weekday()) % 7 # mod-7 ensures we don't go backward in time
next_run_date = d + timedelta(days=n)
person aganders3    schedule 03.01.2012
comment
Похоже, у меня это не сработало. Это было отключено на несколько дней, когда я провел свой модульный тест с изменением. Я думаю, что может сбить с толку то, что в Python понедельник равен 0, а воскресенье — 6. Я думаю, что понедельник, равный 0, отбрасывает это, но я не уверен. - person Jon; 03.01.2012
comment
Я думаю, вы хотите next_day - d.weekday() вместо этого. - person Mark Ransom; 03.01.2012
comment
Спасибо @MarkRansom, я думаю, вы правы, и я исправил свой ответ. @Джон, ты можешь попробовать еще раз? Я не думаю, что понедельник = 0 должен быть проблемой, если next_day использует то же соглашение. - person aganders3; 03.01.2012
comment
Теперь это работает, спасибо за помощь. Я изначально пытался что-то очень похожее, но это было не совсем правильно. Все мои модульные тесты проходят сейчас. - person Jon; 03.01.2012

Используйте dateutil.relativedelta:

from dateutil import relativedelta
import datetime

today = datetime.date.today()
# datetime.date(2012, 1, 3)

today + relativedelta.relativedelta(weekday=2) # 2 is Wednesday
# datetime.date(2012, 1, 4)

today + relativedelta.relativedelta(weekday=6) # 6 is Sunday
# datetime.date(2012, 1, 8)

today + relativedelta.relativedelta(weekday=1) # 1 is Tuesday
# datetime.date(2012, 1, 3)
# returns today

today + relativedelta.relativedelta(weeks=1, weekday=1)
# datetime.date(2012, 1, 10)
# returns Tuesday at least one week ahead
person eumiro    schedule 03.01.2012

Мы знаем это:

  • с понедельника по среду разница составляет 2 дня.
  • с среды по пятницу разница составляет 2 дня.
  • с пятницы по понедельник разница в 3 дня.

Итак, это так же просто, как добавить разницу в днях между запланированными задачами:

from datetime import datetime, timedelta
first_scheduled_task = datetime(year=2012, month=1, day=2)
second_scheduled_task = first_scheduled_task + timedelta(2)
third_scheduled_task = second_scheduled_task + timedelta(2)
fourth_scheduled_task = third_scheduled_task + timedelta(3)

Это даст нам результат:

>>> first_scheduled_task
datetime.datetime(2012, 1, 2, 0, 0) # Monday 1/2/2012
>>> second_scheduled_task
datetime.datetime(2012, 1, 4, 0, 0) # Wednesday 1/4/2012
>>> third_scheduled_task
datetime.datetime(2012, 1, 6, 0, 0) # Friday 1/6/2012
>>> fourth_scheduled_task
datetime.datetime(2012, 1, 9, 0, 0) # Monday 1/9/2012
person juliomalegria    schedule 03.01.2012
comment
Я должен уточнить, что использовал понедельник и среду в качестве общего примера. Повтор может быть любой комбинацией дней. Например, понедельник, четверг, суббота. Так что это не сработает. - person Jon; 03.01.2012

Используйте dateutil для работы с расписанием и повторениями.

person warvariuc    schedule 03.01.2012