Unix-временны́е метки: полное руководство
Что такое Unix-временны́е метки, почему они начинаются с 1 января 1970 года, как конвертировать их в читаемые даты и как с ними работать на практике.
Откройте любой лог-файл. Посмотрите на поле exp в JWT-токене. Проверьте поле created_at в ответе API. Скорее всего, вы увидите число вроде 1711065600 или 1711065600000. Это Unix-временная метка — простое целое число, представляющее момент времени. Понимание того, как работает Unix-время, откуда оно берётся и как избегать типичных ловушек, убережёт вас от целого класса багов — незаметных, трудновоспроизводимых и порой весьма неловких в продакшне.
Вы можете мгновенно конвертировать любую Unix-временную метку в читаемую дату (и обратно) с помощью конвертера Unix-временных меток BrowseryTools — бесплатно, без регистрации, всё остаётся в браузере.
Что такое Unix-временная метка?
Unix-временная метка — это количество секунд, прошедших с момента Unix Epoch: полуночи 1 января 1970 года по всемирному координированному времени (UTC). Этот момент — 00:00:00 UTC, 1970-01-01 — был выбран в качестве точки отсчёта при разработке операционной системы Unix в начале 1970-х годов. Это была недавняя и круглая дата, которая упрощала вычисления на аппаратном обеспечении той эпохи.
Элегантность Unix-времени в том, что любой момент времени представлен одним целым числом. Сравнение двух временных меток — это вычитание. Проверка истечения срока — это сравнение. Добавление интервала — это сложение. Никаких часовых поясов, никакой календарной математики, никакого перехода на летнее время — только число.
По состоянию на 2026 год текущая Unix-временная метка составляет примерно 1 774 000 000. Каждую секунду это число увеличивается на 1.
Проблема 2038 года (Y2K38)
Если Unix-время хранится как 32-битное знаковое целое число — как это было во многих ранних реализациях — максимальное значение равно 2 147 483 647. Это число соответствует 03:14:07 UTC 19 января 2038 года. После этого момента 32-битное знаковое целое число переполняется и становится большим отрицательным числом, и системы, которые не были обновлены, будут неверно интерпретировать временные метки.
Это проблема 2038 года (Y2K38) — Unix-эквивалент ошибки Y2K. Современные системы используют 64-битные целые числа для временных меток, что расширяет представимый диапазон примерно до 292 миллиардов лет в обоих направлениях — фактически вечность для любых практических целей. Однако встроенные системы, устаревшие базы данных с 32-битными столбцами временных меток и старый C-код, использующий time_t как 32-битный тип, всё ещё находятся в зоне риска.
Получение текущей временной метки
Вот как получить текущую Unix-временную метку на самых распространённых языках:
// JavaScript — возвращает миллисекунды, делите на 1000 для секунд const nowMs = Date.now(); // например, 1711065600000 const nowSec = Math.floor(Date.now() / 1000); // например, 1711065600 // Python import time now = int(time.time()) # секунды с начала эпохи # Через модуль datetime from datetime import datetime, timezone now = int(datetime.now(timezone.utc).timestamp()) // Go import "time" now := time.Now().Unix() // секунды nowNano := time.Now().UnixNano() // наносекунды -- SQL (PostgreSQL) SELECT EXTRACT(EPOCH FROM NOW())::BIGINT; -- SQL (MySQL) SELECT UNIX_TIMESTAMP();
Преобразование временных меток в читаемые даты
// JavaScript — из секунд const ts = 1711065600; const date = new Date(ts * 1000); // умножаем на 1000 для мс console.log(date.toISOString()); // "2024-03-22T00:00:00.000Z" console.log(date.toLocaleDateString()); // дата в локальном формате // Python import datetime ts = 1711065600 dt = datetime.datetime.fromtimestamp(ts, tz=datetime.timezone.utc) print(dt.isoformat()) # 2024-03-22T00:00:00+00:00 -- PostgreSQL: временная метка из целого числа SELECT to_timestamp(1711065600); -- Результат: 2024-03-22 00:00:00+00 -- MySQL SELECT FROM_UNIXTIME(1711065600); -- Результат: 2024-03-22 00:00:00
Баг №1 с временными метками: миллисекунды против секунд
Date.now() в JavaScript возвращает миллисекунды. Unix-стандарт — и практически все остальные языки, базы данных и API — использует секунды. Это несоответствие является самым распространённым источником ошибок с временными метками.
Симптомы характерны: даты отображаются как 1970 год (временная метка случайно делится на 1000 или воспринимается как секунды, хотя на самом деле это миллисекунды), или даты попадают в 56 000+ год (секунды воспринимаются как миллисекунды). Значение около 1 700 000 000 — почти наверняка секунды. Значение около 1 700 000 000 000 — почти наверняка миллисекунды.
// Баг: секунды воспринимаются как миллисекунды — возвращает 1970 год
new Date(1711065600) // Mon Jan 20 1970 11:24:25 UTC 🚫
// Правильно: умножаем секунды на 1000
new Date(1711065600 * 1000) // Fri Mar 22 2024 00:00:00 UTC ✓
// Защитная вспомогательная функция — работает и с секундами, и с миллисекундами
function toDate(ts) {
// Если меньше 10^12 — это секунды; умножаем
return new Date(ts < 1e12 ? ts * 1000 : ts);
}Проблемы с часовыми поясами
Unix-временные метки всегда в UTC — они представляют единственный абсолютный момент времени без привязки к часовому поясу. Вопрос часового пояса возникает только на уровне отображения, когда вы конвертируете временную метку в читаемый формат.
Самая распространённая ошибка — использование методов локального часового пояса без осознания этого. new Date(ts).toLocaleDateString() в JavaScript возвращает дату в часовом поясе браузера. Если сервер генерирует метку в 23:00 UTC, а пользователи в UTC+0 и UTC+1 отображают её, они увидят разные календарные даты. Правильно это или нет — зависит от требований продукта, но это должен быть осознанный выбор, а не случайность.
// Всегда явно указывайте часовой пояс — используйте toISOString() для UTC
const date = new Date(1711065600 * 1000);
date.toISOString() // "2024-03-22T00:00:00.000Z" ← всегда UTC
// Или используйте Intl.DateTimeFormat для отображения с локалью/часовым поясом
new Intl.DateTimeFormat("en-US", {
timeZone: "America/New_York",
dateStyle: "full",
}).format(date); // "Friday, March 22, 2024"Временные метки в базах данных
Базы данных предлагают два основных варианта хранения дат: тип столбца TIMESTAMP (который хранит абсолютный момент времени) и тип DATE или DATETIME (который хранит календарное представление без часового пояса).
Для полей вроде created_at, updated_at и временных меток событий всегда используйте столбец TIMESTAMP WITH TIME ZONE (или его эквивалент в вашей СУБД), а не просто целое число. Это позволяет базе данных корректно обрабатывать преобразование часовых поясов и сравнение, а запросы вроде «события за последние 24 часа» будут точными независимо от настроек часового пояса сервера.
Если вам всё же нужно хранить Unix-временную метку как сырое целое число (для совместимости с внешними системами или максимальной переносимости), явно задокументируйте, секунды это или миллисекунды, и соблюдайте единообразие во всей схеме.
Временные метки в JWT и API
JSON Web Tokens (JWT) используют Unix-временные метки (в секундах) для своих временных claims:
iat— issued at («выдан в»): время создания токенаexp— expiry («срок действия»): время, после которого токен не должен приниматьсяnbf— not before («не раньше»): токен не должен использоваться до этого времени
Проверка истечения JWT — простое сравнение: exp > Math.floor(Date.now() / 1000). Если текущее время в секундах больше exp, токен истёк. Всегда валидируйте exp на сервере — никогда не полагайтесь только на клиентскую проверку срока действия.
Быстрый справочник: конвертация временных меток
Для быстрой и точной конвертации между Unix-временными метками и читаемыми датами используйте конвертер Unix-временных меток BrowseryTools. Вставьте временную метку, чтобы увидеть соответствующую UTC-дату и локальную дату, или введите дату, чтобы получить её временную метку. Всё работает в браузере — никакого сервера, никакой слежки.
Итоги
Unix-временные метки — универсальный и однозначный способ представления моментов времени. Ключевые правила: они всегда в UTC, всегда в секундах (за исключением JavaScript, где Date.now() использует миллисекунды), и всегда положительное целое число для любой даты после 1970 года. Явно обрабатывайте различие миллисекунды/секунды, используйте UTC для хранения и передачи, и конвертируйте в локальное время только на уровне отображения.
Try the Tools — 100% Free, No Sign-Up
Everything runs in your browser. No uploads. No accounts. No ads.
Explore All Tools →