当BYMONTH,BYWEEKNO,BYYEARDAY不止一个人出现时,每年的RRULE解释

问题描述 投票:0回答:1

我目前正在努力解决RFC 5545的解释细节.Section 3.3.10表示,基本上,所有BYxxx字段都显示出扩展行为,除了BYDAY,它具有特定的规则,具体取决于实际存在的BYxxx字段。

然而,我不清楚一个RRULE究竟应该发生什么,它指定了{BYMONTHBYWEEKNOBYYEARDAY}中的一个以上。在我看来,第3.3.10节中的表允许我必须分别扩展每个规则部分的解释,即构建由此产生的三个集合的并集。

  1. 扩大BYMONTHBYMONTHDAY等。
  2. 扩大BYWEEKNO
  3. 扩大BYYEARDAY

一直在纪念注释2解释BYDAY行为。结果可能有点违反直觉(当然用户很可能不会指定这样的规则)。但是至少有一个实现claims to do it this way

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

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

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

有效地创造一个交集而不是一个联合。这种方法似乎与第3.3.10节规定的规则部分的申请顺序一致:

如果指定了多个BYxxx规则部分,那么在评估指定的FREQINTERVAL规则部分之后,BYxxx规则部分将按以下顺序应用于当前评估事件集:BYMONTHBYWEEKNOBYYEARDAYBYMONTHDAYBYDAYBYHOURBYMINUTEBYSECONDBYSETPOS;然后对COUNTUNTIL进行评估。

然而,解释这意味着规则部分是限制而不是扩展在我看来与page 44 of the standard上显示的扩展/限制表直接矛盾。

我的问题是:

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

icalendar rrule
1个回答
2
投票

RFC5545是否实际上明确指定了如何同时存在BYMONTH,BYWEEKNO和BYYEARDAY中的多个BYMONTH,BYWEEKNO和BYYEARDAY?

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

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

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

在这种情况下,扩展/限制表是无关紧要的。 RFC非常清楚地说明:

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

该表未概述BYxxx规则部分对其他BYxxx规则部分的行为。

因此,它是一个明确的交叉点。想一想:如果结果是一个联盟,就没有办法写出诸如“二月的第五周的每一天”(FREQ=YEARLY;BYWEEKNO=5;BYMONTH=2)等规则。

为了实现联合,RFC定义了一个递归集,它简单地组合了多个RRULE,RDATE和EXDATE(尽管由于某种原因,RFC声明RRULE不应出现多次)。

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

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

Edit: answer to your comment about BYDAY

表格的注释2确实很混乱,所以这里有一点澄清。 BYDAY是特殊的,因为它有2种语法:简单的一种具有当天的名称(例如MOTU等)和“复杂的”语法,其中包含日期的名称和集合中的位置。例如,1MO的意思是“第一个星期一”,-1MO是“最后一个星期一”。然而问题是“什么的第一个/最后一个星期一?”。

  • 当使用YEARLY频率和BYDAY=1MO,2MO时,它是“一年中的第一个和第二个星期一”,当使用MONTHLY时它是“本月的第一个和第二个星期一”,依此类推,这非常简单。
  • 然而,当使用YEARLY频率和BYMONTH=2,3为例时,规则实际上意味着“每个二月和三月”所以问题是:如果你得到2月和3月的每个第一和第二个星期一(扩展),或者每个第一个和第二个星期一2月和3月发生的年份 - 即空集,因为两者都在1月(限制)。答案是通过实际将其视为“每月”频率进行“特殊扩展”(即使它是年度),因此BYDAY=1MO,2MO的含义变为“2月的每个第一个和第二个星期一以及每个第一个和第二个星期一March`。

引用RFC的相关部分

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

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

© www.soinside.com 2019 - 2024. All rights reserved.