Files
mailgoserver/internal/webui/calendar_recurrence.go
T

42 lines
1.5 KiB
Go

package webui
import (
"time"
"github.com/teambition/rrule-go"
"mailgoserver/internal/db"
)
// expandOccurrences returns every occurrence of e falling within [rangeStart,
// rangeEnd) — a single-element slice (or none, if outside the range) for a
// non-recurring event, or every matching occurrence for a recurring one (rrule-go's
// own expansion, seeded with the event's own start time as DTSTART since e.RRule only
// ever stores the bare "FREQ=..." value, not a full RRULE property with its own
// DTSTART). Display-only: an occurrence's time is never itself stored — editing or
// deleting always acts on the whole series (see caldav.go/webmail_calendar.go; a
// single-occurrence RFC 5545 RECURRENCE-ID override is out of scope for this pass).
func expandOccurrences(e db.CalendarEvent, rangeStart, rangeEnd time.Time) []time.Time {
if e.RRule == "" {
if e.StartAt.Before(rangeEnd) && e.EndAt.After(rangeStart) {
return []time.Time{e.StartAt}
}
return nil
}
opt, err := rrule.StrToROption(e.RRule)
if err != nil {
return nil
}
opt.Dtstart = e.StartAt
rule, err := rrule.NewRRule(*opt)
if err != nil {
return nil
}
// Between's window needs to start far enough back to catch an occurrence whose
// start falls before rangeStart but whose duration still overlaps it (a
// multi-hour recurring event straddling midnight) — shift the query window back
// by the event's own duration rather than assuming same-day occurrences.
duration := e.EndAt.Sub(e.StartAt)
return rule.Between(rangeStart.Add(-duration), rangeEnd, true)
}