⏱️
Инструменты разработчика
March 20, 20269 min readBy BrowseryTools Team

Unix-временны́е метки: полное руководство

Что такое Unix-временны́е метки, почему они начинаются с 1 января 1970 года, как конвертировать их в читаемые даты и как с ними работать на практике.

unix timestampвремядатаэпохаразработка

Откройте любой лог-файл. Посмотрите на поле 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 →