diff --git a/caldav/match.go b/caldav/match.go index b881183..948b33c 100644 --- a/caldav/match.go +++ b/caldav/match.go @@ -127,9 +127,19 @@ func matchPropFilter(filter PropFilter, comp *ical.Component) (bool, error) { func matchCompTimeRange(start, end time.Time, comp *ical.Component) (bool, error) { // See https://datatracker.ietf.org/doc/html/rfc4791#section-9.9 - // TODO handle "infinity" values in query - // TODO handle recurring events + // evaluate recurring components + rset, err := comp.RecurrenceSet(start.Location()) + if err != nil { + return false, err + } + if rset != nil { + // TODO we can only set inclusive to true or false, but really the + // start time is inclusive while the end time is not :/ + return len(rset.Between(start, end, true)) > 0, nil + } + // TODO handle "infinity" values in query + // TODO handle more than just events if comp.Name != ical.CompEvent { return false, nil } diff --git a/caldav/match_test.go b/caldav/match_test.go index e911846..73114bb 100644 --- a/caldav/match_test.go +++ b/caldav/match_test.go @@ -253,6 +253,24 @@ END:VCALENDAR`) addrs: []CalendarObject{event1, event2, event3, todo1}, want: []CalendarObject{event1}, }, + { + // Query a time range that only returns a result if recurrence is properly evaluated. + name: "recurring events in time range", + query: &CalendarQuery{ + CompFilter: CompFilter{ + Name: "VCALENDAR", + Comps: []CompFilter{ + CompFilter{ + Name: "VEVENT", + Start: toDate(t, "20060103T000000Z"), + End: toDate(t, "20060104T000000Z"), + }, + }, + }, + }, + addrs: []CalendarObject{event1, event2, event3, todo1}, + want: []CalendarObject{event2}, + }, // TODO add more examples } { t.Run(tc.name, func(t *testing.T) {