From a9d2adc6a1fc257690c13d7f6a4d50181b8d2f30 Mon Sep 17 00:00:00 2001 From: Varun Raj Date: Fri, 10 Jul 2026 15:53:04 +0000 Subject: [PATCH] fix: measure trip gap tolerance in real calendar days, not array-index distance clusterTrips's gap check compared array-index adjacency between DaySignal entries. Since `days` only contains dates with >=1 photo (GROUP BY DATE(...) with no zero-photo rows), two trips separated by months with no photos in between were array-adjacent (gapLen=0) and got merged into one bogus trip. Compare actual elapsed calendar days between the last and next away day instead. --- src/helpers/trips.helper.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/helpers/trips.helper.ts b/src/helpers/trips.helper.ts index 00c2f87..4fde3e4 100644 --- a/src/helpers/trips.helper.ts +++ b/src/helpers/trips.helper.ts @@ -8,6 +8,8 @@ * Pure functions — no DB, no network. Easy to unit-test. */ +import { differenceInCalendarDays, parseISO } from "date-fns"; + export interface DaySignal { /** YYYY-MM-DD */ date: string; @@ -160,12 +162,16 @@ export function clusterTrips(days: DaySignal[], opts: ClusterOptions): Trip[] { k += 1; continue; } - // Count consecutive non-away days - const gapStart = k; + // Skip consecutive non-away days, then compare actual elapsed calendar + // days (not array-index distance) against the next away day — `days` + // only contains dates with ≥1 photo, so a months-long photo-less gap + // must not look "adjacent" just because no entries sit between them. while (k < sorted.length && !away[k]) k += 1; - const gapLen = k - gapStart; - if (gapLen > opts.gapTolerance) break; // close trip at endIdx - // else tolerated; `k` now points at next away day (or end) + if (k < sorted.length) { + const gapDays = differenceInCalendarDays(parseISO(sorted[k].date), parseISO(sorted[endIdx].date)); + if (gapDays > opts.gapTolerance) break; // close trip at endIdx + } + // else tolerated (or no more away days left); `k` now points at next away day (or end) } const slice = sorted.slice(i, endIdx + 1);