Как рассчитать следующую пятницу в 3 часа ночи?

Как вы можете рассчитать следующую пятницу в 3 часа ночи как объект datetime ?

Уточнение: т. Е. Расчетная дата всегда должна быть больше 7 дней, и меньше или равна 14.


Переход со слегка измененной версией решения Марка :

 def _next_weekday(day_of_week=4, time_of_day=datetime.time(hour=3), dt=None): if dt is None: dt = datetime.datetime.now() dt += datetime.timedelta(days=7) if dt.time() < time_of_day: dt = dt.combine(dt.date(), time_of_day) else: dt = dt.combine(dt.date(), time_of_day) + datetime.timedelta(days=1) return dt + datetime.timedelta((day_of_week - dt.weekday()) % 7) 

Вот функция и тест, который соответствует требованиям OP:

 import datetime _3AM = datetime.time(hour=3) _FRI = 4 # Monday=0 for weekday() def next_friday_3am(now): now += datetime.timedelta(days=7) if now.time() < _3AM: now = now.combine(now.date(),_3AM) else: now = now.combine(now.date(),_3AM) + datetime.timedelta(days=1) return now + datetime.timedelta((_FRI - now.weekday()) % 7) if __name__ == '__main__': start = datetime.datetime.now() for i in xrange(7*24*60*60): now = start + datetime.timedelta(seconds=i) then = next_friday_3am(now) assert datetime.timedelta(days=7) < then - now <= datetime.timedelta(days=14) assert then.weekday() == _FRI assert then.time() == _3AM 

Если вы установите dateutil , вы можете сделать что-то вроде этого:

 import datetime import dateutil.relativedelta as reldate def following_friday(dt): rd=reldate.relativedelta( weekday=reldate.FR(+2), hours=+21) rd2=reldate.relativedelta( hour=3,minute=0,second=0,microsecond=0) return dt+rd+rd2 

Выше, hours=+21 говорят relativedelta чтобы увеличить dt на 21 час, прежде чем найти следующую пятницу. Итак, если dt – 12 марта 2010 года в 2 часа ночи, добавление 21 часа составляет 11 вечера того же дня , но если dt после 3 часов, то добавление 21 часа нажимает dt в субботу.

Вот несколько тестовых кодов.

 if __name__=='__main__': today=datetime.datetime.now() for dt in [today+datetime.timedelta(days=i) for i in range(-7,8)]: print('%s --> %s'%(dt,following_friday(dt))) 

который дает:

 2010-03-05 20:42:09.246124 --> 2010-03-19 03:00:00 2010-03-06 20:42:09.246124 --> 2010-03-19 03:00:00 2010-03-07 20:42:09.246124 --> 2010-03-19 03:00:00 2010-03-08 20:42:09.246124 --> 2010-03-19 03:00:00 2010-03-09 20:42:09.246124 --> 2010-03-19 03:00:00 2010-03-10 20:42:09.246124 --> 2010-03-19 03:00:00 2010-03-11 20:42:09.246124 --> 2010-03-19 03:00:00 2010-03-12 20:42:09.246124 --> 2010-03-26 03:00:00 2010-03-13 20:42:09.246124 --> 2010-03-26 03:00:00 2010-03-14 20:42:09.246124 --> 2010-03-26 03:00:00 2010-03-15 20:42:09.246124 --> 2010-03-26 03:00:00 2010-03-16 20:42:09.246124 --> 2010-03-26 03:00:00 2010-03-17 20:42:09.246124 --> 2010-03-26 03:00:00 2010-03-18 20:42:09.246124 --> 2010-03-26 03:00:00 2010-03-19 20:42:09.246124 --> 2010-04-02 03:00:00 

а до 3 утра:

 two = datetime.datetime(2010, 3, 12, 2, 0) for date in [two+datetime.timedelta(days=i) for i in range(-7,8)]: result = following_friday(date) print('{0}-->{1}'.format(date,result)) 

выходы:

 2010-03-05 02:00:00-->2010-03-12 03:00:00 2010-03-06 02:00:00-->2010-03-19 03:00:00 2010-03-07 02:00:00-->2010-03-19 03:00:00 2010-03-08 02:00:00-->2010-03-19 03:00:00 2010-03-09 02:00:00-->2010-03-19 03:00:00 2010-03-10 02:00:00-->2010-03-19 03:00:00 2010-03-11 02:00:00-->2010-03-19 03:00:00 2010-03-12 02:00:00-->2010-03-19 03:00:00 2010-03-13 02:00:00-->2010-03-26 03:00:00 2010-03-14 02:00:00-->2010-03-26 03:00:00 2010-03-15 02:00:00-->2010-03-26 03:00:00 2010-03-16 02:00:00-->2010-03-26 03:00:00 2010-03-17 02:00:00-->2010-03-26 03:00:00 2010-03-18 02:00:00-->2010-03-26 03:00:00 2010-03-19 02:00:00-->2010-03-26 03:00:00 

Мне нравятся даты для таких задач в целом, но я не понимаю эвристики, которые вы хотите – поскольку я использую слова, если я говорю «в следующую пятницу», и в четверг я буду иметь в виду завтра (возможно, я слишком много работал и потерял след в тот день недели). Если вы можете точно указать свою эвристику, они, безусловно, могут быть запрограммированы, но если они странные и причудливые, вы вряд ли найдете их уже запрограммированными для вас в существующих пакетах ;-).

Основываясь на вашем разъяснении … Я думаю, вы можете сделать что-то вроде этого:

 from datetime import * >>> today = datetime.today() >>> todayAtThreeAm = datetime(today.year, today.month, today.day, 3) >>> todayAtThreeAm datetime.datetime(2010, 3, 12, 3, 0) >>> nextFridayAtThreeAm = todayAtThreeAm + timedelta(12 - today.isoweekday()) >>> nextFridayAtThreeAm datetime.datetime(2010, 3, 19, 3, 0) 

Уведомление isoweekday() возвращает 1 к 7 в понедельник в воскресенье. 12 – пятница на следующей неделе. Итак, 12 – today.isoweekday () дает вам правильную временную дельту, которую вы должны добавить к сегодняшнему дню.

Надеюсь это поможет.