subtract method

List<Period> subtract(
  1. List<Period> periods
)

Returns a list of Periods that are the difference between this Period and the periods passed as argument.

The periods are sorted, merged, trimmed and if not overlapping with this Period they are removed. After that, the result will be the periods between the merged periods and the period between the start of this Period and the first merged period, and the period between the end of this Period and the last merged period.

If the periods are overlapping with this Period the result will be a list with only this Period.

Example:

final period = Period(
  start: DateTime(2020, 1, 1),
  end: DateTime(2020, 1, 31),
);
final periods = [
  Period(
    start: DateTime(2020, 1, 1),
    end: DateTime(2020, 1, 10),
  ),
  Period(
    start: DateTime(2020, 1, 15),
    end: DateTime(2020, 1, 20),
  ),
  Period(
    start: DateTime(2020, 1, 25),
    end: DateTime(2020, 1, 29),
  ),
];

final result = period.subtract(periods);

// result = [
//   Period(
//     start: DateTime(2020, 1, 10),
//     end: DateTime(2020, 1, 15),
//   ),
//   Period(
//     start: DateTime(2020, 1, 20),
//     end: DateTime(2020, 1, 25),
//   ),
//   Period(
//     start: DateTime(2020, 1, 29),
//     end: DateTime(2020, 1, 31),
//   ),
// ]

Implementation

List<Period> subtract(List<Period> periods) {
  if (periods.isEmpty) return [this];
  final localPeriods = trim(periods);
  if (localPeriods.isEmpty) return [this];
  final merged = mergeOverlappingPeriods(localPeriods);
  final result = <Period>[];
  final difference = calculateStartDifference(merged.first, this);
  if (difference != null) result.add(difference);
  for (var i = 0, j = 1; j < merged.length; i++, j++) {
    result.add(Period.inBetween(merged[i], merged[j])!);
  }
  if (merged.length > 1) {
    final differenceLast = calculateEndDifference(merged.last, this);
    if (differenceLast != null) result.add(differenceLast);
  }
  return result;
}