42 lines
1.5 KiB
Go
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)
|
|
}
|