Конвертер Unix-времени

Переведите Unix-метку времени в дату в любом часовом поясе и обратно: секунды или миллисекунды определяются сами, плюс ISO 8601 и сколько времени прошло.

Текущее Unix-время
Определяется…
Ввод

Что такое Unix-метка времени

Unix-метка времени — её также называют epoch-временем или POSIX-временем — это одно число, считающее, сколько секунд прошло с 00:00:00 UTC 1 января 1970 года, момента, известного как Unix-эпоха. Поскольку это одно целое число, без часового пояса, без календаря и без форматирования, именно к этому формату обращаются компьютеры всякий раз, когда момент времени нужно сохранить, отсортировать, сравнить или передать по сети. Это то, что стоит за столбцом «created_at» в вашей базе данных, за полями «iat» и «exp» в JWT, за mtime файла и за метками времени почти в любом журнале, который вам доведётся читать.

Плата за это — голое число ничего не говорит человеку. 1716197600 — вполне корректный момент, но с первого взгляда не понять, прошлый ли это вторник или три года назад. Именно этот перевод, в обе стороны, и делает данный инструмент.

Секунды или миллисекунды — двусмысленность, которая кусается

Исходное соглашение Unix считает целые секунды, и именно это возвращают date +%s в оболочке, time() в PHP и time.time() в Python после отбрасывания дробной части. JavaScript, Java и многие другие считают миллисекунды: Date.now() возвращает число в тысячу раз больше. И то и другое называют «меткой времени», а их смешение — одна из самых частых ошибок с датами вообще.

Сбой здесь тихий, а не громкий. Прочитайте значение в миллисекундах как секунды — и дата улетит на десятки тысяч лет вперёд; прочитайте значение в секундах как миллисекунды — и всё схлопнется в январь 1970 года. Ни в том, ни в другом случае ошибки не будет: вы просто получите неверную дату, выглядящую как настоящая.

Этот инструмент угадывает по порядку величины числа, а затем сообщает вам, что именно он угадал, прямо рядом с результатом. Сегодняшние epoch-секунды состоят из десяти цифр, а миллисекунды — из тринадцати, поэтому догадка почти всегда верна. Но «почти» недостаточно для значения, которое вы вот-вот вставите в отчёт об ошибке, — поэтому выбранная трактовка всегда на виду и всегда в одном щелчке от переключения.

Часовые пояса, UTC и почему «местное» — скользкое понятие

У Unix-метки времени нет часового пояса. Она обозначает момент: 1716197600 — это 2024-05-20T09:33:20Z, и этот же самый момент одновременно есть 10:33 в Лондоне, 12:33 в Иерусалиме и 18:33 в Токио, потому что в тот день в Лондоне и Иерусалиме действует летнее время, а в Японии его нет вовсе. Часовой пояс не входит в значение; это линза, через которую вы на него смотрите.

Поэтому инструмент показывает сразу несколько линз. UTC — нейтральная точка отсчёта, с которой согласны все серверы и журналы. Ваше местное время — то, о котором сообщает ваше собственное устройство; оно показано с именем пояса (например, Europe/Berlin), чтобы вы всегда знали, какая линза его дала: определение происходит в вашем браузере, поэтому посетитель из Берлина видит берлинское время, а из Токио — токийское. Третья строка — любой пояс на ваш выбор из полной базы IANA, и именно она нужна, когда вы читаете журнал сервера, стоящего где-то ещё.

  • UTC — точка отсчёта, с которой согласны все системы, и то, что правильно хранить и записывать в журналы.
  • Местное — тот же момент, каким его видит ваше устройство, с пометкой об определённом поясе.
  • Пояс на ваш выбор — для чтения журналов и трассировок с машин в других местах.
  • ISO 8601 — текстовый формат обмена, например 2024-05-20T09:33:20.000Z.
  • Относительно — «3 часа назад», чтобы быстро понять, насколько это свежее.

Смещения показаны рядом с каждым временем (+03:00, -04:00), потому что они не постоянны: большинство поясов сдвигаются на час из-за перехода на летнее время, так что один и тот же пояс может давать разные смещения в разное время года. Дата вблизи перехода — как раз то место, где ручные подсчёты дают сбой.

Работа с epoch-временем на практике

В каждом языке и в каждой оболочке свой способ получать и читать epoch-значения. Эти стоит запомнить:

date +%s                         # оболочка: текущее время в секундах
date -d @1716197600              # оболочка (GNU): из секунд в дату
Date.now()                       # JavaScript: текущее время в МИЛЛИсекундах
new Date(1716197600 * 1000)      # JavaScript: из секунд в Date
time.time()                      # Python: секунды, как дробное число
datetime.fromtimestamp(1716197600, tz=timezone.utc)
SELECT EXTRACT(EPOCH FROM now()) -- PostgreSQL: секунды

Правило, избавляющее от большей части боли с датами: храните и передавайте моменты в UTC — либо целым epoch-числом, либо строкой ISO 8601 — и переводите в местный пояс только в самый последний момент, когда действительно показываете их человеку. Слишком раннее форматирование — это то, как ошибка часового пояса запекается в ваши данные вместо того, чтобы остаться в слое отображения.

Ещё одно, о чём стоит знать: знаковый 32-битный счётчик секунд исчерпывается 19 января 2038 года — «проблема 2038 года». Современные системы используют 64-битные значения и в безопасности, но старые встраиваемые устройства и унаследованные столбцы баз данных — как раз те места, где с ней ещё можно столкнуться.

Что такое эпоха и почему не всякая метка времени отсчитывается от 1970 года

Эпоха в этом смысле — просто выбранный ноль, момент, от которого счётчик по определению начинает счёт. Unix-эпоха — это 1 января 1970 года, 00:00:00 UTC, и она выбрана потому, что это удобная круглая дата, а не потому, что откуда-то выводится: ничто в самом формате не требует именно этого дня. Ранний Unix считал шестидесятые доли секунды от куда более близкого нуля, и руководство третьего издания прямо сказало, почему так не могло продолжаться: тридцать два бита шестидесятых долей гарантируют кризис каждые 2,26 года, то есть примерно каждые 828 дней. Целых секунд в тех же тридцати двух битах хватает на сто тридцать шесть лет, или на шестьдесят восемь, если счётчик знаковый, — это и есть дата 2038 года выше.

Эта предыстория и есть причина проверять длинное число, прежде чем ему доверять. Другие системы считают от других нулей и с другим разрешением, и прочитать одно из них как Unix-секунды — значит промахнуться не на несколько часов, а на века. Вот те, что встречаются чаще всего:

  • Windows FILETIME — стонаносекундные тики с 1 января 1601 года UTC. Разделите на десять миллионов и вычтите 11644473600, чтобы получить Unix-секунды; момент 1716197600, который используется во всём этом руководстве, там равен 133606712000000000.
  • .NET DateTime.Ticks — тот же стонаносекундный тик, но отсчитываемый от начала 1 года. Сама Unix-эпоха приходится на 621355968000000000 тиков, и это то число, которое вычитают перед делением.
  • Опорная дата Apple — секунды с 1 января 2001 года UTC, её используют Cocoa и Core Data. Прибавьте 978307200, чтобы получить Unix-секунды: 1716197600 там равно 737890400.
  • Серийные номера Excel — дни, а не секунды, и отсчёт идёт с 30 декабря 1899 года, потому что Excel считает 1900 год високосным, каким он не был.
  • Время GPS — секунды с 6 января 1980 года, отсчитываемые без единого пропуска секунды координации, так что время GPS и UTC больше не совпадают.

Последний пункт указывает на то, что верно и для самого значения Unix: это не показание секундомера. POSIX определяет его как значение, приближающее число секунд, прошедших с эпохи, и требует, чтобы каждый без исключения день учитывался ровно 86400 секундами, — то есть вставленные в UTC секунды координации не считаются вовсе. Разность двух Unix-меток времени — это число календарных секунд между ними, а не число действительно прошедших, и значение лучше всего понимать как кодировку календарного показания в UTC. По этой же причине ни одна метка времени не обозначает секунду координации: в кодировке для неё просто нет места.

Как из даты получить epoch-значение: оболочка, JavaScript и Python

Блок выше превращает epoch-значение в нечто читаемое. Обратное направление — дата, которая у вас уже есть, текстом или набором чисел, превращаемая в epoch-значение, — как раз то место, где живут ошибки часовых поясов, потому что каждый из этих языков молча предположит пояс, если текст его не называет. Вот одна и та же задача тремя способами, на моменте 2024-05-20T09:33:20Z из этого руководства. Строки оболочки — это date из GNU; date в BSD и macOS принимает другие ключи.

date -u -d '2024-05-20 09:33:20' +%s     # 1716197600 — ключ -u читает текст как UTC
date -d '2024-05-20 09:33:20 UTC' +%s    # то же самое, но пояс назван в самом тексте
date -d '2024-05-20 09:33:20' +%s        # ни то ни другое: пояс вашей машины
Date.parse('2024-05-20T09:33:20Z') / 1000    // 1716197600 — именно Z делает это UTC
new Date('2024-05-20T09:33:20Z').getTime()   // тот же момент в миллисекундах
Date.parse('2024-05-20 09:33:20')            // без Z: пояс вашей машины, другой момент
from datetime import datetime, timezone
int(datetime(2024, 5, 20, 9, 33, 20, tzinfo=timezone.utc).timestamp())   # 1716197600 — с часовым поясом
int(datetime.fromisoformat('2024-05-20T09:33:20+00:00').timestamp())     # то же самое, разобранное из строки
int(datetime(2024, 5, 20, 9, 33, 20).timestamp())                        # наивный: пояс вашей машины

Схема во всех трёх одна: назовите пояс — или унаследуете тот, на который настроена машина. Число, верное на вашем ноутбуке и ошибающееся на несколько часов на ноутбуке коллеги, — это почти всегда именно оно, и потому инструмент выше показывает UTC и ваше местное время рядом, а не выбирает одно за вас. Если число у вас уже есть и вы хотите проверить его глазами, вставьте его в поле вверху этой страницы.

Частые вопросы

Как инструмент понимает, секунды у меня или миллисекунды?
По порядку величины: значения примерно до 1e11 читаются как секунды, большие — как миллисекунды. Сегодня это чётко отделяет десятизначные секунды от тринадцатизначных миллисекунд. Трактовка показана рядом с результатом, и её можно переключить одним щелчком, так что догадка никогда от вас не скрыта.
Какой часовой пояс считается «местным»?
Тот, о котором сообщает ваше собственное устройство; он определяется в браузере и показан по имени, чтобы не оставалось сомнений. Это ваш пояс, а не пояс сайта: посетитель из Берлина видит берлинское время, а из Токио — токийское.
Можно ли перевести дату обратно в метку времени?
Да. Одно и то же поле принимает оба направления: введите число — получите дату; введите дату вида 2024-05-20 или 2024-05-20T09:33:20Z — получите epoch-значение. Никакой режим переключать не нужно.
Работает ли он с датами до 1970 года?
Да. Метки времени до эпохи просто отрицательные — -86400 это 31 декабря 1969 года — и отрицательные значения принимаются и преобразуются как обычно.
Почему моя метка времени показывает не ту дату, которую я ожидал?
Почти всегда по одной из двух причин: трактовка секунды/миллисекунды не та, которую вы предполагали (посмотрите на подпись и переключите её), либо вы сравниваете значение в UTC с ожиданием в местном времени. Инструмент показывает обе строки рядом, чтобы вы увидели, какой из случаев ваш.
Что такое проблема 2038 года?
Системы, хранящие epoch-секунды в знаковом 32-битном целом, переполняются 19 января 2038 года и переходят к отрицательному числу, давая даты в 1901 году. Всё, что использует 64-битные значения — то есть почти всё современное — не затронуто, но унаследованные встраиваемые системы и старые столбцы баз данных всё ещё могут быть в зоне риска.
Почему моя метка времени состоит из восемнадцати цифр?
Потому что это, скорее всего, не Unix-метка времени. Unix-секунды сегодня занимают десять цифр, а миллисекунды — тринадцать; восемнадцать — это вид стонаносекундного тика, который Windows FILETIME отсчитывает от 1601 года, а .NET — от начала 1 года. Шестнадцать цифр — другой частый случай: тот же момент в микросекундах. Раздел об эпохах выше даёт число, которое нужно вычесть в каждом случае.
Как в Python перевести дату в Unix-метку времени?
Создайте datetime с часовым поясом — то есть несущий tzinfo — вызовите у него метод timestamp и отбросьте дробную часть до целого. Строка есть в блоке кода выше, и тот же раздел показывает ту же задачу в оболочке и в JavaScript. Вся трудность именно в tzinfo: опустите его — и Python прочитает ваши числа как местное время машины и вернёт другое значение, ничего вам не сказав.
Отправляется ли куда-нибудь введённая мной метка времени?
Нет. Разбор, преобразование и форматирование выполняются целиком в вашем браузере, с опорой на собственную поддержку дат и часовых поясов в платформе. Ничто из набранного вами не покидает ваше устройство.

Похожие инструменты