Преобразование из формата времени MediaWiki в временную метку Unix в PHP

MediaWiki (бесплатное программное обеспечение, лежащее в основе Википедии) хранит временные метки базы данных в уникальном двоичном (14) формате для полей базы данных. Это описано далее в их документации временных меток.

Формат временных меток, используемый в URL-адресах MediaWiki и в некоторых Поля базы данных MediaWiki имеют формат ггггммддччммсс. Например, отметка времени для 2023-01-20 17:12:22 (UTC) — 20230120171222. часовой пояс для этих временных меток — UTC.

Я также видел аналогичный формат метки времени в других местах, таких как URL-адреса для Интернет-архива. Мне регулярно нужно сравнивать эти метки времени с метками времени, которые хранятся в стандартном формате меток времени Unix (секунды от эпохи Unix). Я считаю, что это должен быть общий формат, поэтому меня удивляет, что я не могу найти готовое решение для простого преобразования формата MediaWiki в метку времени Unix.

Что меня больше всего интересует, так это лучший способ сделать это преобразование. То есть:

  • Относительно короткий/простой для понимания код.
  • Самый эффективный алгоритм.
  • Обнаруживает ошибки в исходном формате.

По-видимому, существует функция , которую MediaWiki включает для преобразования, под названием «wfTimestamp» , однако я не смог найти эту функцию или исходный код в Интернете, и я понимаю, что она имеет большое количество ненужных функций помимо простого преобразования. Одним из возможных решений может быть удаление других частей этой функции, но я до сих пор не знаю, является ли эта функция оптимальным решением или есть лучший способ. Есть много вопросов по более общему преобразованию в временные метки, но я надеюсь на что-то конкретное для этого формата. Я думал о многих способах ее решения, таких как регулярное выражение, mktime после разделения строки, strtotime и т. д., но я не уверен, какой из них будет самым быстрым для этого конкретного формата задачи/времени, если ему придется делать много раз. Я предполагаю, что, поскольку этот формат существует по крайней мере в двух местах, оптимальное решение для преобразования этого конкретного формата может быть полезно и для других. Спасибо.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
59
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать функцию DateTime::createFromFormat с указанным форматом.

$date = DateTime::createFromFormat("YmdHis", "20230120171222", new \DateTimeZone('UTC'));
$timestamp = $date->getTimestamp();

Я не уверен, что вы можете найти более оптимизированный способ, потому что даже если вы будете разбирать это вручную, вы должны учитывать, что есть високосные годы и не каждый день имеет ровно 24 часа. PHP делает это за вас.

Спасибо! Теперь я провел метрическое тестирование вашего решения и strtotime. Это показало, что на самом деле strtotime постоянно работает быстрее. Тест 1: strtotime потребовалось 0,01284 с для 10 000 конверсий. DateTime::createFromFormat потребовалось 0,02822 с для 10 000 конверсий. Тест 2: strtotime потребовалось 0,064132 с для 10 000 конверсий. DateTime::createFromFormat потребовалось 0,113503 с для 10 000 конверсий. Тест 3: strtotime потребовалось 0,014117 с для 10 000 конверсий. DateTime::createFromFormat потребовалось 0,051584 с для 10 000 конверсий. Я попытался поменять порядок тестов, и результаты были одинаковыми.

azoundria 03.02.2023 20:55
Ответ принят как подходящий

Я думаю, это то, что вы, вероятно, ищете:

$timestamp = strtotime("20230120171222"); 
// 1674234742

Отметка времени Unix, которую возвращает эта функция, не содержит информации о часовых поясах. Чтобы выполнять вычисления с информацией о дате/времени, вы должны использовать более способный DateTimeImmutable.

Пожалуйста, смотрите здесь: https://www.php.net/manual/en/function.strtotime.php

Спасибо. Похоже, это работает, и я просто никогда не думал, что strtotime будет автоматически работать с этим форматом. Обратите внимание, что ваш комментарий о временной метке Unix верен в отношении временных меток Unix в целом. Они всегда относятся к определенному моменту времени. (Одна из причин, по которой мне нравится с ними работать. Мне приходится иметь дело только со сложностью часового пояса/летнего времени при отображении информации пользователю.) Это, безусловно, самая простая для понимания реализация, хотя я все еще не уверен, что это самая эффективная реализация.

azoundria 03.02.2023 20:44

Теперь я провел метрическое тестирование вашего решения и DateTime::createFromFormat. Это показало, что на самом деле strtotime постоянно работает быстрее. Тест 1: strtotime потребовалось 0,01284 с для 10 000 конверсий. DateTime::createFromFormat потребовалось 0,02822 с для 10 000 конверсий. Тест 2: strtotime потребовалось 0,064132 с для 10 000 конверсий. DateTime::createFromFormat потребовалось 0,113503 с для 10 000 конверсий. Тест 3: strtotime потребовалось 0,014117 с для 10 000 конверсий. DateTime::createFromFormat потребовалось 0,051584 с для 10 000 конверсий. Я попытался поменять порядок тестов, и результаты были одинаковыми.

azoundria 03.02.2023 20:54

Обратите внимание, что я обнаружил, что решение не работает, если date_default_timezone_set был вызван ранее с часовым поясом, отличным от UTC. Я не обнаружил, что strtotime принимает параметр часового пояса, поэтому я добавил date_default_timezone_set для UTC ранее и восстановил через date_default_timezone_get. В моем тестировании это не добавило ничего существенного во время выполнения функции.

azoundria 03.02.2023 22:06

Лучше сразу указать правильный часовой пояс, как в решении Андрея Макарова или моём.

jspit 04.02.2023 18:06

Чтобы интерпретировать строку «20230120171222» как время в формате UTC, часовой пояс должен быть указан с помощью strtotime или часовой пояс по умолчанию должен быть установлен в формате UTC.

$dateStr = "20230120171222"; 
$timestamp = strtotime($dateStr.' UTC');
var_dump($timestamp); //int(1674234742)

См. этот пример для сравнения.

Другие вопросы по теме