pcp-tgu-ops-ui: единый UTC во времени; дефолтный диапазон Планы
Время бэка (naive LocalDateTime и OffsetDateTime) разбиралось через new Date(string)/Date.parse, из-за чего naive-строки трактовались как локальное время браузера: вкладки расходились по времени, а путь создания заявки сдвигал введённое время на офсет. Ввёл единую точку utils/utcTime (parseUtc/formatUtc*/toUtcInputValue/toUtcIso) и перевёл на неё вкладки «Планы», «Заявки», «Карта 2D» — чтение, пикеры диапазона, создание заявки. Плюс на вкладке «Планы» график по умолчанию открывается на интервал сейчас−30 мин … сейчас+3 дня. docs/tasks/TASK_datetime-utc-consistency.md — ТЗ на сверку всей группы сервисов pcp на единообразие времени.
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Единый разбор и форматирование времени в UTC.
|
||||
*
|
||||
* Бэкенд (Kotlin `LocalDateTime`) отдаёт время как ISO-строку без зоны
|
||||
* (например `"2026-05-29T01:00:00"`) и по соглашению системы это UTC.
|
||||
* Конструктор `Date`/`Date.parse` трактует такую строку как локальное время
|
||||
* браузера, поэтому naive-строки нужно парсить явно как UTC, а отображать —
|
||||
* с `timeZone: "UTC"`. Весь интерфейс ТГУ работает в UTC.
|
||||
*/
|
||||
|
||||
/** Разбирает ISO-строку как UTC: если зоны нет — добавляет `Z`. */
|
||||
export function parseUtc(value: string): number {
|
||||
const hasZone = /[zZ]$|[+-]\d{2}:?\d{2}$/.test(value);
|
||||
return Date.parse(hasZone ? value : `${value}Z`);
|
||||
}
|
||||
|
||||
/** Дата-время в UTC, формат ru-RU. */
|
||||
export function formatUtcDateTime(ms: number): string {
|
||||
return new Date(ms).toLocaleString("ru-RU", {
|
||||
timeZone: "UTC",
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit"
|
||||
});
|
||||
}
|
||||
|
||||
/** Дата (дд.мм) в UTC. */
|
||||
export function formatUtcDate(ms: number): string {
|
||||
return new Date(ms).toLocaleDateString("ru-RU", { timeZone: "UTC", day: "2-digit", month: "2-digit" });
|
||||
}
|
||||
|
||||
/** Время (чч:мм) в UTC. */
|
||||
export function formatUtcTime(ms: number): string {
|
||||
return new Date(ms).toLocaleTimeString("ru-RU", { timeZone: "UTC", hour: "2-digit", minute: "2-digit" });
|
||||
}
|
||||
|
||||
/** Значение для `<input type="datetime-local">` в UTC (`YYYY-MM-DDTHH:mm`). */
|
||||
export function toUtcInputValue(ms: number): string {
|
||||
return new Date(ms).toISOString().slice(0, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Naive-строку (из `datetime-local`) трактует как UTC и возвращает ISO с `Z`.
|
||||
* Для бэкендов с `OffsetDateTime` на границе API (напр. pcp-request-service):
|
||||
* пользователь вводит время по UTC, отправляем его же как UTC-смещение.
|
||||
*/
|
||||
export function toUtcIso(value: string): string {
|
||||
return new Date(parseUtc(value)).toISOString();
|
||||
}
|
||||
Reference in New Issue
Block a user