import type { DaySummary, TimeEntry, WeekSummary } from "./types"; const DAY_MS = 24 * 60 * 60 * 1000; function dayStartMs(value: number): number { const d = new Date(value); return new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime(); } function dayKey(value: number): string { const d = new Date(value); const y = d.getFullYear(); const m = String(d.getMonth() + 1).padStart(2, "0"); const day = String(d.getDate()).padStart(2, "0"); return `${y}-${m}-${day}`; } function isoWeekKey(value: number): string { const d = new Date(value); const date = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate())); const dayNum = date.getUTCDay() || 7; date.setUTCDate(date.getUTCDate() + 4 - dayNum); const yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1)); const weekNo = Math.ceil((((date.getTime() - yearStart.getTime()) / DAY_MS) + 1) / 7); return `${date.getUTCFullYear()}-W${String(weekNo).padStart(2, "0")}`; } export function splitEntryAcrossDays(entry: TimeEntry): DaySummary[] { const result: DaySummary[] = []; let cursor = entry.startedAtEpochMs; const end = entry.endedAtEpochMs; while (cursor < end) { const startOfDay = dayStartMs(cursor); const nextDay = startOfDay + DAY_MS; const segmentEnd = Math.min(end, nextDay); result.push({ day: dayKey(cursor), durationMs: segmentEnd - cursor }); cursor = segmentEnd; } return result; } export function computeDaySummaries(entries: TimeEntry[]): DaySummary[] { const map = new Map(); for (const entry of entries) { for (const segment of splitEntryAcrossDays(entry)) { map.set(segment.day, (map.get(segment.day) ?? 0) + segment.durationMs); } } return [...map.entries()] .map(([day, durationMs]) => ({ day, durationMs })) .sort((a, b) => a.day.localeCompare(b.day)); } export function computeWeekSummaries(entries: TimeEntry[]): WeekSummary[] { const daySummaries = computeDaySummaries(entries); const map = new Map(); for (const day of daySummaries) { const week = isoWeekKey(new Date(`${day.day}T12:00:00`).getTime()); map.set(week, (map.get(week) ?? 0) + day.durationMs); } return [...map.entries()] .map(([week, durationMs]) => ({ week, durationMs })) .sort((a, b) => a.week.localeCompare(b.week)); }