splitIn method

List<Period> splitIn(
  1. int times, {
  2. Duration periodBetween = Duration.zero,
})

Split the period in multiple periods. The times is the number of periods to split the period in.

The periodBetween is the duration between each period. The periodBetween must be greater than or equals to zero and less than the duration of the period. The sum of the period between the periods 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.

The times must be greater than zero. If the times is one, the period will be returned. If the times is greater than one, the period will be split in multiple periods.

Example:

final period = Period(
  start: DateTime(2020, 1, 1),
  end: DateTime(2020, 1, 31),
);
final periods = period.splitIn(
  3,
  periodBetween: Duration(days: 1),
);
// periods = [
//   Period(
//     start: DateTime(2020, 1, 1),
//     end: DateTime(2020, 1, 10, 8),
//   ),
//   Period(
//     start: DateTime(2020, 1, 11, 8),
//     end: DateTime(2020, 1, 20, 16),
//   ),
//   Period(
//     start: DateTime(2020, 1, 21, 16),
//     end: DateTime(2020, 1, 31),
//   ),
// ]

Implementation

List<Period> splitIn(
  int times, {
  Duration periodBetween = Duration.zero,
}) {
  if (times <= 0) {
    throw ArgumentError.value(
      times,
      'times',
      'Times must be greater than zero.',
    );
  }
  if ((periodBetween < Duration.zero) || (duration <= periodBetween)) {
    throw ArgumentError.value(
      periodBetween,
      'periodBetween',
      'Period between must be greater than or equals to zero and less than '
          'the duration of the period.',
    );
  }
  if ((periodBetween * times) > duration) {
    throw ArgumentError.value(
      times,
      'times',
      'The sum of the period between dates is greater than the duration of '
          'the period.',
    );
  }
  final periods = <Period>[];
  final finalBetween = periodBetween * (times - 1);
  var fullPeriodDuration = duration - finalBetween;
  var rest = fullPeriodDuration.inMicroseconds % times;
  while (rest != 0) {
    fullPeriodDuration -= const Duration(microseconds: 1);
    rest = fullPeriodDuration.inMicroseconds % times;
  }
  final periodDuration = fullPeriodDuration ~/ times;
  for (var i = 0; i < times; i++) {
    final start = this.start.add(
          (periodDuration * i) + periodBetween * i,
        );
    var end = this.start.add(
          periodDuration * (i + 1) + periodBetween * i,
        );
    if (i == (times - 1)) end = this.end;
    periods.add(Period(start: start, end: end));
  }
  return periods;
}