Я ненавижу работать с часовыми поясами. Такое себе откровение, конечно. Мне кажется это бесит любого человека, который имел работу с пользователями в нескольких часовых поясах.

В аду точно есть специальный котёл, где грешникам нужно высчитывать время по разным часовым поясам на границы перехода дней.

Но как ни крути, с этим приходится иметь дело, и это всегда боль и страдания. Я работал во многих компаниях и с кучей проектов, но проблема отображения и сохранения дат была всегда.

Буду рассказывать на примере работы с моим ботом, который является пет-проектом. Добавление туда поддержки таймзон я откладывал как можно дольше, но в какой-то момент пришлось пересилить себя и сделать это.

Бот нужен, чтобы записаться на игры с друзьями в конкретный день, время и игру. Также он посылает нотификации за час до игры.

Вот сам бот — @game_session_scheduler_bot

Вот канал с обновлениями — https://t.me/gamescheduler

Первая проблема это определиться, как отображать даты и время и как их сохранять. Самый простой способ, и самый эффективный, это показывать локальное время клиента, а сохранять в UTC. А что вообще считать локальным временем клиента в телеграм-боте? Вот несколько вариантов:

  1. Время установленное в самом приложении телеграм

  2. Время в браузере

  3. Время основанное на локации, где сейчас находится пользователь

  4. Время системы

  5. Время, которое пользователь явно укажет в профиле самого бота

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

Идём дальше, а какое время нужно прислать из клиента? Можно присылать UTC, но тогда клиент должен знать таймзону, а он не знает (так как клиент это телеграм). Значит присылаем как есть, а потом переводим в UTC и сохраняем. Тут тоже есть варианты как сохранять:

  1. Прям как пришло, так и сохранять, тогда никуда не надо будет переводить

  2. Делать преобразования и сохранять в часовом поясе сервера

  3. Сохранять в UTC

  4. Сохранять в каком-то общем часовом поясе

Первый вариант не работает, если у вас видят даты пользователи из нескольких часовых поясов. Остальные три одинаковые по сути, но разный часовой пояс будет базовым. У себя в боте мне пришлось ввести ещё один часовый пояс, который нужно настроить пользователю - часовой пояс группы. Группа это объединение людей, которые играют вместе и они могут иметь совершенно разные часовые пояса и это не было бы проблемой, если бы не одно НО, как определить день игры?

Простой пример. Я в часовой зоне МСК записался на игру 1-ого января в 11 вечера, мой друг из Сибири записался на это же время, но для него это будет 2-ое января 3 часа ночи. Что в данном случае считать днём игры? Я не нашёл правильного ответа, поэтому днём игры я считаю время по таймзоне группы, если она МСК, то это 1-ое января, если Сибирь, то 2-ое.

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

Ещё хочется сказать, что нужно использовать обязательно таймзоны, а не просто смещения. Почему? К сожалению, в нашем мире часовой пояс зависит ещё и от времени года. Поэтому в одну дату это +2, а в другую уже +3. Чтобы поддерживать этот хаос ещё и задним числом, то лучше использовать именно таймзону, которая может рассчитать какое смещение было в какой день.

Иногда я с содроганием задумываюсь, что делать с переводом времени, когда люди полетят на Марс, а там день 24 часа 39 минут. Единственная надежда, что это будет нескоро.

Итог: храните всё в UTC или таймзоне вашего объединения пользователей, используйте реальную таймзону (а не смещение), дайте пользователю явно указать свой часовой пояс.

А есть ли у вас какой-то секрет работы с датами, возникают ли проблемы? Может быть в моей ситуации тоже есть решение лучше, буду рад его услышать.

Ссылка на предыдущие статьи:

Комментарии (3)


  1. APXEOLOG
    31.07.2025 19:51

    Хранить в UTC, хранить часовой пояс пользователя (не смещение). Все вычисления делать только с помощью специализированных библиотек. В часовых поясах столько тонкостей, что руками туда лучше не лезть


    1. alados Автор
      31.07.2025 19:51

      Сейчас я примерно так и делаю, только храню не UTC, а время группы, учитывая смещения от времени пользователя.

      Но даты это действительно сложно, а так как это пет проект, то ещё и тестировать тяжело


  1. withkittens
    31.07.2025 19:51

    В .NET вопрос часовых поясов, дат и времён, в общем-то, решён: NodaTime. От вас нужно правильно подобрать входные типы данных (в библиотеке 7 видов дат и времён), остальное вам подскажут типы.