【问题标题】:YEARLY RRULE interpretation when more than one of BYMONTH, BYWEEKNO, BYYEARDAY are present当出现 BYMONTH、BYWEEKNO、BYYEARDAY 中的一个以上时的 YEARLY RRULE 解释
【发布时间】:2018-01-03 18:07:04
【问题描述】:

我目前正在为 RFC 5545 的解释细节而苦苦挣扎。Section 3.3.10 指出,基本上,所有BYxxx 字段都显示扩展 行为,BYDAY 除外,它具有具体规则,具体取决于BYxxx 字段实际上存在于其上。

但是,我不清楚对于指定 多个 {BYMONTHBYWEEKNOBYYEARDAY} 的 RRULE 究竟应该发生什么。在我看来,第 3.3.10 节中的表格允许我必须分别扩展每个规则部分的解释,也就是说,构建由

产生的三个集合的并集
  1. 扩展BYMONTHBYMONTHDAY
  2. 扩展BYWEEKNO
  3. 扩展BYYEARDAY

始终尊重解释 BYDAY 行为的注释 2。结果可能有点违反直觉(当然,用户不太可能指定此类规则)。但至少有一种实现是claims to do it this way

对于 YEARLY 频率,BYMONTHBYWEEKNOBYYEARDAY 规则在指定时彼此分开扩展。

