Clean up detail-page time formatting

Render ISO timestamps as "23:30 UTC+03:00 17.04.2026" instead of the
raw "2026-04-17T23:30:00+03:00" that the API returns. Applies to the
per-leg station blocks (new LegStation helper) plus the
Registration / Boarding / Deboarding panels.

formatLocalTime now preserves the wall-clock in the source string
(previously `new Date(...)` would shift it to the runtime's locale).
Added formatUtcOffset (UTC±HH:mm) and formatDayMonthYear (DD.MM.YYYY)
helpers next to it.

Also ship the Angular footer notes on the details page (estimated
times / local-time disclaimer) and added BOARD.LOCAL-TIME-NOTE,
BOARD.ESTIMATED-TIME-NOTE keys to all nine locales.
This commit is contained in:
2026-04-17 23:58:22 +03:00
parent ad8367c203
commit 4d73e2fd3c
15 changed files with 1824 additions and 1643 deletions
+45
View File
@@ -66,6 +66,51 @@ export function formatDate(
});
}
const ISO_OFFSET_RE = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::\d{2})?(Z|[+-]\d{2}:?\d{2})?$/;
const BARE_HH_MM_RE = /^(\d{1,2}):(\d{2})(?::\d{2})?$/;
/**
* Return the HH:mm portion of an ISO string without reprojecting it to the
* browser's local timezone. The API sends strings like
* "2026-04-17T23:30:00+03:00"; `new Date(...)` would shift it to whatever
* locale the SSR/client runs in. We want the wall-clock value that was in
* the string. Plain "HH:mm" / "HH:mm:ss" inputs pass through unchanged.
*/
export function formatLocalTime(iso: string): string {
const full = ISO_OFFSET_RE.exec(iso);
if (full) return `${full[4]}:${full[5]}`;
const bare = BARE_HH_MM_RE.exec(iso);
if (bare) return `${bare[1]!.padStart(2, "0")}:${bare[2]}`;
return formatTime(iso); // fall back to Date-based formatter
}
/**
* Extract the UTC offset (e.g. "+03:00", "-05:00", "UTC+00:00") from an
* ISO string. Returns "UTC±HH:mm" or "" if the string has no offset.
*/
export function formatUtcOffset(iso: string): string {
const m = ISO_OFFSET_RE.exec(iso);
const off = m?.[6];
if (!off) return "";
if (off === "Z") return "UTC+00:00";
const normalized = off.includes(":") ? off : `${off.slice(0, 3)}:${off.slice(3)}`;
return `UTC${normalized}`;
}
/**
* "DD.MM.YYYY" — matches the Angular board footer style.
*/
export function formatDayMonthYear(iso: string): string {
const m = ISO_OFFSET_RE.exec(iso);
if (m) return `${m[3]}.${m[2]}.${m[1]}`;
const d = new Date(iso);
if (Number.isNaN(d.getTime())) return "";
const day = String(d.getDate()).padStart(2, "0");
const month = String(d.getMonth() + 1).padStart(2, "0");
return `${day}.${month}.${d.getFullYear()}`;
}
/**
* Calculate the day offset between two dates (ignoring time).
* Returns 0 if same day, +1 if actual is the next day, etc.