【问题标题】:rrule in future but relative to this morning未来的规则,但相对于今天早上
【发布时间】:2013-05-01 14:59:48
【问题描述】:

我正在尝试计算符合一些简单规则的下一个时间点。

仅包括列表中提到的工作日(在下面的示例中,周一至周五)。仅返回列出的时间(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,这似乎与当前时间有关。

谁能告诉我如何让规则使用相对于午夜的时间但在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)

【问题讨论】:

  • 你能给出一些期望输出的例子吗(给定After的明确值)?
  • @unutbu 完成 - 希望更清楚?

标签: python rrule python-dateutil


【解决方案1】:

我想你正在寻找bysetpos = 1。此参数导致rrule 返回一组匹配项中位于“位置 1”的日期时间。 “位置 1”相对于byweekdaybyhourbyminutebysecond 等。因此通过设置byminute=0bysecond=0,以及bysetpos=1rrule 总是返回小时 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

【讨论】:

    【解决方案2】:

    您应该将 dtstart 与 minutes=0 和 seconds=0 一起使用,或者自己从返回的值中删除时间。

    因为这是 rrule 的预期工作方式 - 它为传递的 dtstart 添加了一些间隔,在您的情况下包括分钟和秒。

    【讨论】:

    • 我无法从dtstart 中删除分钟/秒,因为这可能会导致过去的“命中”。虽然从输出中剥离它们是一种选择
    • 你可以通过dtstart来传递最近的一个小时
    猜你喜欢
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-14
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    相关资源
    最近更新 更多