如果存在多个规则部分,其他实现(例如 http://recurrence-expansion-service.appspot.com/ 或 Google 日历)似乎使用限制策略:

  1. 展开BYMONTH/BYMONTHDAY
  2. 然后限制使用BYWEEKNOBYYEARDAY

有效地创建交叉而不是联合。这种方法似乎与第 3.3.10 节规定的规则部分的应用顺序有些一致:

如果指定了多个 BYxxx 规则部分,则在评估后 指定的FREQINTERVAL 规则部分,BYxxx 规则部分 应用于当前的一组评估事件中 以下顺序:BYMONTHBYWEEKNOBYYEARDAYBYMONTHDAYBYDAYBYHOURBYMINUTEBYSECONDBYSETPOS;然后COUNTUNTIL 是 评估。

但是,将其解释为规则部分是 limiting 而不是 expanding 在我看来与 @987654324 上显示的扩展/限制表直接矛盾@。

因此我的问题是:

RFC5545 是否真的明确规定了如何解释BYMONTHBYWEEKNOBYYEARDAY 中的多个同时存在?如果有,在哪里说明?如果标准在这方面实际上并不清楚,是否有“事实上的标准”首选方式来处理这种情况?

【问题讨论】:

    标签: icalendar rrule


    【解决方案1】:

    RFC5545 是否真的明确规定了如何解释同时存在的多个 BYMONTH、BYWEEKNO 和 BYYEARDAY?

    是的,在您在问题中引用的摘录中:它们按顺序应用于当前的评估事件集

    当前评估的事件集是句子的关键部分。例如,让我们采用 BYMONTH 和 BYYEARDAY 的规则。

    1. 首先评估 BYMONTH,生成一组出现次数(在 YEARLY 频率上扩展,即该组中每年可以出现一次以上)
    2. 然后 BYYEARDAY 应用于仅那些出现,即匹配 BYMONTH 的出现。不考虑与 BYMONTH 不匹配的每一天,因为根据定义,它不是步骤 1 中计算的当前事件集的一部分。

    在这种情况下,扩展/限制表无关紧要。 RFC 非常明确地指出:

    "下表总结了 BYxxx 规则部分扩展或限制行为对 FREQ 规则部分值的依赖性。"

    该表没有总结了 BYxxx 规则部分的行为在其他 BYxxx 规则部分上

    因此,它无疑是一个交叉点。这么想:如果结果是一个联合,就没有办法编写诸如“一年中第 5 周的每一天在二月”之类的规则 (FREQ=YEARLY;BYWEEKNO=5;BYMONTH=2)。

    为了实现 union,RFC 定义了一个 recurrence set,它简单地结合了多个 RRULE、RDATE 和 EXDATE(尽管出于某种原因,RFC 声明 RRULE 不应出现多次)。

    如果标准在这方面实际上并不清楚,是否有“事实上的标准”首选方式来处理这种情况?

    我是 php-rrule 的维护者,它是 Python dateutil 的一个端口,这就是两个版本处理这种情况的方式。据我记得,Javascript 和 Ruby 库也以这种方式工作。我不知道那里的所有其他库,但无论如何,RFC 都很清楚,我希望我已经在上面演示过。

    编辑:回答您关于 BYDAY 的评论

    表中的注释 2 确实很令人困惑,所以在这里做一点澄清。 BYDAY 之所以特别,是因为它有两种语法:一种是简单的带有日期名称的语法(例如MOTU 等等),而“复杂的”一种是带有日期名称的and 集合中的位置。例如,1MO 表示“第一个星期一”,-1MO 表示“最后一个星期一”。然而问题是“什么的第一个/最后一个星期一?”。

    • 当使用 YEARLY 频率和BYDAY=1MO,2MO 时,它是“一年中的第一个和第二个星期一”,当使用 MONTHLY 时,它是“一个月的第一个和第二个星期一”等等,这很漂亮直截了当。
    • 但是,例如,当使用 YEARLY 频率 BYMONTH=2,3 时,规则实际上意味着“每年二月和三月”,所以问题是:您是否应该在二月和三月的每个第一个和第二个星期一获得(展开),或在 2 月和 3 月发生的每个第一个和第二个星期一 - 即空集,因为两者都在 1 月(限制)。答案是通过实际将其视为“每月”频率(即使是每年)来进行“特殊扩展”,因此BYDAY=1MO,2MO 的含义更改为“2 月的第一个和第二个星期一以及每个第一个和第二个星期一三月的星期一`。

    引用 RFC 的相关部分

    a 中的数值 FREQ 规则部分设置为 YEARLY 的 BYDAY 规则部分对应 到 BYMONTH 规则部分的月份内的偏移量 存在,并且对应于当年度内的偏移量 存在 BYWEEKNO 或 BYMONTH 规则部分。

    老实说,我不确定为什么 BYDAY 会有这种特殊情况,但无论如何它应该如何表现是很清楚的。

    【讨论】:

    • 非常感谢,这是有道理的,正如我所料。您对 union 假设的反例正是让我提出这个问题的那种案例。我的困惑源于这样一个事实:BYDAY 部分确实根据表上的注释 2 扩展了其他 BYxxx 部分,而其他 BYxxx 部分实际上具有更多的限制行为。那是我太专注于桌子的结果。感谢您指出关键短语。
    • @mindriot 不用担心,很高兴我能帮上忙。我想回答你关于 BYDAY 的评论,但评论有点太长了,所以我编辑了我的答案。 BYDAY 确实是一种特殊情况,处理方式略有不同。
    • 还有一个问题:规范的哪一部分允许您得出结论FREQ=YEARLY;BYWEEKNO=5;BYMONTH=2 包含所有第 5 周和 2 月的日子?从spec on page 43,倒数第二段,我预计日期(和时间)取自DTSTART,因为周数并不能清楚地确定实际日期。在这种情况下,我找不到任何表明我们必须扩展到 all 天的内容。事实上,虽然 Google 和 dateutil 扩展到所有天,但 Thunderbird Lightning 并没有。
    • 顺便说一下,关于您最后的报价的一个小问题:rfc-editor.org/errata_search.php?rfc=5545&eid=1913
    • @mindriot RFC 不清楚应该从DTSTART 中提取哪些信息以及在什么情况下,这无疑是可以解释的。我的推理与您最初的问题相同:如果它不包含 all 一周中的几天,那么您将如何编写规则来匹配“X 周的所有天”?跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-15
    相关资源
    最近更新 更多