Если слоты записи отображаются в неправильном часовом поясе, клиент выбирает одно время, а сотрудник видит другое. Ошибка может появляться только у путешествующих пользователей, отдельных филиалов или на датах перехода летнего времени.

Нужно разделить три понятия: абсолютный момент, часовой пояс филиала и локальное отображение пользователя. Добавление фиксированных трех часов в одном месте не исправляет модель и ломает другие регионы.

Зафиксируйте время на каждом этапе

Проследите один слот от графика сотрудника до сохраненной записи и уведомления.

  • Список показывает верно, а подтверждение сдвинуто.
  • Администратор и клиент видят разные часы.
  • Ошибка появляется только после смены часового пояса устройства.
  • Слот на границе DST отсутствует или дублируется.

Почему возникает проблема

Дата без timezone интерпретируется по-разному в базе, backend, JavaScript и календаре.

  • Backend возвращает локальное время без offset.
  • База хранит смесь UTC и локальных значений.
  • Frontend повторно применяет смещение браузера.
  • График филиала рассчитывается в timezone сервера.
  • Внешний календарь использует другой идентификатор зоны.

Пошаговая диагностика

Используйте конкретную дату и записывайте ISO-значение вместе с timezone.

  1. Сверьте timezone филиала, пользователя, сервера и базы.
  2. Проверьте исходный timestamp и offset в API.
  3. Сравните создание слота, выбор, сохранение и уведомление.
  4. Повторите тест на зимней и летней дате.
  5. Проверьте импорт и экспорт внешнего календаря.

Храните момент и зону раздельно

Абсолютная запись хранится в UTC, а бизнес-расписание привязано к именованной зоне филиала.

  • Начало записи хранится как однозначный момент.
  • Филиал хранит IANA timezone, а не фиксированный offset.
  • Frontend получает ISO 8601 с явным смещением.
  • Уведомление указывает зону или понятное локальное время.

Как исправить проблему

Исправьте контракт даты целиком, а не отдельное отображение.

  1. Нормализуйте хранение новых записей в UTC.
  2. Рассчитывайте рабочие окна в зоне филиала.
  3. Передавайте offset или Z в каждом API timestamp.
  4. Уберите ручные прибавления часов на frontend.
  5. Мигрируйте старые данные только после определения их исходной зоны.

Как проверить результат

  • Один слот означает одинаковый момент для клиента и сотрудника.
  • Смена timezone устройства меняет только представление.
  • DST-даты не создают невозможные или двойные записи.
  • Письма и календари показывают согласованное время.

Типичные ошибки

  • Хранить локальную дату без timezone.
  • Использовать фиксированный offset для региона с DST.
  • Применять смещение и на backend, и на frontend.
  • Массово сдвигать старые записи без аудита.

Как предотвратить повторение

  • Зафиксируйте контракт даты в API.
  • Добавьте тесты нескольких зон и DST.
  • Храните именованную timezone филиала.
  • Мониторьте расхождения календарных интеграций.

Когда нужна помощь

Если слоты смещаются по времени, я прослежу timestamp через базу, API, frontend и календарь, исправлю модель UTC и timezone и помогу безопасно нормализовать старые записи.