expand static method
List<PlexCalendarEvent>
expand(
- PlexCalendarEvent event, {
- required DateTime rangeStart,
- required DateTime rangeEnd,
Expands event into occurrences whose start date falls on or between
rangeStart and rangeEnd (inclusive dates).
Stops at count instances, until (inclusive date), or rangeEnd,
whichever comes first. Daily steps interval days; weekly steps
interval weeks on the same weekday as PlexCalendarEvent.start.
Occurrence ids are '${event.id}#${yyyyMMdd}'. The master id is stored
on PlexCalendarEvent.occurrenceOf. Start/end are shifted by the same
duration. Events without a rule are returned unchanged when in range.
Implementation
static List<PlexCalendarEvent> expand(
PlexCalendarEvent event, {
required DateTime rangeStart,
required DateTime rangeEnd,
}) {
final DateTime from = _dateOnly(rangeStart);
final DateTime to = _dateOnly(rangeEnd);
if (to.isBefore(from)) return const <PlexCalendarEvent>[];
final PlexCalendarRecurrence? rule = event.recurrence;
if (rule == null || event.occurrenceOf != null) {
return _inInclusiveDateRange(event.start, from, to)
? <PlexCalendarEvent>[event]
: const <PlexCalendarEvent>[];
}
final int step = rule.interval < 1 ? 1 : rule.interval;
final int? count = rule.count;
if (count != null && count <= 0) return const <PlexCalendarEvent>[];
final DateTime? untilDate =
rule.until == null ? null : _dateOnly(rule.until!);
final Duration span = event.end == null
? Duration.zero
: event.end!.difference(event.start);
final List<PlexCalendarEvent> out = <PlexCalendarEvent>[];
DateTime cursor = event.start;
int generated = 0;
int guard = 0;
while (guard++ < _maxIterations) {
final DateTime cursorDay = _dateOnly(cursor);
if (untilDate != null && cursorDay.isAfter(untilDate)) break;
if (cursorDay.isAfter(to)) break;
generated++;
if (count != null && generated > count) break;
if (!cursorDay.isBefore(from)) {
out.add(
PlexCalendarEvent(
id: '${event.id}#${_yyyyMMdd(cursor)}',
start: cursor,
end: event.end == null ? null : cursor.add(span),
title: event.title,
color: event.color,
occurrenceOf: event.occurrenceOf ?? event.id,
),
);
}
if (count != null && generated >= count) break;
cursor = _advance(cursor, rule.frequency, step);
}
return out;
}