Интерпретация YEARLY RRULE при наличии более чем одного из BYMONTH, BYWEEKNO, BYYEARDAY

В настоящее время я борюсь с деталями интерпретации RFC 5545. В разделе 3.3.10 говорится, что, по сути, все BYxxx поля показывают расширяющееся поведение, за исключением BYDAY, который имеет конкретные правила, в зависимости от которых BYxxx поля на самом деле присутствуют.

Однако мне неясно, что именно должно произойти для RRULE который указывает более одного из { BYMONTH, BYWEEKNO, BYYEARDAY }. По моему мнению, таблица в Разделе 3.3.10 позволяет интерпретировать, что я должен расширить каждую часть правила отдельно, то есть построить объединение трех наборов, полученных в результате

  1. расширяющийся BYMONTH, BYMONTHDAY и т.п.
  2. расширяющийся BYWEEKNO
  3. расширяющийся BYYEARDAY

все время чтить Примечание 2, которое объясняет BYDAY поведение. Результат может быть несколько нелогичным (и, конечно, маловероятно, что пользователи будут указывать такие правила). Но есть по крайней мере одна реализация, которая утверждает, что делает это следующим образом:

Для YEARLY частота, BYMONTH, BYWEEKNO, а также BYYEARDAY правила раскрываются отдельно друг от друга, если указано.

Другие реализации, такие как http://recurrence-expansion-service.appspot.com/ или Календарь Google, по-видимому, используют стратегию ограничения, если присутствует более одной части правила:

  1. расширять BYMONTH / BYMONTHDAY
  2. Затем ограничить использование BYWEEKNO а также BYYEARDAY

эффективно создавать пересечение, а не союз. Такой подход выглядит в некоторой степени совместимым с порядком применения для частей правила, предусмотренных в разделе 3.3.10:

Если несколько BYxxx части правила указываются, затем после оценки указанного FREQ а также INTERVAL части правила, BYxxx Части правила применяются к текущему набору оцененных вхождений в следующем порядке: BYMONTH, BYWEEKNO, BYYEARDAY, BYMONTHDAY, BYDAY, BYHOUR, BYMINUTE, BYSECOND а также BYSETPOS; затем COUNT а также UNTIL оцениваются.

Однако интерпретация этого как означающего, что части правила ограничивают, а не расширяют, как мне кажется, находится в прямом противоречии с таблицей расширения / ограничения, показанной на стр. 44 стандарта.

Мой вопрос таков:

Действительно ли RFC5545 однозначно указывает, каким образом одновременное присутствие более одного BYMONTH , BYWEEKNO а также BYYEARDAY должен быть интерпретирован? Если да, то где это указано? И если стандарт на самом деле неясен в этом отношении, существует ли "стандарт де-факто", предпочтительный способ решения этой ситуации?

1 ответ

Решение

Действительно ли RFC5545 однозначно определяет, как следует интерпретировать одновременное присутствие более чем одного из BYMONTH, BYWEEKNO и BYYEARDAY?

Ну да, в отрывке, который вы цитировали в своем вопросе: они применяются к текущему набору оцененных вхождений по порядку.

Термин " текущий набор оцененных вхождений" является ключевой частью предложения. Например, давайте возьмем правило с BYMONTH и BYYEARDAY.

  1. BYMONTH оценивается в первую очередь, генерируя набор вхождений (расширяется на ЧАСТОТНУЮ ЧАСТОТУ, т. Е. В наборе может быть более одного вхождения в год)
  2. только тогда BYYEARDAY применяется только к тем вхождениям, то есть вхождениям, которые соответствуют BYMONTH. Каждый год, который не соответствует BYMONTH, не учитывается, поскольку он по определению не является частью текущего набора вхождений, рассчитанного на шаге 1.

Таблица расширения / ограничения не имеет значения в этом случае. RFC очень четко заявляет:

"В таблице ниже приведены зависимости расширения или ограничения части правила BYxxx от значения части правила FREQ".

Таблица не суммирует поведение части правила BYxxx в других частях правила BYxxx.

Следовательно, это однозначно пересечение. Подумайте об этом так: если бы результат был объединением, не было бы никакого способа написать такие правила, как "каждый день 5-й недели года, которая в феврале" (FREQ=YEARLY;BYWEEKNO=5;BYMONTH=2).

Чтобы достичь объединения, RFC определяет набор повторений, который просто объединяет несколько RRULE, RDATE и EXDATE (хотя по какой-то причине RFC утверждает, что RRULE не должен появляться более одного раза).

И если стандарт на самом деле неясен в этом отношении, существует ли "стандарт де-факто", предпочтительный способ решения этой ситуации?

Я поддерживаю php-rrule, который является портом Python dateutil, и именно так обе версии справляются с этой ситуацией. Насколько я помню, библиотеки Javascript и Ruby также работают таким образом. Я не знаю ни о каких других библиотеках, которые есть, но RFC в любом случае достаточно ясен, как я надеюсь, я продемонстрировал выше.

Редактировать: ответ на ваш комментарий о BYDAY

Примечание 2 к таблице может быть довольно запутанным, поэтому здесь есть небольшое пояснение. BYDAY особенный, потому что он имеет 2 синтаксиса: простой с названием дня (например, MO, TU и так далее) и "сложный" с названием дня и положением в наборе. Например 1MO означает "первый понедельник" и -1MO "последний понедельник". Однако вопрос "первый / последний понедельник чего?".

  • При использовании ГОДОВОЙ частоты и BYDAY=1MO,2MOэто "первый и второй понедельник года", при использовании "ЕЖЕМЕСЯЧНО" это "первый и второй понедельник месяца" и т. д., это довольно просто.
  • Однако при использовании ЧЕСТНОЙ частоты и BYMONTH=2,3 например, тогда правило фактически означает "каждый февраль и март", поэтому возникает вопрос: должны ли вы получать каждый первый и второй понедельник февраля и марта (развернуть) или каждый первый и второй понедельник года, которые происходят в феврале и марте - т.е. пустой набор, так как оба в январе (предел). Ответ заключается в том, чтобы сделать "специальное расширение", фактически рассматривая его как "ЕЖЕМЕСЯЧНУЮ" частоту (даже если она ГОДНУЮ) и, следовательно, значение BYDAY=1MO,2MO меняется на "каждый первый и второй понедельник февраля И каждый первый и второй понедельник марта".

Цитировать соответствующую часть RFC

Числовое значение в части правила BYDAY с частью правила FREQ, установленной в YEARLY, соответствует смещению в течение месяца, когда присутствует часть правила BYMONTH, и соответствует смещению в течение года, когда присутствуют части правила BYWEEKNO или BYMONTH.

Честно говоря, я не уверен, почему существует такой особый случай для BYDAY, но в любом случае совершенно ясно, как он должен себя вести.

Другие вопросы по тегам