feat(boss-dashboard): add windowRange helper with UTC boundaries

This commit is contained in:
Dave 2026-08-27 23:42:16 +02:00
parent 918586b6fb
commit 52b4b1f053
2 changed files with 77 additions and 0 deletions

View file

@ -0,0 +1,30 @@
import { describe, it, expect } from "vitest";
import { windowRange } from "./boss-dashboard-service";
describe("windowRange", () => {
it("today: start of UTC day to start of next UTC day", () => {
const r = windowRange("today", new Date("2026-08-27T14:32:11.000Z"));
expect(r.rangeStart).toBe("2026-08-27T00:00:00.000Z");
expect(r.rangeEnd).toBe("2026-08-28T00:00:00.000Z");
});
it("week: Monday 00:00 UTC to next Monday 00:00 UTC", () => {
// 2026-08-27 is a Thursday. Week starts Mon 2026-08-24.
const r = windowRange("week", new Date("2026-08-27T14:32:11.000Z"));
expect(r.rangeStart).toBe("2026-08-24T00:00:00.000Z");
expect(r.rangeEnd).toBe("2026-08-31T00:00:00.000Z");
});
it("month: first of month to first of next month", () => {
const r = windowRange("month", new Date("2026-08-27T14:32:11.000Z"));
expect(r.rangeStart).toBe("2026-08-01T00:00:00.000Z");
expect(r.rangeEnd).toBe("2026-09-01T00:00:00.000Z");
});
it("week across month boundary: still anchored to Monday", () => {
// 2026-09-02 is a Wednesday. Week starts Mon 2026-08-31, ends Mon 2026-09-07.
const r = windowRange("week", new Date("2026-09-02T09:00:00.000Z"));
expect(r.rangeStart).toBe("2026-08-31T00:00:00.000Z");
expect(r.rangeEnd).toBe("2026-09-07T00:00:00.000Z");
});
});

View file

@ -0,0 +1,47 @@
export type BossWindow = "today" | "week" | "month";
export interface WindowRange {
rangeStart: string; // ISO
rangeEnd: string; // ISO
}
/**
* Computes the [start, end) UTC window for a boss-dashboard time tab.
* Today: midnight-to-midnight UTC.
* Week: Monday 00:00 UTC to next Monday 00:00 UTC.
* Month: day-1 00:00 UTC to day-1 of next month.
*
* All UTC because that's how PocketBase `created` timestamps compare.
*/
export function windowRange(window: BossWindow, now: Date = new Date()): WindowRange {
const start = new Date(now);
const end = new Date(now);
switch (window) {
case "today": {
start.setUTCHours(0, 0, 0, 0);
end.setUTCDate(end.getUTCDate() + 1);
end.setUTCHours(0, 0, 0, 0);
break;
}
case "week": {
// Monday = 1, Sunday = 0. Shift so Monday is start.
const day = start.getUTCDay();
const diffToMonday = day === 0 ? -6 : 1 - day;
start.setUTCDate(start.getUTCDate() + diffToMonday);
start.setUTCHours(0, 0, 0, 0);
end.setTime(start.getTime());
end.setUTCDate(end.getUTCDate() + 7);
break;
}
case "month": {
start.setUTCDate(1);
start.setUTCHours(0, 0, 0, 0);
end.setUTCMonth(end.getUTCMonth() + 1, 1);
end.setUTCHours(0, 0, 0, 0);
break;
}
}
return { rangeStart: start.toISOString(), rangeEnd: end.toISOString() };
}