getRecurrencesForPeriod method
Implementation
List<DateTime> getRecurrencesForPeriod(DateTime periodStart,
DateTime periodEnd, DateTime eventStart, DateTime eventEnd) {
assert(periodStart.isBefore(periodEnd));
var recurrences = <DateTime>[];
if (until != null && until!.isBefore(periodStart)) {
return recurrences;
}
switch (frequency) {
case Frequency.SECONDLY:
assert(bySecond != null && bySecond!.isNotEmpty);
while (eventStart.isBefore(periodEnd.add(Duration(milliseconds: 1))) &&
(until == null ||
eventStart.isBefore(until!.add(Duration(milliseconds: 1))))) {
if (eventStart.isAfter(periodStart) || eventStart == periodStart) {
recurrences.add(eventStart);
}
eventStart = eventStart.add(Duration(seconds: interval));
}
break;
case Frequency.MINUTELY:
assert(byMinute != null && byMinute!.isNotEmpty);
while (eventStart.isBefore(periodEnd.add(Duration(milliseconds: 1))) &&
(until == null ||
eventStart.isBefore(until!.add(Duration(milliseconds: 1))))) {
if (eventStart.isAfter(periodStart) || eventStart == periodStart) {
recurrences.add(eventStart);
}
eventStart = eventStart.add(Duration(minutes: interval));
}
break;
case Frequency.HOURLY:
assert(byHour != null && byHour!.isNotEmpty);
while (eventStart.isBefore(periodEnd.add(Duration(milliseconds: 1))) &&
(until == null ||
eventStart.isBefore(until!.add(Duration(milliseconds: 1))))) {
if (eventStart.isAfter(periodStart) || eventStart == periodStart) {
recurrences.add(eventStart);
}
eventStart = eventStart.add(Duration(hours: interval));
}
break;
case Frequency.DAILY:
assert(byDay != null && byDay!.isNotEmpty);
while (eventStart.isBefore(periodEnd.add(Duration(milliseconds: 1))) &&
(until == null ||
eventStart.isBefore(until!.add(Duration(milliseconds: 1))))) {
if (eventStart.isAfter(periodStart) || eventStart == periodStart) {
recurrences.add(eventStart);
}
eventStart = eventStart.add(Duration(days: interval));
}
break;
case Frequency.WEEKLY:
while (eventStart.isBefore(periodEnd.add(Duration(milliseconds: 1))) &&
(until == null ||
eventStart.isBefore(until!.add(Duration(milliseconds: 1))))) {
for (DayOfWeek dayOfWeek in (byDay ?? []).whereType<DayOfWeek>()) {
var daysUntilRecurrence =
(dayOfWeek.weekday.index - eventStart.weekday + 7) % 7;
var nextRecurrence =
eventStart.add(Duration(days: daysUntilRecurrence));
if (nextRecurrence.isAfter(periodStart) ||
nextRecurrence == periodStart) {
if (nextRecurrence.isBefore(periodEnd) ||
nextRecurrence == periodEnd) {
recurrences.add(nextRecurrence);
}
}
}
eventStart = eventStart.add(Duration(days: interval * 7));
}
break;
case Frequency.MONTHLY:
assert(byMonth != null && byMonth!.isNotEmpty);
while (eventStart.isBefore(periodEnd.add(Duration(milliseconds: 1))) &&
(until == null ||
eventStart.isBefore(until!.add(Duration(milliseconds: 1))))) {
if (eventStart.isAfter(periodStart) || eventStart == periodStart) {
recurrences.add(eventStart);
}
var nextMonthStart = DateTime(
eventStart.year + (eventStart.month + interval - 1) ~/ 12,
(eventStart.month + interval - 1) % 12 + 1,
eventStart.day,
eventStart.hour,
eventStart.minute,
eventStart.second,
eventStart.millisecond,
);
if (byMonth == null ||
byMonth!.isEmpty ||
byMonth!.contains(nextMonthStart.month)) {
eventStart = nextMonthStart;
} else {
var nextValidMonth = byMonth!
.firstWhere((m) => m > nextMonthStart.month, orElse: () => -1);
if (nextValidMonth == -1) {
break; // exit loop if there are no valid months left
}
eventStart = DateTime(
nextMonthStart.year + (nextValidMonth - 1) ~/ 12,
(nextValidMonth - 1) % 12 + 1,
nextMonthStart.day,
nextMonthStart.hour,
nextMonthStart.minute,
nextMonthStart.second,
nextMonthStart.millisecond,
);
}
if (eventStart.month == DateTime.february &&
eventStart.day == 29 &&
!isLeapYear(eventStart.year)) {
eventStart = DateTime(eventStart.year, DateTime.march, 1,
eventStart.hour, eventStart.minute, eventStart.second);
}
}
break;
case Frequency.YEARLY:
assert(byYearDay != null && byYearDay!.isNotEmpty);
var eventStartYear = eventStart.year;
var eventStartMonth = eventStart.month;
var eventStartDay = eventStart.day;
if (eventStartMonth == DateTime.february &&
eventStartDay == 29 &&
!isLeapYear(eventStartYear)) {
eventStartMonth = DateTime.march;
eventStartDay = 1;
}
while (eventStart.isBefore(periodEnd) &&
(until == null ||
eventStart.isBefore(until!.add(Duration(milliseconds: 1))))) {
if (eventStart.isAfter(periodStart) || eventStart == periodStart) {
recurrences.add(eventStart);
}
eventStart = DateTime(
eventStartYear + interval,
eventStartMonth,
eventStartDay,
eventStart.hour,
eventStart.minute,
eventStart.second,
eventStart.millisecond);
if (eventStartMonth == DateTime.february &&
eventStartDay == 29 &&
!isLeapYear(eventStartYear)) {
eventStartMonth = DateTime.march;
eventStartDay = 1;
} else {
eventStartMonth = eventStart.month;
eventStartDay = eventStart.day;
}
eventStartYear = eventStart.year;
}
break;
}
return recurrences;
}