rianjs / ical.net

ical.NET - an open source iCal library for .NET
MIT License
782 stars 230 forks source link

Recurrence skipped when exact date of event does not exist #446

Open AntenorBusinessSolutions opened 5 years ago

AntenorBusinessSolutions commented 5 years ago

Hi,

I'm using iCal.Net library version 4.1.11 (the current latest stable) to generate event recurrences.

When a recurrence falls on a date that doesn't exist (i.e. > 29th Feb in a leap year, > 28th Feb other years and > 30th of any 30-day month) then the recurrence is completely skipped.

I understand that skipping events can be the expected behaviour in some circumstances, but in our position we would expect the missing event to occur on the nearest date that does exist. I haven't been able to find any configuration option that might switch between those behaviours.

Tests have shown the behaviour as described. Here is one example that we tested: RecurrencePattern: FREQ=MONTHLY;COUNT=8;INTERVAL=3 DtStart: 2018/11/29

...which skips: 2019/02/29

Can you guide us on whether this is a bug or not? If it is intended behaviour, whether there is a way to switch between behaviours?

None of the examples that I have been able to find online address this behaviour.

Many thanks, Anthony.

AntenorBusinessSolutions commented 5 years ago

OK... for anyone else encountering this problem...

The package is implementing the standard correctly, but the standard does not appear to have considered recurrence under these circumstances so it simply states that non-existent dates will be ignored.

Our solution is to detect the vulnerable days of the month and append the recurrence rule to include a BYMONTHDAY clause with a negative value (to make it count from the end of the month).

For recurrences with MONTHLY frequency: When the start day is 29th or greater we set the new clause to the recurrence start day (29, 30 or 31) less the number of days in the start date's month and subtract 1 (producing -1, -2 or -3).

For recurrences with YEARLY frequency: When the start date is 29th February we set the new clause to -1.

For our purposes this adjustment meets the requirement, however you may want to make it more sophisticated (e.g. only adjusting recurrences for a 29th of a month when it's a February in a non-leap year).