ical.net icon indicating copy to clipboard operation
ical.net copied to clipboard

GetOccurrences includes the first event at the start/end even though it is not in RRule

Open sonyisda1 opened this issue 8 years ago • 9 comments

I am implementing Telerik's KendoUI Scheduler control in a MVC web project. It has a calendar for users to enter scheduled tasks. Since it is open for the users to add/edit, any date can be selected to create a new event and the start/end times can be customized. This presents a scenario where the user creates an event on Friday but sets the recurrence rule to repeat only on Mondays.

In the HashSet<Occurrence> Calendar.GetOccurrences(..) method, it includes the start/end of the event even though it is not under the rrule.

I am using latest v2.2.32. See this following code for an example:

public static void StartEndEventShouldNotBeIncludedInOccurrences()
         {

         // Recur weekly every monday through the end of the day, April 5 2017
         var rrule = new RecurrencePattern("FREQ=WEEKLY;UNTIL=20170405T115959;BYDAY=MO");
         var vEvent = new Event
            {
            // the start/end datetimes for the event are on Friday March 10 2017
            DtStart = new CalDateTime(DateTime.Parse("2017-03-10T14:00:00")),
            DtEnd = new CalDateTime(DateTime.Parse("2017-03-10T18:00:00")),
            RecurrenceRules = new List<IRecurrencePattern> { rrule },
            };

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

         // set the occurrences roll out to start at the event start time and go to the until time
         var startSearch = new CalDateTime(DateTime.Parse("2017-03-10T14:00:00"));
         var endSearch = new CalDateTime(DateTime.Parse("2017-04-05T11:59:59"));
         var occurrences = calendar.GetOccurrences(startSearch, endSearch);
         }

Below is screenshot of the occurrences. Why is the first occurrence at 3/10/2017 included in this list? image

I do not think it should be. If I enter that recurrence pattern at: http://jakubroztocil.github.io/rrule/ it does not show the occurrence on Mar 10 but instead the first one on Mar 13. image

Telerick's Scheduler calendar control does not show the event on March 10 nor does Telerik's client-side SchedulerEvent.expand(..) (http://docs.telerik.com/kendo-ui/api/javascript/data/schedulerevent#methods-expand).

So which is right?

sonyisda1 avatar Mar 10 '17 14:03 sonyisda1

I have a similar issue of the DtStart date not matching the RRULE and have figured out a work around using the RecurrencePatternEvaluator.

// 3/1/2017 is a wednesday so it shouldn't display in the occurrences
var vEvent = new Event {
 DtStart = new CalDateTime(newDateTime(2017, 3, 1, 9, 0, 0)),
 DtEnd = new CalDateTime(newDateTime(2017, 3, 1, 10, 0, 0))
};
var recurrenceRule = new RecurrencePattern(FrequencyDayType.Weekly, 1) {
 ByDay = new IList<IWeekday> { new WeekDay(DayOfWeek.Thursday) }
};
var recurrenceEvaluator = new RecurrencePatternEvaluator(recurrenceRule);
var searchStart = new DateTime(2017, 3, 1, 0, 0, 0);
var searchEnd = new DateTime(2017, 3, 17, 0, 0, 0);
var correctOccurrences = recurrenceEvaluator.Evaluate(vEvent.DtStart, searchStart, searchEnd, false);

Occurrence should equal 3/2/2017, 3/9/2017, and 3/16/2017. By setting the parameter includeReferenceDateInResults to false only adds the DtStart to the occurrences if it matches the RRULE.

streviranus avatar Mar 10 '17 23:03 streviranus

Thanks @streviranus for your work around. The RecurrencePatternEvaluator will be helpful though it presents another issue for my application since I am looking for the next occurrence's start and end times so that I can auto-adjust the entered times with the actual next occurrence. I think I will have to come up with a custom solution to either marry the the two HashSets or calculate the end time from the start time manually.

I think it would be best if that bool includeReferenceDateInResults flag could be a (optional) parameter in the GetOccurrences method.

sonyisda1 avatar Mar 13 '17 13:03 sonyisda1

@sonyisda1 same here I have to implement a custom solution and will use my correctOccurrences list to verify the first element matches the RRULE.

@rianjs can I +1 vote to add an optional bool includeReferenceDateInResults flag to the GetOccurrences method?

streviranus avatar Mar 13 '17 14:03 streviranus

@rianjs can I +1 vote to add an optional bool includeReferenceDateInResults flag to the GetOccurrences method?

Sure. Alternatively, you could open a pull request to add it...

rianjs avatar Mar 13 '17 14:03 rianjs

Sure. Alternatively, you could open a pull request to add it...

@rianjs when I have the time I can, it'll be a couple weeks at least tho.

streviranus avatar Mar 13 '17 14:03 streviranus

I hear you: most of my current work on ical.net happens when I need changes (and bugfixes) because of work. :)

rianjs avatar Mar 13 '17 14:03 rianjs

Encountered the same issue. It may cause devastating effect in Outlook because once you saved an event which actually fires zero times (while the current implementation of GetOccurrences returns 1 for it), Outlook lets you save such event successfully but future access to this event crashes Outlook. Outlook itself (when you create events in UI) does not allow start date to differ from the first date actually evaluated by the event rules. But you can do that with their object model, so it's very important to check if the event you're feeding to Outlook does have at least one actual occurrence.

Are there any plans to implement includeReferenceDateInResults parameter in GetOccurrences method in the near future?

afterlogic-support avatar Jan 26 '18 17:01 afterlogic-support

Well, it seems I can just use RecurrencePatternEvaluator.Evaluate as I don't need actual occurrences, only their count.

I, however, noticed another issue. Looks like Until is exclusive, not inclusive. If event.Start is the same as recurPattern.Until and the event occurs the same weekday, I'm not getting the match. I understand it's artificial example (recurring weekly event which repeats only once and has the same start and end date and its weekday matches the same day) but it's still valid.

Event someEvent = new Event();
someEvent.Start = new CalDateTime(new DateTime(2018, 1, 25, 9, 0, 0));
someEvent.End = new CalDateTime(new DateTime(2018, 1, 25, 10, 0, 0));
var recurrenceRule = new RecurrencePattern(FrequencyType.Weekly, 1)
{
	ByDay = new List<IWeekDay> { new WeekDay(DayOfWeek.Thursday) }
};
var recurrenceEvaluator = new RecurrencePatternEvaluator(recurrenceRule);
var searchStart = new DateTime(2018, 1, 25, 0, 0, 0);
var searchEnd = new DateTime(2018, 1, 25, 0, 0, 0);
var correctOccurrences = recurrenceEvaluator.Evaluate(someEvent.Start, searchStart, searchEnd, false);

https://github.com/rianjs/ical.net/issues/121 issue explains this is intended behavior, and I can understand that but there are scenarios when this should be different. So, maybe another parameter which controls that? DDay.iCal is indeed not the best source but Outlook behaves the same way. It delivers a single occurrence (not zero) for recurring event having the same start and end dates.

afterlogic-support avatar Jan 26 '18 18:01 afterlogic-support

Currently, to make Until inclusive, I work this around by making searchEnd like this (so it covers the day in question completely but never spans to the next day, no matter which time is in searchEnd):

searchEnd.Date.Add(new TimeSpan(23, 59, 59))

afterlogic-support avatar Jan 26 '18 19:01 afterlogic-support