From 263d35c68848e1a6ca2d97f0f898b1a0169e9bc0 Mon Sep 17 00:00:00 2001 From: tajniak81 <13187254+tajniak81@users.noreply.github.com> Date: Thu, 3 Sep 2026 20:29:49 +0200 Subject: [PATCH] Picking a clock picks its separator too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 24-hour read as 13.45 in Denmark, because that is how Danish writes a clock and toLocaleTimeString was doing as it was told. But somebody who leaves "follow the region" and picks 24-hour has just said they want the region to stop deciding — and they mean 13:45. So the two explicit modes build the string from formatToParts and pin the mark between the hour and the minute. Only that one literal is replaced: everything else stays the locale's, which is why Japanese keeps 午後 in front of it and English keeps its lowercase pm after. 12-hour got the same for free — it had the identical 01.45 pm. Auto is left alone. A setting that says to follow the region has no business arguing with it. Co-Authored-By: Claude Opus 5 --- Web App/web/src/lib/format.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Web App/web/src/lib/format.js b/Web App/web/src/lib/format.js index f5cda20..451b1f6 100644 --- a/Web App/web/src/lib/format.js +++ b/Web App/web/src/lib/format.js @@ -92,9 +92,27 @@ export function formatTime(value) { const d = value instanceof Date ? value : new Date(value); if (isNaN(d)) return "—"; const opts = { hour: "2-digit", minute: "2-digit" }; - if (prefs.timeFormat === "24") opts.hourCycle = "h23"; - else if (prefs.timeFormat === "12") opts.hourCycle = "h12"; - return d.toLocaleTimeString(prefs.locale || undefined, opts); + const mode = prefs.timeFormat; + if (mode !== "24" && mode !== "12") { + // Auto is the region's, whole: 13.45 is how Danish writes a clock, and a + // setting that says "follow the region" has no business arguing with it. + return d.toLocaleTimeString(prefs.locale || undefined, opts); + } + + // Asking for a clock outright is asking for its separator too. Somebody who + // picked "24-hour" means 13:45, not the 13.45 their region would have written + // — the point of leaving auto was to stop the region deciding. Only the mark + // between the hour and the minute is pinned: the rest is still the locale's, + // including whether there is an am/pm marker, what it reads and where it sits. + opts.hourCycle = mode === "24" ? "h23" : "h12"; + const parts = new Intl.DateTimeFormat(prefs.locale || undefined, opts).formatToParts(d); + return parts + .map((p, i) => + p.type === "literal" && parts[i - 1]?.type === "hour" && parts[i + 1]?.type === "minute" + ? ":" + : p.value + ) + .join(""); } // Every number we render goes through here so the grouping separator follows