Если вы когда-нибудь публиковали пост, только чтобы увидеть на сайте пометку «57 лет назад», в то время как ваша панель управления спокойно утверждает, что он был опубликован десять минут назад, вы знаете, насколько неприятен этот баг. Он не ломает верстку. Он не вызывает фатальную ошибку. Он просто состаривает ваш контент на полвека, и изучение файлов темы не заставит это число измениться.
Эта проблема часто ускользает от стандартных проверок. Вы просматриваете single.php, archive.php и functions.php с помощью grep в поисках некорректного вызова get_the_date(). Всё выглядит стандартно. Вы обновляете страницу сайта. Призрак 1968 года всё еще преследует вашу дату публикации. В этот момент проблема почти не имеет отношения к вашим шаблонам — она целиком связана с тем, как время проходит через стек WordPress.
Почему появляется именно это число
Цифра «57 лет назад» не случайна. Темы WordPress часто отображают относительное время с помощью функции human_time_diff(), которая сравнивает временную метку поста с текущим моментом и выводит дружелюбную фразу вроде «2 часа назад». Чтобы этот расчет работал, PHP необходим корректный Unix-таймштамп — количество секунд, прошедших с 1 января 1970 года, эпохи Unix.
Когда что-то удаляет или повреждает временную метку до того, как она попадет в расчет, функция часто сравнивает ноль (или аналогичную невалидную начальную точку) с текущим временем. Результатом становится временной отрезок, уходящий примерно на пять с половиной десятилетий назад, который увеличивается на один календарный год за раз. Это симптом отсутствующего или неверно прочитанного значения времени, а не база данных, полная ретро-постов.
Обман панели управления
Одним из самых разочаровывающих аспектов этого бага является «раздвоение личности» вашей админ-панели. Внутри wp-admin список записей показывает правильную дату публикации, потому что WordPress часто берет её напрямую из таблицы MySQL wp_posts и форматирует на стороне сервера, не пропуская через фильтр относительного времени. Однако фронтенд может полагаться на тему или плагин, который вызывает human_time_diff(), или же он может передавать необработанное значение из базы данных через цепочку преобразований часовых поясов PHP, которую бэкенд полностью обходит.
Таким образом, данные обычно остаются неповрежденными. Проблема заключается в «трубопроводе» между базой данных и отрисованным HTML, в котором возникает затор.
Версия PHP и настройки часового пояса
Начните с PHP. Панели управления хостингом делают смену версий безобидной процедурой, но PHP обрабатывает объекты времени по-разному в разных мажорных релизах. Сайт, работающий на устаревшем коде PHP 7.4 в среде PHP 8.1, может столкнуться с тонкими изменениями в том, как объекты DateTime инициализируют пустые или некорректные строки. Если в вашем файле php.ini параметр date.timezone не определен, PHP по умолчанию использует UTC и полагается на настройки сервера. WordPress может с этим не согласиться.
Проверьте, не прописал ли кто-нибудь объявление часового пояса жестко внутри wp-config.php. Строка вроде date_default_timezone_set( 'Asia/Kolkata' ); кажется полезной, но WordPress ожидает управлять своими часами самостоятельно через значение, установленное в Настройки > Общие. Принудительное смещение на уровне PHP может создать состояние гонки, при котором ядро считает время локальным, а PHP — универсальным. Когда эти смещения сталкиваются во время преобразования временной метки, результат, возвращаемый в ваш шаблон, может обнулиться.
Конфигурации часовых поясов сервера
Ваш сервер MySQL имеет свое представление о локальном времени. WordPress записывает две даты для каждой записи: post_date в локальном времени сайта и post_date_gmt в универсальном времени (UTC). Если глобальный параметр time_zone базы данных изменится — скажем, с SYSTEM на +00:00 после миграции — функция PHP strtotime() может не суметь сопоставить сохраненную строку с тем, что она ожидает. База данных по-прежнему хранит 2024-03-15 14:30:00, но контекст вокруг неё меняется, и результат парсинга в PHP становится false или null.
Пример из реальной жизни: управляемый хостинг переносит вашу базу данных с узла под управлением MySQL 5.7 с системным временем (SYSTEM) на кластер под управлением MariaDB 10.11, настроенный на строгий UTC. Ваша тема не менялась. Ваши настройки WordPress не менялись. Тем не менее, get_the_time( 'U' ) — формат Unix-таймштампа — внезапно возвращает пустое значение для некоторых постов, и функция относительного времени откатывается к расчету от «нулевой эпохи». Решение заключается в согласовании часового пояса приложения, часового пояса базы данных и часов операционной системы, чтобы WordPress не приходилось угадывать, какую систему отсчета использовать.
Форматы меток времени в базе данных
WordPress core stores post dates in MySQL DATETIME columns, not TIMESTAMP fields. That distinction matters because DATETIME holds a calendar value without_zone awareness in older MySQL versions, whereas TIMESTAMP converts everything to UTC behind the scenes. If a plugin or migration tool has altered your wp_posts schema, or if an old backup restored invalid zero dates into the table, WordPress may read a value like 0000-00-00 00:00:00 and quietly hand it off to your theme.
Modern MySQL modes, particularly NO_ZERO_DATE and STRICT_TRANS_TABLES, reject those zero placeholders. If a backup script inserted them during a migration, the database might have truncated or nulled them on import. You can verify this quickly with a direct SQL query:
SELECT ID, post_title, post_date, post_date_gmt
FROM wp_posts
WHERE post_status = 'publish'
ORDER BY post_date DESC
LIMIT 10;
If the raw columns look correct but the site still displays ancient history, the corruption is happening after the query. If the columns themselves contain zeroes, you have found the leak in the plumbing.
Plugin Conflicts with Date Functions
Plugins that filter date output are common culprits. Multilingual tools such as WPML or Polylang hook into get_the_date to translate month names. Caching plugins intercept the final HTML. Either layer can accidentally pass an unformatted string into a function expecting a Unix integer.
A translation plugin might replace “March 15, 2024” with its localized equivalent, but if a theme then pipes that localized string into strtotime() inside a custom function, the parser fails on non-English characters and returns false. That false value hits human_time_diff(), which compares zero against now, producing the infamous half-century gap.
Object cache layers complicate this further. Redis or Memcached can store a serialized WP_Post object from a request that briefly failed to parse the date. Every subsequent visitor receives that corrupted object straight from RAM, bypassing the database entirely. The issue persists on the live site because your production stack has cache infrastructure that your local install lacks.
A Practical Debugging Checklist
Because the symptom hides deep in the stack, you need to peel layers systematically until the dates snap back into place.
- Query the database directly. Open phpMyAdmin or run WP-CLI and inspect the raw
post_datevalues. If they are correct, the database is not the problem. - Switch to a default theme. Activate Twenty Twenty-Four or Twenty Twenty-Three. If the bug disappears, audit your active theme and child theme for custom functions wrapping time output.
- Silence the plugins. Rename the
/wp-content/pluginsfolder temporarily, or disable all plugins from the dashboard. Re-enable them one by one, checking the frontend after each activation. - Read the error log. Look for timezone warnings,
DateTimeerrors, orstrtotime()complaints. They often point to the exact
