规则日期偏移一周

rrule dates are offset by a week

我在使用 python-dateutil rrule 模块时得到了意外的结果,我想知道这是否是 WAI。

我正在动态创建 rrule 使用:

dtstart = datetime.date(2019, 1, 7)
until = datetime.date(2029, 11, 29)
freq = MONTHLY
byweekday=MO(2)
interval = 4

这导致以下规则

DTSTART:20190107T000000
RRULE:FREQ=MONTHLY;INTERVAL=4;UNTIL=20291129T000000;BYDAY=+2MO

但是,在生成日期时(循环此 python 模块的规则),我得到以下日期:

 [datetime.datetime(2019, 1, 14, 0, 0),
 datetime.datetime(2019, 5, 13, 0, 0),
 datetime.datetime(2019, 9, 9, 0, 0),
 datetime.datetime(2020, 1, 13, 0, 0),
 datetime.datetime(2020, 5, 11, 0, 0),
 datetime.datetime(2020, 9, 14, 0, 0),
 datetime.datetime(2021, 1, 11, 0, 0),
 datetime.datetime(2021, 5, 10, 0, 0),
 datetime.datetime(2021, 9, 13, 0, 0),
 datetime.datetime(2022, 1, 10, 0, 0),
 datetime.datetime(2022, 5, 9, 0, 0),
 datetime.datetime(2022, 9, 12, 0, 0),
 datetime.datetime(2023, 1, 9, 0, 0),
 datetime.datetime(2023, 5, 8, 0, 0),
 datetime.datetime(2023, 9, 11, 0, 0),
 datetime.datetime(2024, 1, 8, 0, 0),
 datetime.datetime(2024, 5, 13, 0, 0),
 datetime.datetime(2024, 9, 9, 0, 0),
 datetime.datetime(2025, 1, 13, 0, 0),
 datetime.datetime(2025, 5, 12, 0, 0),
 datetime.datetime(2025, 9, 8, 0, 0),
 datetime.datetime(2026, 1, 12, 0, 0),
 datetime.datetime(2026, 5, 11, 0, 0),
 datetime.datetime(2026, 9, 14, 0, 0),
 datetime.datetime(2027, 1, 11, 0, 0),
 datetime.datetime(2027, 5, 10, 0, 0),
 datetime.datetime(2027, 9, 13, 0, 0),
 datetime.datetime(2028, 1, 10, 0, 0),
 datetime.datetime(2028, 5, 8, 0, 0),
 datetime.datetime(2028, 9, 11, 0, 0),
 datetime.datetime(2029, 1, 8, 0, 0),
 datetime.datetime(2029, 5, 14, 0, 0),
 datetime.datetime(2029, 9, 10, 0, 0)]

注意第一个日期偏移了一周!为什么会这样?这是库中的错误吗?

谢谢, 大卫

不是库中的错误。 2019-01-14 是符合您的规则的第一个日期(即 2019 年 1 月的第二个星期一)。显然 python-dateutil 选择不包括您提供的开始日期,这是完全合法的。

RRULERFC 5545, which states in Section 3.8.5.3 中指定(在“描述”下):

The recurrence set generated with a "DTSTART" property value not synchronized with the recurrence rule is undefined.

这基本上意味着没有正确或错误的解释,因为如果开始日期与规则不匹配,输入数据就会“损坏”。

注意,许多其他实现可能 return 两者,您的开始日期 2019-01-07 结果 2019-01-14。我认为任何实施都不会省略 2019-01-14,仅仅是因为它是符合规则的第一个日期。开始日期 2019-01-07 是否应该出现在结果中还有待商榷,但 2019-01-14 肯定应该出现在结果中。

在Python中by_weekly代码可以这样实现。

from calendar import isleap

from datetime import datetime
from dateutil.rrule import rrule, DAILY, WEEKLY, MONTHLY 

def bi_weekly(start_date=datetime.now(),count=53,interval=2):
    """
      dateTImeSart = bi_weekly(datetime.strptime('2021-01-01', '%Y-%m-%d'),53)
      print(dateTImeSart[0].strftime("%Y-%m-%d"))
      print(dateTImeSart[1].strftime("%Y-%m-%d"))
      print(dateTImeSart[50].strftime("%Y-%m-%d"))
      print(dateTImeSart[51].strftime("%Y-%m-%d"))
      print(dateTImeSart[52].strftime("%Y-%m-%d"))
      2021-01-01
      2021-01-15
      2022-12-02
      2022-12-16
      2022-12-30
    """
    # returns the datetime for an year and calculates them for 1 By weekly
    return list(rrule(WEEKLY, count=count,interval=interval, dtstart=start_date))