MediaWiki (бесплатное программное обеспечение, лежащее в основе Википедии) хранит временные метки базы данных в уникальном двоичном (14) формате для полей базы данных. Это описано далее в их документации временных меток.
Формат временных меток, используемый в URL-адресах MediaWiki и в некоторых Поля базы данных MediaWiki имеют формат ггггммддччммсс. Например, отметка времени для 2023-01-20 17:12:22 (UTC) — 20230120171222. часовой пояс для этих временных меток — UTC.
Я также видел аналогичный формат метки времени в других местах, таких как URL-адреса для Интернет-архива. Мне регулярно нужно сравнивать эти метки времени с метками времени, которые хранятся в стандартном формате меток времени Unix (секунды от эпохи Unix). Я считаю, что это должен быть общий формат, поэтому меня удивляет, что я не могу найти готовое решение для простого преобразования формата MediaWiki в метку времени Unix.
Что меня больше всего интересует, так это лучший способ сделать это преобразование. То есть:
По-видимому, существует функция , которую MediaWiki включает для преобразования, под названием «wfTimestamp» , однако я не смог найти эту функцию или исходный код в Интернете, и я понимаю, что она имеет большое количество ненужных функций помимо простого преобразования. Одним из возможных решений может быть удаление других частей этой функции, но я до сих пор не знаю, является ли эта функция оптимальным решением или есть лучший способ. Есть много вопросов по более общему преобразованию в временные метки, но я надеюсь на что-то конкретное для этого формата. Я думал о многих способах ее решения, таких как регулярное выражение, mktime после разделения строки, strtotime и т. д., но я не уверен, какой из них будет самым быстрым для этого конкретного формата задачи/времени, если ему придется делать много раз. Я предполагаю, что, поскольку этот формат существует по крайней мере в двух местах, оптимальное решение для преобразования этого конкретного формата может быть полезно и для других. Спасибо.






Вы можете использовать функцию DateTime::createFromFormat с указанным форматом.
$date = DateTime::createFromFormat("YmdHis", "20230120171222", new \DateTimeZone('UTC'));
$timestamp = $date->getTimestamp();
Я не уверен, что вы можете найти более оптимизированный способ, потому что даже если вы будете разбирать это вручную, вы должны учитывать, что есть високосные годы и не каждый день имеет ровно 24 часа. PHP делает это за вас.
Я думаю, это то, что вы, вероятно, ищете:
$timestamp = strtotime("20230120171222");
// 1674234742
Отметка времени Unix, которую возвращает эта функция, не содержит информации о часовых поясах. Чтобы выполнять вычисления с информацией о дате/времени, вы должны использовать более способный DateTimeImmutable.
Пожалуйста, смотрите здесь: https://www.php.net/manual/en/function.strtotime.php
Спасибо. Похоже, это работает, и я просто никогда не думал, что strtotime будет автоматически работать с этим форматом. Обратите внимание, что ваш комментарий о временной метке Unix верен в отношении временных меток Unix в целом. Они всегда относятся к определенному моменту времени. (Одна из причин, по которой мне нравится с ними работать. Мне приходится иметь дело только со сложностью часового пояса/летнего времени при отображении информации пользователю.) Это, безусловно, самая простая для понимания реализация, хотя я все еще не уверен, что это самая эффективная реализация.
Теперь я провел метрическое тестирование вашего решения и 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 конверсий. Я попытался поменять порядок тестов, и результаты были одинаковыми.
Обратите внимание, что я обнаружил, что решение не работает, если date_default_timezone_set был вызван ранее с часовым поясом, отличным от UTC. Я не обнаружил, что strtotime принимает параметр часового пояса, поэтому я добавил date_default_timezone_set для UTC ранее и восстановил через date_default_timezone_get. В моем тестировании это не добавило ничего существенного во время выполнения функции.
Лучше сразу указать правильный часовой пояс, как в решении Андрея Макарова или моём.
Чтобы интерпретировать строку «20230120171222» как время в формате UTC, часовой пояс должен быть указан с помощью strtotime или часовой пояс по умолчанию должен быть установлен в формате UTC.
$dateStr = "20230120171222";
$timestamp = strtotime($dateStr.' UTC');
var_dump($timestamp); //int(1674234742)
См. этот пример для сравнения.
Спасибо! Теперь я провел метрическое тестирование вашего решения и 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 конверсий. Я попытался поменять порядок тестов, и результаты были одинаковыми.