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

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

Буду рассказывать на примере работы с моим ботом, который является пет-проектом. Добавление туда поддержки таймзон я откладывал как можно дольше, но в какой-то момент пришлось пересилить себя и сделать это.
Бот нужен, чтобы записаться на игры с друзьями в конкретный день, время и игру. Также он посылает нотификации за час до игры.
Вот сам бот — @game_session_scheduler_bot
Вот канал с обновлениями — https://t.me/gamescheduler
Первая проблема это определиться, как отображать даты и время и как их сохранять. Самый простой способ, и самый эффективный, это показывать локальное время клиента, а сохранять в UTC. А что вообще считать локальным временем клиента в телеграм-боте? Вот несколько вариантов:
Время установленное в самом приложении телеграм
Время в браузере
Время основанное на локации, где сейчас находится пользователь
Время системы
Время, которое пользователь явно укажет в профиле самого бота
И это могут быть вообще разные часовые пояса. Ответ на самом деле здесь простой, телеграм не так много информации даёт в запросе и никакой информации о часовом поясе вообще нет, поэтому необходимо, чтобы пользователь вручную, для конкретного бота, выбрал часовой пояс.
Идём дальше, а какое время нужно прислать из клиента? Можно присылать UTC, но тогда клиент должен знать таймзону, а он не знает (так как клиент это телеграм). Значит присылаем как есть, а потом переводим в UTC и сохраняем. Тут тоже есть варианты как сохранять:
Прям как пришло, так и сохранять, тогда никуда не надо будет переводить
Делать преобразования и сохранять в часовом поясе сервера
Сохранять в UTC
Сохранять в каком-то общем часовом поясе
Первый вариант не работает, если у вас видят даты пользователи из нескольких часовых поясов. Остальные три одинаковые по сути, но разный часовой пояс будет базовым. У себя в боте мне пришлось ввести ещё один часовый пояс, который нужно настроить пользователю - часовой пояс группы. Группа это объединение людей, которые играют вместе и они могут иметь совершенно разные часовые пояса и это не было бы проблемой, если бы не одно НО, как определить день игры?
Простой пример. Я в часовой зоне МСК записался на игру 1-ого января в 11 вечера, мой друг из Сибири записался на это же время, но для него это будет 2-ое января 3 часа ночи. Что в данном случае считать днём игры? Я не нашёл правильного ответа, поэтому днём игры я считаю время по таймзоне группы, если она МСК, то это 1-ое января, если Сибирь, то 2-ое.

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

Итог: храните всё в UTC или таймзоне вашего объединения пользователей, используйте реальную таймзону (а не смещение), дайте пользователю явно указать свой часовой пояс.
А есть ли у вас какой-то секрет работы с датами, возникают ли проблемы? Может быть в моей ситуации тоже есть решение лучше, буду рад его услышать.
Ссылка на предыдущие статьи:
Комментарии (3)
withkittens
31.07.2025 19:51В .NET вопрос часовых поясов, дат и времён, в общем-то, решён: NodaTime. От вас нужно правильно подобрать входные типы данных (в библиотеке 7 видов дат и времён), остальное вам подскажут типы.
APXEOLOG
Хранить в UTC, хранить часовой пояс пользователя (не смещение). Все вычисления делать только с помощью специализированных библиотек. В часовых поясах столько тонкостей, что руками туда лучше не лезть
alados Автор
Сейчас я примерно так и делаю, только храню не UTC, а время группы, учитывая смещения от времени пользователя.
Но даты это действительно сложно, а так как это пет проект, то ещё и тестировать тяжело