没有 BYMONTH 值的 iCalendar YEARLY 规则

iCalendar YEARLY rrule without BYMONTH value

我正在构建一个接受 icalendar 事件并计算所有重复事件发生的东西。

我发现了一个问题,每个月 returns 我都会遇到一些年度事件。 这些事件具有每年的频率,但只有 bymonthday 没有 bymonth 值。

这是在 RFC-5545 中指定的,还是这只是我的日历工具的一个错误。 (PS:这实际上在我的 Google 日历中并且此事件在那里正确显示)

BEGIN:VEVENT
DTSTART;VALUE=DATE:20110814
DTEND;VALUE=DATE:20110815
RRULE:FREQ=YEARLY;BYMONTHDAY=14
DTSTAMP:20170328T223152Z 
UID:388B4AE8602346DAA7BD9C1906FC390200000000000000000000000000000000
CREATED:20110610T073603Z
DESCRIPTION:
LAST-MODIFIED:20160811T230008Z
LOCATION:
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Some BDAY
TRANSP:OPAQUE
CATEGORIES:http://schemas.google.com/g/2005#event
BEGIN:VALARM
ACTION:AUDIO
TRIGGER:-P1DT15H
ACKNOWLEDGED:20160811T230006Z
ATTACH;VALUE=URI:Basso
UID:26C6C0F7-8B77-4E20-8EFD-E82A614B0751
X-WR-ALARMUID:26C6C0F7-8B77-4E20-8EFD-E82A614B0751
END:VALARM
BEGIN:VALARM
ACTION:NONE
TRIGGER;VALUE=DATE-TIME:19760401T005545Z
END:VALARM
END:VEVENT

在 RFC 5545 中 - page 44 确切地说 - BYMONTHDAY 被指定为 扩展 年度规则,即生成更多结果,仅每年 1 个。

此外,在 the next page 上,它给出了一个必须如何评估规则的示例:

DTSTART;TZID=America/New_York:19970105T083000
  RRULE:FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=SU;BYHOUR=8,9;
  BYMINUTE=30

First, the "INTERVAL=2" would be applied to "FREQ=YEARLY" to arrive at "every other year". Then, "BYMONTH=1" would be applied to arrive at "every January, every other year". Then, "BYDAY=SU" would be applied to arrive at "every Sunday in January, every other year". Then, "BYHOUR=8,9" would be applied to arrive at "every Sunday in January at 8 AM and 9 AM, every other year". Then, "BYMINUTE=30" would be applied to arrive at "every Sunday in January at 8:30 AM and 9:30 AM, every other year".

如您所见,即使 FREQ 是 YEARLY,该规则也会 return“每隔一年一月的每个星期日上午 8 点和上午 9 点”,即每两年出现一次以上。简而言之,就是扩展 FREQ 行为的概念。

现在应用此规则:

RRULE:FREQ=YEARLY;BYMONTHDAY=14

意思是“每年的每月十四号”。所以你每年会得到12次。

编辑:也就是说,在重新阅读RFC之后,BYMONTHDAY的定义是:

The BYMONTHDAY rule part specifies a COMMA-separated list of days of the month.

这可以解释为“ 月的天数列表”,如“只有 月指定 DTSTART 属性”。然而,这种解释对于 FREQ 的其他值(MONTHLY、DAILY 等)没有意义,因此这只是 FREQ=YEARLY 和 BYMONTH 缺失的特殊情况……我个人认为这是不正确的,但是我必须承认 RFC 有点模棱两可。

不幸的是,没有任何 BYMONTHDAY 的 FREQ=YEARLY 没有 BYMONTH 的例子,所以没有明确明确的答案

结论:为避免任何问题,如果您只想要“给定月份的 14 号”,则应添加 BYMONTH

回复您的评论

规则“FREQ=MONTHLY;BYMONTHDAY=14”确实产生了相同的结果。 INTERVAL 大于 1 或其他 BYxxx 时会出现差异。

IMO FREQ=YEARLY;BYMONTHDAY=14 应该在每年的 8 月 14 日只生成一个事件。

RFC 5545, page 42 说:

Information, not contained in the rule, necessary to determine the various recurrence instance start time and dates are derived from the Start Time ("DTSTART") component attribute. For example, "FREQ=YEARLY;BYMONTH=1" doesn't specify a specific day within the month or a time. This information would be the same as what is specified for "DTSTART".

所以在您的情况下,规则没有指定月份,因此它是从开始日期继承的。你的情况是八月。

查看我们的图书馆为此事件生成的实例:FREQ=YEARLY;BYMONTHDAY=14