правило в будущем, но по отношению к сегодняшнему утру

Я пытаюсь рассчитать следующий момент времени, который соответствует некоторым простым правилам.

Включайте только дни недели, указанные в списке (в приведенном ниже примере — с понедельника по пятницу). Возвращает только те часы, которые указаны в списке (12:00, 18:00).

Я хочу получить первую такую ​​точку, начиная с указанной даты After.

Я дошел до этого, но он возвращает «неокругленное» время, которое кажется постоянным смещением от текущего времени.

def NextRunTime(After=django.utils.timezone.now()):
    Sched = {'Hours': [12,18], 'Days': [0,1,2,3,4]}
    rule = DateRule.rrule(DateRule.HOURLY,
                byweekday=Sched['Days'],
                byhour=Sched['Hours'],
                dtstart=After,
                count=1)
    return rule[0]

В настоящее время он возвращает 2013-05-01 18:53:39+01, что, по-видимому, относится к текущему времени суток.

Может ли кто-нибудь сказать мне, как я могу заставить rrule использовать время относительно полуночи, но возвращать даты после After?

Явные примеры желаемого результата

After           Output
Mon 10:11:12    Mon 12:00:00
Mon 11:22:33    Mon 12:00:00
Mon 12:00:01    Mon 18:00:00
Fri 12:00:01    Fri 18:00:00
Fri 18:00:01    Mon 12:00:00 (Following Monday)

person Basic    schedule 01.05.2013    source источник
comment
Можете ли вы привести несколько примеров желаемого вывода (учитывая явные значения для After)?   -  person unutbu    schedule 01.05.2013
comment
@unutbu Готово - надеюсь, стало понятнее?   -  person Basic    schedule 01.05.2013


Ответы (2)


Я думаю, вы ищете bysetpos = 1. Этот параметр заставляет rrule возвращать дату и время, которые находятся в «позиции 1» в наборе совпадений. «позиция 1» относится к byweekday, byhour, byminute, bysecond и т. д. Таким образом, при установке byminute=0 и bysecond=0, а также bysetpos=1, rrule всегда возвращает 12 или 18 час:

import dateutil.rrule as DateRule
import datetime as DT

def NextRunTime(After):
    Sched = {'Hours': [12,18], 'Days': [0,1,2,3,4]}
    rule = DateRule.rrule(DateRule.HOURLY,
                          byweekday=Sched['Days'],
                          byhour=Sched['Hours'],
                          byminute=0,
                          bysecond=0,
                          bysetpos=1,
                          # dtstart=After means rule might return After
                          dtstart=After,
                          # To ensure NextRunTime returns something after After, use
                          # dtstart=After+DT.timedelta(seconds=1), 
                          count=1)
    return rule[0]

tests = [
    (DT.datetime(2013,4,29,10,11,12),
     DT.datetime(2013,4,29,12,0,0)),
    (DT.datetime(2013,4,29,11,22,33),
     DT.datetime(2013,4,29,12,0,0)),
    (DT.datetime(2013,4,29,12,0,1),
     DT.datetime(2013,4,29,18,0,0)),
    (DT.datetime(2013,5,3,12,0,1),
     DT.datetime(2013,5,3,18,0,0)),
    (DT.datetime(2013,5,3,18,0,1),
     DT.datetime(2013,5,6,12,0,0)),
    (DT.datetime(2013,4,29,12,0,0),  # Note that NextRunTime(After) returns After
     DT.datetime(2013,4,29,12,0,0)),
    ]

for After, answer in tests:
    result = NextRunTime(After)
    try:
        assert result == answer
    except AssertionError:
        print('''\
result:
{result}
answer:
{answer}
'''.format(**locals()))
        raise
person unutbu    schedule 01.05.2013

Вы должны либо использовать dtstart с минутами = 0 и секундами = 0, либо самостоятельно вырезать время из возвращаемого значения.

Поскольку ожидается, что именно так будет работать rrule - он добавляет некоторые интервалы к переданному dtstart, который в вашем случае включает минуты и секунды.

person warvariuc    schedule 01.05.2013
comment
Я не могу вырезать минуты/секунды из dtstart, так как это может привести к попаданию в прошлое. Однако удаление их из вывода является вариантом. - person Basic; 01.05.2013
comment
Вы можете передать ближайший час в будущем как dtstart - person warvariuc; 01.05.2013