rianjs / ical.net

ical.NET - an open source iCal library for .NET
MIT License
767 stars 228 forks source link

How to get repeating occurences from RRULE strin #489

Open pantonis opened 4 years ago

pantonis commented 4 years ago

I have not found a single tutorial of how to parse an RRULE string and get the occurences. Is this not supported by this library?

elamje commented 4 years ago

I'm curious as well. @pantonis Any luck in your search?

vanpyrzericj commented 4 years ago

You can use this library to get occurrences. But if you want all the occurrences, well, that's not really a complete possibility.

This seems fairly reasonable, since indefinite recurrences would mean you'd never actually get a finite answer to an occurrences inquiry. If you really needed to, I suppose you could set the end date on GetOccurrences to some date far in the future (note: DateTime.Max did not work for me when I tested this). For example, perhaps you could say your end date range is Today's date plus 10 years.

As others have pointed out, the purpose of RRULE in the iCalendar spec is to consolidate recurrences. Not to expand them out (and certainly not for indefinite ones). If your RRULE has Until specified, that gives you an easy way to pull your end parameter for GetOccurrences.

The only tricky one that jumps out at me is when an RRULE uses just Count. In these cases, I'd suggest using an arbitrary date in the somewhat-distant-but-not-too-distant-future.

pantonis commented 4 years ago

@elamje I have found out some things but the library in general behaves very strange. I have an example that I have quarterly events start date 01/07/2020, end date 30/09/202 with rrule RRULE:FREQ=MONTHLY;INTERVAL=3 and it returns back some correct occurences but also some wrong ones. I get 01/01/2021 - 02/04/2021 where as end date should be 31/03/2021

pantonis commented 4 years ago

@elamje here is a snippet that I am using to get repeating occurrences

 public void GetRecurrences()
        {
            string rrule = "RRULE:FREQ=MONTHLY;INTERVAL=3";
            if (string.IsNullOrWhiteSpace(rrule))
                return;

            var dtStart = new DateTime(2020, 4, 1);
            var dtEnd = new DateTime(2020, 6, 30);

            RecurrencePattern recurrenceRule = new RecurrencePattern(rrule);
            var vEvent = new CalendarEvent
            {
                DtStart = new CalDateTime(dtStart),
                DtEnd = new CalDateTime(dtEnd),
                RecurrenceRules = new List<RecurrencePattern> { recurrenceRule },
            };

            var calendar = new Calendar();
            calendar.Events.Add(vEvent);

            var startSearch = new CalDateTime(dtStart.AddDays(-1));

            var endSearch = new CalDateTime(DateTime.UtcNow.AddYears(30));
            HashSet<Occurrence> occurrences = calendar.GetOccurrences(startSearch, endSearch);

            foreach (var item in occurrences)
            {
                Console.WriteLine($"{item.Period.StartTime} - {item.Period.EndTime}");
            }
        }
iamkinetic commented 4 years ago

Should it work if the RRULE string contains DTSTART and DTEND? They seem to be ignored in my test when using this RRULE:

DTSTART:20200101T150000Z
DTEND:20200101T160000Z
RRULE:FREQ=DAILY;COUNT=10;INTERVAL=5