Unix timestamp, или Unix-время, это число секунд, прошедших с 00:00:00 UTC 1 января 1970 года. Например, 1700000000 означает 14 ноября 2023 года, 22:13:20 по UTC, а в Москве в этот момент было уже 01:13:20 15 ноября. Такую метку времени одинаково понимают Linux, базы данных, браузер и сервер на другом конце света, поэтому её и хранят вместо даты строкой.
Текущий timestamp получают одной командой: Date.now() в JavaScript, time.time() в Python, date +%s в терминале. Ниже разберём, как перевести метку в обычную дату и обратно, как отличить секунды от миллисекунд и что случится в 2038 году.
Что такое Unix-время и timestamp

Слово timestamp переводится как «метка времени» или «временная метка». В широком смысле это любая запись о том, когда произошло событие: строка 2026-10-15 12:00:00 в журнале сервера тоже метка времени. Такие строки видны в каждом лог-файле.
Но чаще всего, говоря «таймстамп», программисты имеют в виду именно Unix timestamp. Его ещё называют Unix time, POSIX time и epoch time. Точку отсчёта, полночь 1 января 1970 года по UTC, называют эпохой Unix.
У этого счётчика есть особенность, о которой мало кто знает. Стандарт POSIX требует, чтобы каждые сутки в нём занимали ровно 86 400 секунд. Поэтому високосные секунды Unix-время не считает: в руководстве GNU coreutils сказано, что на большинстве систем високосную секунду 2016-12-31 23:59:60 UTC записать числом невозможно. Для веб-разработки это неважно, для точных измерений важно.
Как выглядит timestamp в цифрах
Несколько опорных значений:
| Timestamp | Дата и время по UTC | Что это за момент |
|---|---|---|
| 0 | 01.01.1970 00:00:00 | начало эпохи Unix |
| 1 000 000 000 | 09.09.2001 01:46:40 | первая метка из 10 цифр |
| 1 700 000 000 | 14.11.2023 22:13:20 | пример из этой статьи |
| 1 792 065 600 | 15.10.2026 12:00:00 | около полудня в день написания статьи |
| 2 147 483 647 | 19.01.2038 03:14:07 | предел 32-битного счётчика |
Отрицательные числа тоже работают и означают даты до 1970 года: -1 соответствует 31 декабря 1969 года, 23:59:59 UTC.
Секунды или миллисекунды: как понять по длине числа
Классический Unix timestamp считает секунды. Но JavaScript по умолчанию отдаёт миллисекунды, а часть логов хранит микросекунды и наносекунды. Если перепутать единицы, дата уедет в январь 1970 года или в далёкое будущее.
Отличить проще всего по количеству цифр. Для дат с сентября 2001 года по ноябрь 2286 года правило такое:
| Цифр в числе | Единица | Пример для 14.11.2023 22:13:20 UTC | Где встречается |
|---|---|---|---|
| 10 | секунды | 1700000000 | Unix, PHP, Python time(), MySQL |
| 13 | миллисекунды | 1700000000000 | JavaScript Date.now() |
| 16 | микросекунды | 1700000000000000 | часть логов и трассировок |
| 19 | наносекунды | 1700000000000000000 | Python time.time_ns() |
Перевод между ними сводится к умножению или делению на 1000. Секунды в миллисекунды: умножить на 1000. Обратно: разделить на 1000 и отбросить дробную часть.
Канал основателя Checkroi Вани Буявца3 700 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединитьсяКак получить текущий timestamp
В каждом языке это одна строка:
| Где | Секунды | Миллисекунды |
|---|---|---|
| JavaScript | Math.floor(Date.now() / 1000) |
Date.now() |
| Python | int(time.time()) |
time.time_ns() // 1_000_000 |
| PHP | time() |
(int) (microtime(true) * 1000) |
| MySQL | SELECT UNIX_TIMESTAMP(); |
нет отдельной функции |
| Терминал Linux | date +%s |
date +%s%3N |
| Терминал macOS | date +%s |
только через python3 или node |
Обратите внимание на JavaScript. По документации MDN, Date.now() возвращает миллисекунды, прошедшие с эпохи. Если передать это число на сервер на PHP или в API, которое ждёт секунды, его сначала делят на 1000.
Про PHP в руководстве php.net сказано, что time() возвращает текущее время в секундах с начала эпохи Unix по UTC. Сайт php.net из России открывается не всегда, со второй попытки обычно грузится.
Как перевести timestamp в дату и обратно
Ниже рабочий код для пяти сред, результат каждой строки указан в комментарии.
JavaScript
Конструктор Date принимает миллисекунды, поэтому секунды умножаем на 1000:
const d = new Date(1700000000 * 1000);
d.toISOString();
// "2023-11-14T22:13:20.000Z"
d.toLocaleString("ru-RU", { timeZone: "Europe/Moscow" });
// "15.11.2023, 01:13:20"
// дата → timestamp в секундах
Math.floor(new Date("2026-10-15T12:00:00Z").getTime() / 1000);
// 1792065600
Буква Z в конце строки означает UTC. Без неё браузер может понять дату по-своему, об этом в разделе про ошибки.
Python
Для дат в Python есть модуль datetime, часовые пояса берутся из zoneinfo. Устанавливать ничего не нужно:
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
print(datetime.fromtimestamp(1700000000, tz=timezone.utc))
# 2023-11-14 22:13:20+00:00
print(datetime.fromtimestamp(1700000000, tz=ZoneInfo("Europe/Moscow")))
# 2023-11-15 01:13:20+03:00
# дата → timestamp
print(int(datetime(2026, 10, 15, 12, 0, tzinfo=timezone.utc).timestamp()))
# 1792065600
Старая функция datetime.utcfromtimestamp() ещё работает, но с версии 3.12 помечена устаревшей и печатает предупреждение DeprecationWarning. Вместо неё документация советует fromtimestamp() с часовым поясом UTC, как в примере выше.
PHP
Функция date() форматирует метку в часовом поясе, который задан в настройках. На серверах там часто стоит UTC, поэтому пояс лучше указывать явно:
<?php
date_default_timezone_set("Europe/Moscow");
echo date("d.m.Y H:i:s", 1700000000); // 15.11.2023 01:13:20
echo strtotime("2026-10-15 12:00:00 UTC"); // 1792065600
$dt = new DateTime("@1700000000");
$dt->setTimezone(new DateTimeZone("Europe/Moscow"));
echo $dt->format("Y-m-d H:i:s"); // 2023-11-15 01:13:20
Запись @1700000000 в конструкторе DateTime означает «это Unix timestamp». Подробнее о самом языке мы писали в обзоре применения PHP.
MySQL
В SQL у MySQL две функции: FROM_UNIXTIME() переводит число в дату, UNIX_TIMESTAMP() делает обратное. Результат зависит от часового пояса сессии:
SET time_zone = '+00:00';
SELECT FROM_UNIXTIME(1700000000);
-- 2023-11-14 22:13:20
SELECT UNIX_TIMESTAMP('2026-10-15 12:00:00');
-- 1792065600
Если сервер настроен на московское время, то без SET time_zone первый запрос вернёт 2023-11-15 01:13:20. Это не ошибка: метка одна, показ разный. Как устроены сами запросы, разобрано в статье про команду SELECT.
Терминал Linux и macOS
Утилита date есть в обеих системах, но ключи разные. В Linux:
date -u -d @1700000000
# Tue Nov 14 10:13:20 PM UTC 2023
TZ=Europe/Moscow date -d @1700000000 "+%d.%m.%Y %H:%M:%S"
# 15.11.2023 01:13:20
date -u -d "2026-10-15 12:00:00" +%s
# 1792065600
В macOS вместо -d работают -r и -j -f:
date -u -r 1700000000 "+%Y-%m-%d %H:%M:%S"
# 2023-11-14 22:13:20
date -j -u -f "%Y-%m-%d %H:%M:%S" "2026-10-15 12:00:00" +%s
# 1792065600
Если с консолью вы работаете каждый день, пригодится и разбор профессии администратора Linux.
Часовые пояса: почему timestamp один на весь мир

Unix timestamp всегда отсчитывается от UTC. В момент 1700000000 в Лондоне было 22:13 14 ноября, в Москве 01:13 уже 15 ноября, но число у обоих одно и то же. Часовой пояс меняет только то, как метку показать человеку.
Отсюда главное правило работы с датами в коде:
- Храните в базе и передаёте между сервисами timestamp или дату в UTC.
- Переводите в местное время только при показе пользователю.
- Всегда указывайте пояс явно, когда создаёте дату из строки или из чисел.
Проблема начинается, когда пояс не указан. Тогда язык подставляет пояс компьютера, на котором запущен код. Вот одна и та же строка Python на двух компьютерах с разными часовыми поясами:
from datetime import datetime
print(datetime(2026, 10, 15, 12, 0).timestamp())
# при TZ=Europe/Moscow: 1792054800.0
# при TZ=Asia/Makassar (UTC+8): 1792036800.0
Разница пять часов, ровно на столько отличаются пояса двух машин. Код на ноутбуке разработчика и на сервере даст разные метки, и баг проявится только после выкладки.
Такая же история с метками в JSON: формат не знает про даты, поэтому договоритесь, что передаёте, число секунд или строку ISO 8601 с Z на конце.
Проблема 2038 года
Долгое время timestamp хранили в знаковом 32-битном целом. Самое большое такое число 2 147 483 647, это 19 января 2038 года, 03:14:07 UTC. Секундой позже счётчик переполнится и станет отрицательным:
import ctypes
from datetime import datetime, timezone
print(ctypes.c_int32(2**31).value)
# -2147483648
print(datetime.fromtimestamp(-2**31, tz=timezone.utc))
# 1901-12-13 20:45:52+00:00
То есть программа с 32-битным счётчиком после 03:14:07 решит, что на дворе декабрь 1901 года. Современные 64-битные системы считают время 64-битным числом, его хватит на сотни миллиардов лет вперёд. Но старый код, прошивки и форматы данных никуда не делись.
Ближе всего проблема к веб-разработчику в MySQL. По документации, тип столбца TIMESTAMP хранит даты только до 2038-01-19 03:14:07 UTC. Запись на секунду позже заканчивается ошибкой:
INSERT INTO t VALUES ('2038-01-19 03:14:08');
-- Incorrect datetime value: '2038-01-19 03:14:08' for column 'a'
При этом функции FROM_UNIXTIME() и UNIX_TIMESTAMP() на 64-битных сборках с версии 8.0.28 работают до 3001 года. Ограничение остаётся именно у типа столбца. Решение: для дат, которые могут уйти за 2038 год (сроки кредитов, подписок, документов), берите тип DATETIME или храните timestamp в BIGINT.
Частые ошибки при работе с timestamp

Почти все проблемы с метками времени сводятся к двум вещам: перепутали единицы или забыли про часовой пояс.
| Что видите | Причина | Что сделать |
|---|---|---|
| Дата 1970-01-20 вместо 2023 года | секунды передали туда, где ждут миллисекунды: new Date(1700000000) |
умножить на 1000 |
| Дата где-то в 55 000 году | миллисекунды передали туда, где ждут секунды | разделить на 1000 |
| Время сдвинуто на 3 часа или на другое целое число часов | дату создали без пояса, язык подставил пояс компьютера | указать UTC или нужный пояс явно |
new Date("2026-10-15") и new Date("2026-10-15T00:00") дают разные метки |
по MDN, строку только с датой JavaScript считает UTC, а дату со временем считает местной | писать полную строку с Z или смещением +03:00 |
new Date(2026, 9, 15) даёт 15 октября, а не сентября |
месяцы в конструкторе Date считаются с нуля |
вычитать 1 из номера месяца |
В macOS date +%s%3N печатает 17920557953N |
BSD-версия date не знает %N |
взять python3 -c "import time; print(time.time_ns() // 10**6)" |
| Ошибка записи даты после 2038 года в MySQL | тип столбца TIMESTAMP |
сменить тип на DATETIME или BIGINT |
Совет из практики: чтобы быстро проверить незнакомое число, откройте консоль браузера (F12 → Console) и наберите new Date(1700000000 * 1000).toISOString(). Если год вышел странный, уберите * 1000. Это быстрее онлайн-конвертера, и данные никуда не уходят.
Метки времени лежат в основе почти любой серверной задачи: от сроков жизни токенов до сортировки заказов. С ними вы будете сталкиваться постоянно, если выберете профессию бэкенд-разработчика.
Где освоить JavaScript системно
Даты и часовые пояса обычно встают перед новичком вместе с первыми запросами к серверу, формами бронирования и таймерами. Их разбирают в курсах по JavaScript на практических заданиях, вместе с работой с API и хранением данных.
Ниже курсы по JavaScript с рейтингом и отзывами учеников, полный список на странице курсов JavaScript.
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| JavaScript Перейти на сайт курса | 63 829 ₽ | 4086 ₽/мес. | 3 месяца | Обзор курса | |
| Fullstack разработчик JavaScript Перейти на сайт курса | 75 000 ₽ | 20 000 ₽/мес. | 6 месяцев | Обзор курса | |
| Факультет fullstack JavaScript Перейти на сайт курса | 134 700 ₽ | 3742 ₽/мес. | 15 месяцев | Обзор курса | |
| Fullstack-разработчик на Node.js Перейти на сайт курса | 109 000 ₽ | 6137 ₽/мес. | 12 месяцев | Обзор курса | |
| Fullstack-разработчик на JavaScript Перейти на сайт курса | 158 760 ₽ | 6615 ₽/мес. | 11 месяцев | Обзор курса |
Больше программ — в полном каталоге курсов по JavaScript




