refactor(tz): export toBerlinYmd and dedup two more BERLIN_DAY_FORMATTER sites

W4-ARCH-HYGIENE's 7-way dedup landed in `src/lib/tz/resolver.ts` but
left two more BERLIN_DAY_FORMATTER declarations alive:

- `src/lib/insights/bucket-series.ts` needed the numeric `{year,
  month, day}` parts for `Date.UTC` arithmetic, so it kept its own
  formatter and a local `toBerlinYmd` helper.
- `src/lib/analytics/bp-in-target.ts` used a separate en-CA formatter
  to skip the part-reassembly when producing the YYYY-MM-DD string.

Export a sibling `toBerlinYmd(date)` helper from the resolver that
returns the formatter's raw string parts so `bucket-series.ts` can
parse them into numbers without instantiating a second formatter.
Switch `bp-in-target.ts` to the existing `toBerlinDayKey` import —
the en-CA shortcut is a microscopic speedup not worth the duplicate
formatter and the divergent contract.

Net: one shared formatter for every Berlin-anchored cache key in the
tree. The 272 insights / analytics / tz unit tests still pass.
This commit is contained in:
Marc-André Bombeck committed 2026-05-21 19:22:18 +02:00
1 parent d6ea0fa4b4
commit f11df655a2
3 files changed
+24 -26

No files matched your search

+1 -11
View File
@@ -60,17 +60,7 @@ export interface BpReading {
const SYS_HYPOTENSION_FLOOR = 90;
const DIA_HYPOTENSION_FLOOR = 50;
const BERLIN_DAY_FORMATTER = new Intl.DateTimeFormat("en-CA", {
timeZone: "Europe/Berlin",
year: "numeric",
month: "2-digit",
day: "2-digit",
});
function toBerlinDayKey(date: Date): string {
// en-CA gives us the YYYY-MM-DD shape directly.
return BERLIN_DAY_FORMATTER.format(date);
}
import { toBerlinDayKey } from "@/lib/tz/resolver";
/**
* Pair a systolic reading with its closest diastolic by absolute time
+7 -14
View File
@@ -16,12 +16,7 @@
* does not produce 360 zero-rows of noise.
*/
const BERLIN_DAY_FORMATTER = new Intl.DateTimeFormat("en-US", {
timeZone: "Europe/Berlin",
year: "numeric",
month: "2-digit",
day: "2-digit",
});
import { toBerlinYmd as toBerlinYmdStrings } from "@/lib/tz/resolver";
const MS_PER_DAY = 24 * 60 * 60 * 1000;
@@ -65,14 +60,12 @@ interface BerlinYmd {
}
function toBerlinYmd(date: Date): BerlinYmd {
const parts = BERLIN_DAY_FORMATTER.formatToParts(date);
const year = Number(parts.find((p) => p.type === "year")?.value);
const month = Number(parts.find((p) => p.type === "month")?.value);
const day = Number(parts.find((p) => p.type === "day")?.value);
if (!year || !month || !day) {
throw new Error("Could not derive Berlin Y-M-D");
}
return { year, month, day };
const parts = toBerlinYmdStrings(date);
return {
year: Number(parts.year),
month: Number(parts.month),
day: Number(parts.day),
};
}
/** UTC midnight of the Berlin calendar day containing `date`. */
+16 -1
View File
@@ -74,6 +74,21 @@ const BERLIN_DAY_FORMATTER = new Intl.DateTimeFormat("en-US", {
* stored zone.
*/
export function toBerlinDayKey(date: Date): string {
const { year, month, day } = toBerlinYmd(date);
return `${year}-${month}-${day}`;
}
/**
* Same formatter, but returns the numeric `{year, month, day}` parts
* instead of the reassembled string. Used by `bucket-series.ts` for
* `Date.UTC(year, month - 1, day)` arithmetic where parsing the string
* back would be wasted work.
*/
export function toBerlinYmd(date: Date): {
year: string;
month: string;
day: string;
} {
const parts = BERLIN_DAY_FORMATTER.formatToParts(date);
const year = parts.find((part) => part.type === "year")?.value;
const month = parts.find((part) => part.type === "month")?.value;
@@ -83,7 +98,7 @@ export function toBerlinDayKey(date: Date): string {
throw new Error("Could not derive Berlin day key");
}
return `${year}-${month}-${day}`;
return { year, month, day };
}
const TTL_MS = 60_000;