Unix timestamp: полное руководство для разработчиков и обычных пользователей
Unix timestamp — это, пожалуй, самый распространённый способ представления времени в программировании. Если вы когда-либо работали с API, базами данных или логами серверов, вы почти наверняка сталкивались с длинными числами вроде 1715678901. За этими цифрами скрывается конкретный момент времени, понятный любой системе независимо от языка, платформы или географического положения. В этой статье мы разберём, как устроен Unix timestamp, откуда он взялся, почему стал стандартом де-факто и как с ним работать без ошибок.
Что такое Unix timestamp и откуда он взялся
Всё началось в конце 1960-х годов в лабораториях Bell Labs, где Кен Томпсон и Деннис Ритчи создавали операционную систему Unix. Им требовался простой и однозначный способ фиксации времени — без возни с часовыми поясами, названиями месяцев и високосными годами. Решение оказалось гениально простым: считать секунды от фиксированной точки отсчёта. Этой точкой стало 1 января 1970 года, 00:00:00 UTC — «эпоха Unix».
Выбор даты не случаен. К 1970 году Unix уже активно разрабатывался, а начало десятилетия давало удобную круглую отметку. Кроме того, 32-битное знаковое целое — основной тип данных того времени — позволяло хранить около 68 лет в обе стороны от эпохи: с 1901 по 2038 год. Тогда казалось, что 2038 год — это бесконечно далеко.
Сегодня Unix timestamp вышел далеко за пределы Unix-систем. Он используется в Linux, macOS, iOS, Android, в большинстве баз данных (MySQL, PostgreSQL, SQLite), в протоколах HTTP (заголовки Date, Expires), в JSON Web Tokens, в блокчейнах и умных контрактах. Универсальность формата сделала его лингва-франка цифрового времени.
Как устроен Unix timestamp изнутри
Unix timestamp — это целое число секунд, прошедших с полуночи 1 января 1970 года по UTC. Никаких дробных частей, никаких учётов високосных секунд — только чистый счёт. Каждые ровно 86 400 секунд добавляют один день. Год в этой системе длится 31 536 000 секунд (365 дней), високосный — 31 622 400 секунд.
Важный нюанс: Unix timestamp игнорирует високосные секунды. Когда Международная служба вращения Земли добавляет дополнительную секунду к UTC, Unix-время просто «замирает» на секунду или слегка сдвигается. Это сделано для упрощения вычислений — каждый день ровно 86 400 секунд, и никаких исключений. Практическая разница составляет всего 27 секунд за всю историю наблюдений, так что для 99,9% приложений это несущественно.
Отрицательные значения timestamp — это даты до 1970 года. Например, -1 соответствует 31 декабря 1969 года, 23:59:59 UTC. Система симметрична: отсчёт назад от эпохи работает точно так же, как и вперёд. Это позволяет представлять любую дату от условного начала летоисчисления до далёкого будущего — ограниченного лишь разрядностью переменной.
32 бита, 64 бита и проблема 2038 года
Классический Unix timestamp хранится в 32-битном знаковом целом (int32_t). Максимальное положительное значение такого типа — 2 147 483 647. Прибавьте к эпохе это количество секунд — и вы окажетесь ровно в 03:14:07 UTC 19 января 2038 года. В следующую секунду счётчик переполнится и станет равен −2 147 483 648, что заставит систему «провалиться» в 13 декабря 1901 года. Это и есть знаменитая проблема 2038 года — наследница проблемы Y2K, но с более глубокими техническими корнями.
Решение уже существует: переход на 64-битные целые (int64_t). С 64 битами диапазон расширяется до ±292 миллиардов лет — это примерно в 21 раз больше возраста Вселенной. Современные операционные системы (64-битные Linux, Windows, macOS) уже используют 64-битный time_t. Однако миллиарды встроенных устройств — маршрутизаторов, IoT-датчиков, промышленных контроллеров — до сих пор работают на 32-битных чипах. Именно они окажутся в зоне риска в 2038 году.
Если вы разрабатываете программное обеспечение сегодня, всегда указывайте 64-битный тип для хранения timestamp. В C/C++ используйте int64_t, в Java — long (он 64-битный по спецификации), в Python целые числа не ограничены, в JavaScript Number безопасно хранит целые до 253.
Секунды или миллисекунды: как не запутаться
Одна из самых распространённых ошибок — путаница между секундным и миллисекундным представлением. Классический Unix timestamp измеряется в секундах и содержит 10 цифр. Однако JavaScript, Java, C# и некоторые API используют миллисекунды — 13 цифр. Разница в тысячу раз.
Практическое правило: если число порядка 1,7 миллиарда — это секунды (текущее время ~1,71 млрд). Если порядка 1,7 триллиона — миллисекунды. Например, timestamp 1700000000 — это 14 ноября 2023 года (секунды), а 1700000000000 — та же дата в миллисекундах. Ошибка на три порядка отправляет вас на тысячу лет в будущее или прошлое.
При работе с API всегда проверяйте документацию: Stripe использует секунды, Twitter — секунды, GitHub — секунды, но JavaScript-фреймворки часто ожидают миллисекунды. Хорошая привычка — добавлять в название переменной суффикс _sec или _ms, чтобы явно указать единицу измерения.
Практические приёмы конвертации
Конвертация timestamp в читаемую дату тривиальна в любом языке. В Python: datetime.fromtimestamp(1700000000) вернёт объект datetime. В JavaScript: new Date(1700000000 * 1000) — не забудьте умножить на 1000. В командной строке Linux: date -d @1700000000 выведет человекочитаемую дату.
Обратная операция — получить timestamp из даты — чуть сложнее из-за часовых поясов. В Python: int(datetime(2023, 11, 14, 22, 13, 20).timestamp()). В JavaScript: Math.floor(new Date('2023-11-14T22:13:20Z').getTime() / 1000). Суффикс Z в строке даты явно указывает UTC — это хорошая практика, предотвращающая сдвиги из-за локального часового пояса.
Для быстрой проверки текущего timestamp в браузере откройте консоль (F12) и введите Math.floor(Date.now() / 1000). Через секунду повторите — число увеличится ровно на 1. Именно так «тикают» цифровые часы всей планеты.
Где применяется Unix timestamp в реальном мире
Область применения timestamp колоссальна. Базы данных хранят временные метки записей — created_at, updated_at — именно в Unix-формате. Это позволяет легко сортировать записи по времени простым числовым сравнением, без дорогих операций с датами.
Веб-разработка использует timestamp для кеширования (заголовки If-Modified-Since), для ограничения частоты запросов (rate limiting), для управления сессиями. JWT-токены содержат поля iat (issued at) и exp (expiration) — оба в Unix-секундах.
Мобильные приложения синхронизируют данные через timestamp: сервер отправляет время последнего изменения, клиент сравнивает с локальной копией. Игровая индустрия сохраняет рекорды, время прохождения уровней, длительность сессий — всё в секундах с эпохи. Даже умные лампочки используют timestamp для расписания включения и выключения.
Советы и лучшие практики
Всегда храните timestamp в UTC. Локальное время — это проблема отображения, а не хранения. Конвертируйте в локальный пояс только в момент показа пользователю. Так вы избежите путаницы при переходе на летнее/зимнее время и при смене часовых поясов.
Используйте 64-битные типы для новых проектов. Даже если вы уверены, что ваша программа не доживёт до 2038 года, привычка использовать int64 защитит от неожиданных багов при работе с датами планирования (например, расчёт ипотеки на 30 лет вперёд).
Добавляйте в API явное указание единицы измерения. Названия полей вроде created_at_sec или expires_at_ms снимают любые вопросы у разработчиков, интегрирующихся с вашим сервисом. Документация, подкреплённая говорящими именами полей, экономит часы поддержки.
И наконец — не бойтесь отрицательных timestamp. Даты до 1970 года вполне легитимны. Генеалогические базы данных, исторические архивы, астрономические расчёты — все они используют отрицательные значения, и это абсолютно нормально.