mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
The coach snapshot tzDayKey, the dashboard verdict dayKeyInTz, and the mood-entry moodDateKey each carried their own Intl day-key formatter (en-CA / en-CA / sv-SE). Delegate all three to the canonical userDayKey so every day-bucket key stays byte-aligned and the locale decision lives in one place. Behaviour-preserving.
62 lines
2.4 KiB
TypeScript
62 lines
2.4 KiB
TypeScript
/**
|
|
* v1.4.25 W7b — per-row timezone attribution for MoodEntry rows.
|
|
*
|
|
* Background. Up to v1.4.24 the mood-entries POST handler computed
|
|
* `MoodEntry.date` (YYYY-MM-DD) by formatting `moodLoggedAt` in
|
|
* Europe/Berlin regardless of where the user actually was. That is
|
|
* correct for users in DE, wrong for everyone else: a 23:45 NZST
|
|
* reading would store `date` as the Berlin day, one day earlier than
|
|
* the user's own "today".
|
|
*
|
|
* Decision A (proposal §7): forward-only fix.
|
|
*
|
|
* - Schema. Add nullable `MoodEntry.tz` column (migration 0044).
|
|
*
|
|
* - Writes. Every new row captures the user's current
|
|
* `displayTimezone`, stores it on the row's `tz` column, and
|
|
* computes `date` using THAT zone.
|
|
*
|
|
* - Reads. Rows with `tz === null` (legacy) are interpreted as if
|
|
* `tz === "Europe/Berlin"`, matching the implicit write-time
|
|
* assumption. Rows with explicit `tz` are interpreted in their
|
|
* stored zone. No backfill is required because the read-side
|
|
* interpretation rebuilds the historical bucketing without
|
|
* touching the data.
|
|
*
|
|
* The helpers below are the single source of truth for both the write
|
|
* path (`moodDateKey`) and any read path that needs to re-interpret a
|
|
* legacy date string (`effectiveMoodTz`).
|
|
*/
|
|
|
|
import { userDayKey } from "@/lib/tz/format";
|
|
|
|
export const DEFAULT_TIMEZONE = "Europe/Berlin";
|
|
|
|
/**
|
|
* Build the `YYYY-MM-DD` day-key for a mood entry given the user's
|
|
* timezone at write time. Used by `POST /api/mood-entries` and the
|
|
* `PUT /api/mood-entries/:id` route when `moodLoggedAt` changes.
|
|
*
|
|
* Delegates to the canonical `userDayKey` so the mood day-bucket key
|
|
* stays byte-identical to every other day-bucket surface. The ISO
|
|
* YYYY-MM-DD shape is unchanged from the legacy sv-SE formatter; the
|
|
* empty-tz fallback to Europe/Berlin is preserved here.
|
|
*/
|
|
export function moodDateKey(date: Date, tz: string): string {
|
|
const safe = tz && tz.length > 0 ? tz : DEFAULT_TIMEZONE;
|
|
return userDayKey(date, safe);
|
|
}
|
|
|
|
/**
|
|
* Resolve the effective timezone for a MoodEntry row. Read-path
|
|
* helpers (e.g. analytics aggregation by mood-day, export) call this
|
|
* to know which zone the row's `date` string is anchored to. A
|
|
* non-null `tz` column takes precedence; legacy rows fall back to
|
|
* Europe/Berlin.
|
|
*/
|
|
export function effectiveMoodTz(row: {
|
|
tz: string | null | undefined;
|
|
}): string {
|
|
return row.tz && row.tz.length > 0 ? row.tz : DEFAULT_TIMEZONE;
|
|
}
|