From 021d62784e25d2036532f640806268e6d2ab5efb Mon Sep 17 00:00:00 2001 From: chihlasm Date: Sun, 15 Mar 2026 16:39:17 -0400 Subject: [PATCH] fix: parse sidebar timestamps as UTC (append Z suffix) Backend returns naive UTC timestamps without timezone indicator. JS Date() treats bare ISO strings as local time, causing the timer to compute negative elapsed time (future timestamps). Appending 'Z' forces UTC parsing. Co-Authored-By: Claude Opus 4.6 (1M context) --- frontend/src/components/sidebar/SidebarStatsBar.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/sidebar/SidebarStatsBar.tsx b/frontend/src/components/sidebar/SidebarStatsBar.tsx index 64d78f0e..eb54d92c 100644 --- a/frontend/src/components/sidebar/SidebarStatsBar.tsx +++ b/frontend/src/components/sidebar/SidebarStatsBar.tsx @@ -18,19 +18,21 @@ function formatDuration(totalSeconds: number): string { return m > 0 ? `${h}h ${m}m` : `${h}h` } +function parseUTCTimestamp(st: string): number { + // Backend returns naive UTC timestamps without 'Z' suffix. + // JS Date() treats bare strings as local time, so append Z to force UTC. + return new Date(st.endsWith('Z') ? st : st + 'Z').getTime() +} + function calcActiveSeconds(startTimes: string[]): number { const now = Date.now() return startTimes.reduce((sum, st) => { - const elapsed = Math.floor((now - new Date(st).getTime()) / 1000) + const elapsed = Math.floor((now - parseUTCTimestamp(st)) / 1000) return sum + Math.max(0, elapsed) }, 0) } export function SidebarStatsBar({ resolved, active, completedMinutes, activeSessionStartTimes }: SidebarStatsBarProps) { - // Debug: remove after fixing - if (activeSessionStartTimes.length > 0) { - console.log('[SidebarStats] startTimes:', activeSessionStartTimes, 'calcSeconds:', calcActiveSeconds(activeSessionStartTimes), 'now:', Date.now(), 'parsed:', activeSessionStartTimes.map(st => new Date(st).getTime())) - } const [liveSeconds, setLiveSeconds] = useState(() => calcActiveSeconds(activeSessionStartTimes)) // Tick every second to keep the timer in sync with the session timer