Files
request-portal/src/webparts/requestPortal/shared/dateUtils.ts
T
Тимур Городецкий f8ab2a1d71
Tests / frontend-test (push) Successful in 2m1s
fix: даты «только дата» больше не сдвигаются на день назад
SharePoint хранит поле «только дата» как полночь по поясу сайта (UTC+5)
в UTC: «05.10» приходит из REST как 2026-10-04T19:00:00Z. Формы брали
первые 10 символов и показывали 04.10, а каждое пересохранение (полное
право, исполнитель, повторная отправка) записывало дату ещё на день раньше.

Чтение всех дат идёт через spDateOnlyToIso (округление до ближайшей
полуночи UTC), «сегодня» — через todayIsoDate вместо toISOString, который
до 05:00 давал вчерашнее число. Уже сдвинутые записи в SP не исправляются.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 12:41:18 +05:00

57 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
function pad2(n: number): string {
return n < 10 ? `0${n}` : `${n}`;
}
/** Сегодня + n дней в формате YYYY-MM-DD (для min/max у input type=date). */
export function isoDatePlusDays(days: number): string {
const d = new Date();
d.setDate(d.getDate() + days);
return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
}
/**
* Сегодня + n КАЛЕНДАРНЫХ месяцев в формате YYYY-MM-DD (для min/max у input
* type=date) — не приближение через 30 дней: `setMonth` сам разносит месяцы
* разной длины (28–31 день) и года на границе декабря/января.
*
* 31 января + 1 месяц → JS даёт 3 марта (переносит лишние дни на следующий
* месяц, а не откатывает до последнего числа) — для месячного уведомления это
* не проблема (крайняя ранняя дата и так сдвигается на несколько дней позже,
* не раньше), но не считать это «ровно через месяц» в общем случае.
*/
export function isoDatePlusMonths(months: number): string {
const d = new Date();
d.setMonth(d.getMonth() + months);
return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
}
/** Сегодня по МЕСТНОМУ времени в формате YYYY-MM-DD (toISOString дал бы дату по UTC — до 05:00 вчерашнюю). */
export function todayIsoDate(): string {
return isoDatePlusDays(0);
}
const HALF_DAY_MS = 12 * 60 * 60 * 1000;
/**
* Значение поля SharePoint «только дата» → YYYY-MM-DD для input type=date.
*
* REST отдаёт такие поля в UTC: «5 октября» на сайте с поясом UTC+5 приходит
* как «2026-10-04T19:00:00Z», и `slice(0, 10)` давал 4-е число (а каждое
* пересохранение сдвигало дату ещё на день назад). Округляем до ближайшей
* полуночи UTC (+12 ч) — так верно для любого пояса сайта в пределах ±11 ч и
* не зависит от пояса браузера.
*/
export function spDateOnlyToIso(value: unknown): string {
if (typeof value !== 'string' || value === '') return '';
if (value.indexOf('T') < 0) return value.slice(0, 10);
const ms = Date.parse(value);
if (isNaN(ms)) return value.slice(0, 10);
return new Date(ms + HALF_DAY_MS).toISOString().slice(0, 10);
}
/** YYYY-MM-DD → дд.мм.гггг, для текста ошибок валидации. Невалидную строку возвращает как есть. */
export function formatIsoDate(iso: string): string {
const [y, m, d] = iso.split('-');
return y && m && d ? `${d}.${m}.${y}` : iso;
}