splitAt method
Splits the period in multiple periods at the given dates
.
The periodBetween
is the duration between each period.
The dates
not included in the period are ignored.
The dates
will be sorted before splitting.
The periodBetween
must be greater than or equals to zero and less than
the duration of the period.
The sum of the period between dates must be less than the duration of the
period.
If the periodBetween
is zero, the periods will be contiguous.
If the periodBetween
is greater than zero, the periods will be
separated by the given duration.
If the dates
are empty, the period is returned.
If the dates
are not empty, the period is split at the given dates.
Example:
final period = Period(
start: DateTime(2020, 1, 1),
end: DateTime(2020, 1, 31),
);
final periods = period.splitAt(
{
DateTime(2020, 1, 10),
DateTime(2020, 1, 20),
},
periodBetween: const Duration(days: 1),
);
// periods = [
// Period(
// start: DateTime(2020, 1, 1),
// end: DateTime(2020, 1, 10),
// ),
// Period(
// start: DateTime(2020, 1, 11),
// end: DateTime(2020, 1, 20),
// ),
// Period(
// start: DateTime(2020, 1, 21),
// end: DateTime(2020, 1, 31),
// ),
// ]
Implementation
List<Period> splitAt(
Set<DateTime> dates, {
Duration periodBetween = Duration.zero,
}) {
if ((periodBetween < Duration.zero) || (duration <= periodBetween)) {
throw ArgumentError.value(
periodBetween,
'periodBetween',
'The period between dates must be greater than or equals to zero and '
'less than the duration of the period.',
);
}
final periods = <Period>[];
final sortedValidDates = [...dates.where(contains)]..sort();
final resultDuration = periodBetween * sortedValidDates.length;
if (resultDuration > duration) {
throw ArgumentError.value(
dates,
'dates',
'The sum of the period between dates is greater than the duration of '
'the period.',
);
}
for (final date in sortedValidDates.sublist(sortedValidDates.length - 1)) {
if (periods.isEmpty) {
periods.add(Period(start: start, end: date));
} else {
final last = periods.last;
if (last.end.add(periodBetween).isBefore(date)) {
periods.add(Period(start: last.end.add(periodBetween), end: date));
} else {
final start = last.end.add(periodBetween);
periods.add(Period(start: start, end: start));
}
}
}
if (periods.isNotEmpty) {
final last = periods.last;
if (last.end.add(periodBetween).isBefore(end)) {
periods.add(Period(start: last.end.add(periodBetween), end: end));
} else {
final start = last.end.add(periodBetween);
periods.add(Period(start: start, end: start));
}
} else {
periods.add(this);
}
return periods;
}