TGViewer
EvApps EvApps @evapps_team · 198 subscribers
Post #1527 72
🕐 Почему вечно «едут» даты
Со временем всё просто — до первого бага
У юзера отчёт за «вчера» показывает не то, напоминалка падает на час раньше, а после перевода часов вообще всё разъехалось
И самое обидное — локально не повторить, у тебя-то сходится
Разберём, обо что тут все спотыкаются и как перестать воевать

🌍 Правило номер один: всё в UTC
Главная засада — хранить в базе местное время
Пока сервис в одном городе — вроде норм
А как появятся юзеры из разных зон (или сервак переедет) — и ты уже сам не понимаешь, что за 14:00 лежит в базе
По Москве? По серверу? По юзеру? Фиг знает
Как надо: внутри системы всё живёт в UTC — и база, и логика
А местное время — это просто «как показать юзеру», его считаешь в самый последний момент
Прилетело время от клиента — сразу перегнал в UTC и забыл
Отдаёшь наружу — перегнал в зону юзера

🎭 Время без зоны — это мина
В коде время бывает двух видов: с зоной и без
Без зоны — это голое 2026-08-19 14:00, и непонятно, это 14:00 вообще где
Такие штуки нельзя спокойно сравнивать и складывать — рано или поздно бахнет
dt = datetime(2026, 8, 19, 14, 0, tzinfo=timezone.utc)

🌗 Перевод часов — отдельная боль
Даже если зона одна, есть летнее/зимнее время, и тут два прикола, про которые вспоминают только когда уже горит: — один и тот же час может случиться дважды (когда стрелки крутят назад); — а иногда его не бывает вообще (когда крутят вперёд — час просто исчезает)
Поэтому и нельзя держать местное время и думать, что отмотаешь назад

📅 «Вчера» — это когда вообще?
Классика аналитики: юзер хочет отчёт за «вчера», а сутки у всех кончаются в разное время
У чувака в Москве день закрылся в 21:00 UTC, у другого в Нью-Йорке — совсем в другой момент
Режешь сутки по серверному времени — у половины народа «вчера» будет кривым
Границы дня надо считать в зоне юзера, и только потом гнать в UTC для запроса

🔢 Ещё пара вещей, чтоб не наступить
В Postgres храни момент в timestamptz, а не в timestamp
Первый — момент времени, второй — цифры без привязки, и это ловушка
Не парси даты строками руками
Есть ISO 8601 (2026-08-19T14:00:00Z) — понятный формат с зоной, гоняй время между сервисами только так. — Зоны бери из базы IANA (Europe/Moscow), а не хардкодь смещение +3
Страны меняют переводы часов, база обновляется — хардкод нет

⏱️ А ещё есть Unix timestamp

Отдельная штука, которую любят и часто понимают наполовину
Unix timestamp — это число секунд, прошедших с 1 января 1970
Штука отличная: это UTC по своей природе, зоны в нём нет, сравнивать и хранить — одно удовольствие, никаких «а это по чьему времени»

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

Расскажите, про баги, которые возникали у вас из-за проблем со временем? 🤔

#backend #database #dev #programming #datetime #postgres
More from @evapps_team
  1. Sep 21, 2026🧩 Что тут не так? Код-загадка Формат новый - показываю код, ты угадываешь подвох, ниже ра…
  2. Sep 18, 2026🎭 Мифы про производительность, в которые верят даже опытные Миф 1: "Меньше строк кода - б…
  3. Sep 16, 2026🚨 Как перевод денег уронил нам прод ⏰ 19:10 Задеплоили долгожданное - переводы между коше…
  4. Sep 14, 2026🗃 Кэш поставили, а он отдаёт старьё В программировании две сложные вещи - инвалидация кэш…
  5. Sep 11, 2026🔌 "Too many connections" - и почему база падает под нагрузкой Под нагрузкой прилетает FAT…
  6. Sep 11, 2026Пока вы наслаждаетесь пятницей, мы напоминаем, что уже завтра стартует одна из наших любим…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →