mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 22:32:04 +00:00
feat(lint): refuse UTC day keys outside the time zone module
`instant.toISOString().slice(0, 10)` and parsing a key back as UTC midnight are the idioms behind every day-boundary fix this year: the evening west of UTC and the small hours east of it land on the neighbouring day. A new rule, healthlog/no-utc-day-key, refuses them in src/ outside src/lib/tz and tests, and refuses a disable directive for itself that is not next-line or gives no reason. The time zone module now names every legitimate form: userDayKey for a person's day, dateOnlyKey / dateOnlyAtNoonUtc / dayKeyAsUtcMidnight for date-only values and day labels, daysBetweenDateKeys / weekdayOfDateKey / isCalendarDateKey / statedDateKey for key arithmetic and parsing. Of the 133 sites the rule found, 84 are gone. Most moved onto a named helper with no change in behaviour; these changed behaviour: - cycle calendar, insights, Coach snapshot and prediction refresh start their lookbacks at the first instant of the user's day - a model-transcribed date like "June 10, 2026" no longer lands a day early in a process east of UTC (documents and lab scans) - a custom report range covers exactly the picked days in the profile zone instead of starting the evening before west of UTC - date-of-birth pickers cap at the user's today, not the UTC one - an allergy onset date is stored at noon UTC like other date-only values - the report's cycle summary, the Coach's usual BP range and the intake projector's rollup recompute use the user's day - vaccination dates render as dates instead of the previous evening 49 remain, each with its reason on the line above: 39 UTC by design (15 file name stamps, rollup and object keys, the UTC-day score engines) and 10 marked baseline. A guard test requires a classified reason on every directive and holds the baseline to a ceiling that only goes down.
This commit is contained in:
1 parent
5820078008
commit
7c5ff89def
105 files changed
+807
-200
No files matched your search
@@ -28,8 +28,8 @@ import {
|
||||
type DailyEnvironmentObservation,
|
||||
} from "@/lib/environment/open-meteo";
|
||||
import type { EnvironmentLocationSource } from "@/generated/prisma/client";
|
||||
import { shiftDateKey } from "@/lib/tz/format";
|
||||
|
||||
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
||||
/** Default lookback window (days) for the nightly fetch — absorbs the archive
|
||||
* settling lag and any days missed across worker reboots. */
|
||||
export const ENVIRONMENT_LOOKBACK_DAYS = 7;
|
||||
@@ -63,19 +63,15 @@ interface TravelOverride {
|
||||
|
||||
/** UTC YYYY-MM-DD for `date` (used to bound the default lookback window). */
|
||||
export function utcDayKey(date: Date): string {
|
||||
// eslint-disable-next-line healthlog/no-utc-day-key -- UTC by design: the environment module keys homeSince and the backfill window on UTC days throughout, and the worker compares against the same keys
|
||||
return date.toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
/** Inclusive list of YYYY-MM-DD keys from `start` to `end` (date arithmetic). */
|
||||
export function enumerateDays(start: string, end: string): string[] {
|
||||
const out: string[] = [];
|
||||
const [sy, sm, sd] = start.split("-").map(Number);
|
||||
const [ey, em, ed] = end.split("-").map(Number);
|
||||
let cur = Date.UTC(sy, sm - 1, sd);
|
||||
const last = Date.UTC(ey, em - 1, ed);
|
||||
while (cur <= last) {
|
||||
out.push(new Date(cur).toISOString().slice(0, 10));
|
||||
cur += MS_PER_DAY;
|
||||
for (let cur = start; cur <= end; cur = shiftDateKey(cur, 1)) {
|
||||
out.push(cur);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user