findGaps function
Gaps [start, end] (the inclusive bounding sample pair) where consecutive
timestamps are spaced more than expectedInterval * (1 + tolerance) apart.
timestamps is copied and sorted, so order in does not matter. tolerance
is a non-negative fraction of slack on top of the expected interval. With
fewer than two samples there are no pairs, so the result is empty.
Example:
findGaps(
<DateTime>[DateTime(2026, 1, 1, 0), DateTime(2026, 1, 1, 3)],
const Duration(hours: 1),
); // one gap from 00:00 to 03:00 (3h delta > 1.5h threshold)
Audited: 2026-06-12 11:26 EDT
Implementation
List<({DateTime start, DateTime end})> findGaps(
List<DateTime> timestamps,
Duration expectedInterval, {
double tolerance = 0.5,
}) {
// Copy before sorting so the caller's list is never mutated as a side effect.
final List<DateTime> sorted = List<DateTime>.of(timestamps)
..sort((DateTime a, DateTime b) => a.compareTo(b));
// A delta beyond this many microseconds between neighbors is a gap; computing
// it once in microseconds avoids per-pair Duration allocation.
final int thresholdMicros = (expectedInterval.inMicroseconds * (1 + tolerance)).round();
final List<({DateTime start, DateTime end})> gaps = <({DateTime start, DateTime end})>[];
for (int i = 1; i < sorted.length; i++) {
final DateTime prev = sorted[i - 1];
final DateTime curr = sorted[i];
if (curr.difference(prev).inMicroseconds > thresholdMicros) {
gaps.add((start: prev, end: curr));
}
}
return gaps;
}