(medium) Pipeline24moBlock.tsx / fmtMonth: new Date(ISO-date) даёт UTC-полночь — месяц «Сдача» уезжает на предыдущий в отрицательных TZ #1453

Closed
opened 2026-06-15 05:55:51 +00:00 by bot-backend · 1 comment
Collaborator

Severity: medium · Категория: report · Файл: frontend/src/components/site-finder/Pipeline24moBlock.tsx:35-41

Pipeline24moBlock.tsx:35-41. fmtMonth парсит ready_dt через new Date(iso) (строка 38), форматирует toLocaleDateString('ru-RU',{year,month}). Для '2026-07-01' JS трактует как UTC-полночь; в локали с отрицательным смещением → 2026-06-30 → «06.2026» вместо «07.2026». Колонка «Сдача» таблицы топ-объектов (строка 384). planned_commissioning часто нормализуют к 1-му числу месяца/квартала — регулярно попадает под баг. Контраст: MarketLayers.formatReadyDt (85-89) решает это regex-парсом. Оговорка: целевая аудитория РФ (UTC+) — у них сдвиг вперёд, месяц не меняется; баг реален только в UTC-локалях, поэтому латентен. Фикс: regex-парс как в formatReadyDt либо new Date(iso+'T00:00:00').

Почему баг: Это та же ловушка, от которой осознанно ушёл MarketLayers.formatReadyDt (его комментарий прямо: «показываем как есть, без таймзонных сюрпризов от Date()»). Здесь же Date() переиспользован. Колонка «Сдача» в таблице топ-объектов покажет неверный месяц/год для дат, попадающих на 1-е число (а planned_commissioning часто нормализуют к началу месяца/квартала). Для аудитории-девелопера квартал/месяц сдачи конкурента — значимая цифра.

Как чинить: Парсить так же, как в MarketLayers: регексом по 'YYYY-MM' без конструктора Date, либо new Date(Date.UTC(y, m-1, d)) и форматировать в UTC, либо new Date(iso + 'T00:00:00') (локальная полночь). Достаточно взять первые 7 символов 'YYYY-MM' и переставить.


deep-audit «армия ботов 2» · verify+harden, confidence 0.9 · unit U93

**Severity:** medium · **Категория:** report · **Файл:** `frontend/src/components/site-finder/Pipeline24moBlock.tsx:35-41` Pipeline24moBlock.tsx:35-41. fmtMonth парсит ready_dt через new Date(iso) (строка 38), форматирует toLocaleDateString('ru-RU',{year,month}). Для '2026-07-01' JS трактует как UTC-полночь; в локали с отрицательным смещением → 2026-06-30 → «06.2026» вместо «07.2026». Колонка «Сдача» таблицы топ-объектов (строка 384). planned_commissioning часто нормализуют к 1-му числу месяца/квартала — регулярно попадает под баг. Контраст: MarketLayers.formatReadyDt (85-89) решает это regex-парсом. Оговорка: целевая аудитория РФ (UTC+) — у них сдвиг вперёд, месяц не меняется; баг реален только в UTC-локалях, поэтому латентен. Фикс: regex-парс как в formatReadyDt либо new Date(iso+'T00:00:00'). **Почему баг:** Это та же ловушка, от которой осознанно ушёл MarketLayers.formatReadyDt (его комментарий прямо: «показываем как есть, без таймзонных сюрпризов от Date()»). Здесь же Date() переиспользован. Колонка «Сдача» в таблице топ-объектов покажет неверный месяц/год для дат, попадающих на 1-е число (а planned_commissioning часто нормализуют к началу месяца/квартала). Для аудитории-девелопера квартал/месяц сдачи конкурента — значимая цифра. **Как чинить:** Парсить так же, как в MarketLayers: регексом по 'YYYY-MM' без конструктора Date, либо new Date(Date.UTC(y, m-1, d)) и форматировать в UTC, либо new Date(iso + 'T00:00:00') (локальная полночь). Достаточно взять первые 7 символов 'YYYY-MM' и переставить. --- <sub>deep-audit «армия ботов 2» · verify+harden, confidence 0.9 · unit U93</sub>
bot-backend added the
week ревью 1
label 2026-06-15 05:55:51 +00:00
bot-backend added the
scope/frontend
label 2026-06-15 11:02:07 +00:00
Owner

🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)

Текущее состояние кода: frontend/src/components/site-finder/Pipeline24moBlock.tsx:35-41 (fmtMonth), вызов в колонке «Сдача» :384 ({fmtMonth(obj.ready_dt)}, заголовок :350). Эталон — frontend/src/components/site-finder/MarketLayers.tsx:83-89 (formatReadyDt).

Корень: fmtMonth парсит дату через new Date(iso) (стр.38). Для date-only ISO ('2026-07-01') JS трактует строку как UTC-полночь; в UTC-/локали toLocaleDateString('ru-RU',{year,month}) (стр.40) откатывает на предыдущий день → месяц «07.2026» становится «06.2026». MarketLayers.formatReadyDt осознанно ушёл от этого regex-парсом (комментарий стр.85-86: «показываем как есть, без таймзонных сюрпризов от Date()»), здесь же Date() переиспользован.

Что править:

  • Заменить new Date(iso)-ветку на regex-парс YYYY-MM как в MarketLayers.formatReadyDt:87-89 (/^(\d{4})-(\d{2})-(\d{2})/), без конструктора Date. Альтернатива — new Date(iso + 'T00:00:00') (локальная полночь) или формат в UTC.
  • Латентность реальна: РФ-аудитория в UTC+ сдвигается вперёд (месяц не меняется), баг проявляется только в UTC-/локалях — но planned_commissioning часто нормализован к 1-му числу месяца/квартала, т.е. ровно граничный случай.

Что посмотреть:

  • Код: Pipeline24moBlock.tsx:35-41, MarketLayers.tsx:83-89 (готовый regex-helper для переиспользования); добавить unit-тест на '2026-07-01'.
  • Vault: релевантных заметок не найдено.
**🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)** **Текущее состояние кода:** `frontend/src/components/site-finder/Pipeline24moBlock.tsx:35-41` (`fmtMonth`), вызов в колонке «Сдача» `:384` (`{fmtMonth(obj.ready_dt)}`, заголовок `:350`). Эталон — `frontend/src/components/site-finder/MarketLayers.tsx:83-89` (`formatReadyDt`). **Корень:** `fmtMonth` парсит дату через `new Date(iso)` (стр.38). Для date-only ISO (`'2026-07-01'`) JS трактует строку как UTC-полночь; в UTC-/локали `toLocaleDateString('ru-RU',{year,month})` (стр.40) откатывает на предыдущий день → месяц «07.2026» становится «06.2026». `MarketLayers.formatReadyDt` осознанно ушёл от этого regex-парсом (комментарий стр.85-86: «показываем как есть, без таймзонных сюрпризов от Date()»), здесь же `Date()` переиспользован. **Что править:** - Заменить `new Date(iso)`-ветку на regex-парс `YYYY-MM` как в `MarketLayers.formatReadyDt:87-89` (`/^(\d{4})-(\d{2})-(\d{2})/`), без конструктора `Date`. Альтернатива — `new Date(iso + 'T00:00:00')` (локальная полночь) или формат в UTC. - Латентность реальна: РФ-аудитория в UTC+ сдвигается вперёд (месяц не меняется), баг проявляется только в UTC-/локалях — но `planned_commissioning` часто нормализован к 1-му числу месяца/квартала, т.е. ровно граничный случай. **Что посмотреть:** - Код: `Pipeline24moBlock.tsx:35-41`, `MarketLayers.tsx:83-89` (готовый regex-helper для переиспользования); добавить unit-тест на `'2026-07-01'`. - Vault: релевантных заметок не найдено.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1453
No description provided.