Якщо ви коли-небудь публікували допис лише для того, щоб побачити на публічному сайті напис «57 років тому», тоді як ваша панель керування спокійно стверджує, що він з'явився десять хвилин тому, ви знаєте, наскільки прикрим є цей баг. Він не ламає верстку. Він не викликає фатальної помилки. Він просто «старить» ваш контент на пів століття, і вивчення файлів теми не допоможе змінити це число.

Ця проблема зазвичай вислизає від звичайних перевірок. Ви шукаєте через grep у файлах single.php, archive.php та functions.php пошкоджений виклик get_the_date(). Все виглядає стандартно. Ви оновлюєте сторінку. Привид 1968 року все ще переслідує ваш підпис під статтею. На цьому етапі проблема майже не стосується ваших шаблонів — вона повністю пов'язана з тим, як час проходить крізь стек WordPress.

Чому з'являється саме це число

Число «57 років тому» не є випадковим. Теми WordPress часто відображають відносний час за допомогою функції human_time_diff(), яка порівнює мітку часу допису з поточним моментом і виводить зрозумілу фразу, наприклад, «2 години тому». Щоб цей розрахунок спрацював, PHP потрібен коректний Unix timestamp — кількість секунд, що минули з 1 січня 1970 року (Unix epoch).

Коли щось видаляє або пошкоджує мітку часу до того, як вона потрапить у цей розрахунок, функція часто порівнює нуль (або подібну недійсну початкову точку) з поточним часом. Результатом є проміжок часу, що тягнеться приблизно на п'ять з половиною десятиліть, збільшуючись на один календарний рік за раз. Це симптом відсутності або неправильного зчитування значення часу, а не бази даних, повної ретро-записів.

Обман панелі керування

Одним із найбільш прикрих аспектів цього багу є «розщеплена особистість» вашої адмін-панелі. У 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 може створити стан гонитви (race condition), коли ядро вважає час локальним, а 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 timestamp — раптом повертає порожнє значення для деяких дописів, і функція відносного часу переходить до розрахунку від нуля епохи. Вирішення полягає в узгодженні часового поясу додатка, часового поясу бази даних та годинника операційної системи, щоб 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.

  1. Query the database directly. Open phpMyAdmin or run WP-CLI and inspect the raw post_date values. If they are correct, the database is not the problem.
  2. 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.
  3. Silence the plugins. Rename the /wp-content/plugins folder temporarily, or disable all plugins from the dashboard. Re-enable them one by one, checking the frontend after each activation.
  4. Read the error log. Look for timezone warnings, DateTime errors, or strtotime() complaints. They often point to the exact