Search code examples
icalendarrrule

RRULE for first Advent


I am currently trying to setup my own holiday iCalendar to which I can subscribe on, since I don't want to depend on 3rd party services.

I am currently trying to make the the VEVENTs for Christmas. The 2nd, 3rd and 4th advent, as well as the Christmas holidays are straight forward, however I have big issues to model the 1st advent.

Specifically, the problem is that the first advent can be in November and December (27th November to 3rd Devember)

How can I make a recurring event (or, more specifically, the RRULE) to cover all cases for the 1st advent?

What I've tried


My first idea was this:

FREQ=YEARLY;INTERVAL=1;BYMONTH=11,12;BYMONTHDAY=27,28,29,30,1,2,3;BYDAY=SU

The idea was to just pick the one Sunday in between 27th November and 3rd December. This does of course not work because BYMONTH expands the search to all days in November and December, and BYMONTHDAY limits the search to those days in both months. I.e. November 1st, November 2nd, ... December 27th, December 28th, ..., which is of course not what I want.


Next, I tried to use BYYEARDAY=331,332,333,334,335,336,337 instead of BYMONTHDAY and BYMONTH, but unfortunately my webdav server (Nextcloud, which uses Sabre as far as I know. I got an error message "Invalid BYYEARDAY rule") does not support this.


My next idea was to use multiple RRULEs -- at least I did not see any passage in the RFC stating that only one RRULE is allowed at most. So I ended up with:

RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=SU;BYMONTHDAY=27,28,29,30;BYMONTH=11
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=SU;BYMONTHDAY=1,2,3;BYMONTH=12

Didn't work as well. My last resort was to create two separate VEVENTs, one with the first RRULE above and one with the second RRULE above, but otherwise identical. This worked, but it left me confused.

Is there no better solution? How would you do it?


Solution

  • unfortunately my webdav server (Nextcloud, which uses Sabre as far as I know. I got an error message "Invalid BYYEARDAY rule") does not support this.

    Well I think you should raise a bug report, because as far I can tell your solutions are correct and RFC-compliant.

    I tried your solutions 2 and 3 with different libs (my own lib php-rrule, and rrule.js) and both options seems to work just fine.

    FREQ=YEARLY;BYDAY=SU;BYYEARDAY=331,332,333,334,335,336,337

    or combining 2

    FREQ=YEARLY;INTERVAL=1;BYDAY=SU;BYMONTHDAY=27,28,29,30;BYMONTH=11 FREQ=YEARLY;INTERVAL=1;BYDAY=SU;BYMONTHDAY=1,2,3;BYMONTH=12

    will both produce:

    2018-12-02
    2019-12-01
    2020-11-29
    2021-11-28
    2022-11-27
    2023-12-03
    2024-12-01
    2025-11-30
    2026-11-29
    2027-11-28
    

    which according to Google and Wikipedia are the correct dates for the 1st Advent Sunday in the next 10 years.

    Side note

    at least I did not see any passage in the RFC stating that only one RRULE is allowed at most.

    While not strictly forbidden, in RFC 5545 it's literally written everytime RRULE is mentioned:

    ;
    ; The following is OPTIONAL,
    ; but SHOULD NOT occur more than once.
    ;
    rrule
    

    Appendix A even states in the "New restrictions":

    2.  The "RRULE" property SHOULD NOT occur more than once in a
       component.
    

    That being said, multiple RRULE is a great feature, I don't know why they restricted it.