നിങ്ങൾ ഒരു പോസ്റ്റ് ലൈവ് ചെയ്ത ശേഷം, ഡാഷ്‌ബോർഡിൽ അത് പത്ത് മിനിറ്റ് മുമ്പ് പോസ്റ്റ് ചെയ്തതായി കാണിക്കുമ്പോഴും പബ്ലിക് സൈറ്റിൽ അത് “57 years ago” എന്ന് കാണിക്കുന്നുണ്ടെങ്കിൽ, ഈ ബഗ്ഗ് ഉണ്ടാക്കുന്ന വിഷമം നിങ്ങൾക്ക് അറിയാം. ഇത് ലേഔട്ടിനെ തകർക്കുന്നില്ല. ഇത് ഒരു fatal error-ഉം ഉണ്ടാക്കുന്നില്ല. ഇത് നിങ്ങളുടെ ഉള്ളടക്കത്തെ വെറും അരനൂറ്റാണ്ട് പഴക്കമുള്ളതാക്കി മാറ്റുന്നു, നിങ്ങളുടെ തീം ഫയലുകൾ നോക്കിയതുകൊണ്ട് മാത്രം ഈ മാറ്റം മാറില്ല.

സാധാരണ പരിശോധനകളിലൂടെ ഈ പ്രശ്നം കടന്നുപോകാറുണ്ട്. single.php, archive.php, functions.php എന്നിവയിൽ തെറ്റായ രീതിയിലുള്ള get_the_date() കോൾ ഉണ്ടോ എന്ന് നിങ്ങൾ തിരയുന്നുണ്ടാകാം. എല്ലാം സാധാരണ പോലെ തന്നെ തോന്നും. നിങ്ങൾ ലൈവ് പേജ് റീലോഡ് ചെയ്യുന്നു. എങ്കിലും 1968-ലെ ആ പഴയ തീയതി അവിടെത്തന്നെ കാണാം. ആ ഘട്ടത്തിൽ, പ്രശ്നം നിങ്ങളുടെ ടെംപ്ലേറ്റുകളുമായി ബന്ധപ്പെട്ടതല്ല, മറിച്ച് WordPress സ്റ്റാക്കിലൂടെ സമയം കൈമാറ്റം ചെയ്യപ്പെടുന്ന രീതിയുമായി ബന്ധപ്പെട്ടതാണ്.

എന്തുകൊണ്ടാണ് ആ പ്രത്യേക നമ്പർ വീണ്ടും വരുന്നത്?

“57 years ago” എന്ന ആ നമ്പർ യാദൃശ്ചികമല്ല. WordPress തീമുകൾ പലപ്പോഴും human_time_diff() എന്ന ഫങ്ക്ഷൻ ഉപയോഗിച്ചാണ് സമയം കാണിക്കുന്നത്. ഇത് ഒരു പോസ്റ്റിന്റെ ടൈംസ്റ്റാമ്പിനെ നിലവിലെ സമയവുമായി താരതമ്യം ചെയ്യുകയും “2 hours ago” എന്നിങ്ങനെയുള്ള ലളിതമായ പ്രയോഗങ്ങൾ നൽകുകയും ചെയ്യുന്നു. ഈ കണക്കുകൂട്ടൽ ശരിയാകാൻ PHP-ക്ക് ഒരു സാധുവായ Unix timestamp ആവശ്യമാണ്—അതായത്, Unix epoch ആയ 1970 ജനുവരി 1 മുതൽ എണ്ണുന്ന സെക്കൻഡുകളുടെ എണ്ണം.

ഈ കണക്കുകൂട്ടലിലേക്ക് എത്തുന്നതിന് മുമ്പ് ടൈംസ്റ്റാമ്പ് നഷ്ടപ്പെടുകയോ കേടുപാടുകൾ സംഭവിക്കുകയോ ചെയ്താൽ, ആ ഫങ്ക്ഷൻ പൂജ്യത്തെയോ (അല്ലെങ്കിൽ സമാനമായ തെറ്റായ ഒരു മൂല്യത്തെയോ) നിലവിലെ സമയവുമായി താരതമ്യം ചെയ്യുന്നു. ഇതിന്റെ ഫലമായി ഏകദേശം അഞ്ചര പതിറ്റാണ്ട് പഴക്കമുള്ള ഒരു സമയം കാണിക്കുന്നു. ഇത് ഒരു ടൈം വാല്യൂ നഷ്ടപ്പെടുകയോ തെറ്റായി വായിക്കപ്പെടുകയോ ചെയ്യുന്നതിന്റെ ലക്ഷണമാണ്, അല്ലാതെ നിങ്ങളുടെ ഡാറ്റാബേസിൽ പഴയ ബ്ലോഗ് പോസ്റ്റുകൾ നിറഞ്ഞിരിക്കുന്നതുകൊണ്ടല്ല.

ഡാഷ്‌ബോർഡിലെ വഞ്ചന

ഈ ബഗ്ഗിന്റെ ഏറ്റവും നിരാശാജനകമായ ഒരു വശം നിങ്ങളുടെ അഡ്മിൻ പാനലിന്റെ ഈ ഇരട്ട സ്വഭാവമാണ്. wp-admin-നുള്ളിലെ പോസ്റ്റ് ലിസ്റ്റിൽ ശരിയായ പ്രസിദ്ധീകരണ തീയതി കാണിക്കുന്നുണ്ടാകും, കാരണം WordPress പലപ്പോഴും MySQL-ലെ wp_posts ടേബിളിൽ നിന്ന് നേരിട്ട് വിവരങ്ങൾ എടുക്കുകയും അവയെ റിലേറ്റീവ്-ടൈം ഫിൽട്ടറിലൂടെ കടത്തിവിടാതെയുള്ള സെർവർ സൈഡ് ഫോർമാറ്റിംഗിലൂടെ കാണിക്കുകയും ചെയ്യുന്നു. എന്നാൽ ഫ്രണ്ട് എൻഡ് (frontend), 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' ); എന്ന വരി ഉപയോഗിക്കുന്നത് നല്ലതാണെന്ന് തോന്നാമെങ്കിലും, Settings > General എന്നതിൽ നൽകിയിരിക്കുന്ന മൂല്യത്തിലൂടെ സ്വന്തം സമയം നിയന്ത്രിക്കാനാണ് WordPress ആഗ്രഹിക്കുന്നത്. PHP തലത്തിൽ ഒരു ടൈംസോൺ മാറ്റം വരുത്തുന്നത് ഒരു race condition ഉണ്ടാക്കിയേക്കാം; അതായത്, കോർ (core) സമയം ലോക്കൽ ആണെന്നും PHP സമയം യൂണിവേഴ്സൽ ആണെന്നും കരുതുന്ന അവസ്ഥ. ടൈംസ്റ്റാമ്പ് കൺവേർഷൻ സമയത്ത് ഈ വ്യത്യാസങ്ങൾ കൂട്ടിമുട്ടുമ്പോൾ, ടെംപ്ലേറ്റിലേക്ക് ലഭിക്കുന്ന മൂല്യം പൂജ്യമായി മാറാം.

സെർവർ ടൈംസോൺ കോൺഫിഗറേഷനുകൾ

നിങ്ങളുടെ MySQL സെർവർക്ക് അതിന്റേതായ ലോക്കൽ സമയം ഉണ്ടായിരിക്കും. ഓരോ പോസ്റ്റിനും WordPress രണ്ട് തീയതികൾ രേഖപ്പെടുത്തുന്നു: സൈറ്റിന്റെ ലോക്കൽ സമയത്തിലുള്ള post_date, കൂടാതെ യൂണിവേഴ്സൽ ടൈമിലുള്ള post_date_gmt. ഒരു മൈഗ്രേഷന് ശേഷം ഡാറ്റാബേസിലെ ഗ്ലോബൽ time_zone മാറിയാൽ (ഉദാഹരണത്തിന് SYSTEM-ൽ നിന്ന് +00:00-ലേക്ക്), PHP-യുടെ strtotime() ഫങ്ക്ഷന് സ്റ്റോർ ചെയ്തിരിക്കുന്ന സ്ട്രിംഗും അത് പ്രതീക്ഷിക്കുന്ന സമയവും തമ്മിൽ യോജിപ്പിക്കാൻ കഴിഞ്ഞെന്നു വരില്ല. ഡാറ്റാബേസിൽ 2024-03-15 14:30:00 എന്ന് തന്നെ ഉണ്ടാകുമെങ്കിലും, അതിന്റെ ചുറ്റുപാടുമുള്ള സന്ദർഭം മാറുന്നതിനാൽ PHP-യിൽ ലഭിക്കുന്ന ഔട്ട്പുട്ട് തെറ്റായതോ (false) അല്ലെങ്കിൽ ശൂന്യമോ (null) ആകാം.

ഒരു യഥാർത്ഥ ഉദാഹരണം: ഒരു മാനേജ്ഡ് ഹോസ്റ്റ് നിങ്ങളുടെ ഡാറ്റാബേസിനെ SYSTEM ടൈം ഉള്ള MySQL 5.7 നോഡിൽ നിന്ന് സ്ട്രിക്റ്റ് UTC സെറ്റ് ചെയ്തിട്ടുള്ള MariaDB 10.11 ക്ലസ്റ്ററിലേക്ക് മാറ്റുന്നു എന്ന് കരുതുക. നിങ്ങളുടെ തീമിലോ WordPress സെറ്റിംഗ്സിലോ മാറ്റമൊന്നും സംഭവിക്കുന്നില്ല. എങ്കിലും, ചില പോസ്റ്റുകൾക്ക് get_the_time( 'U' )—അതായത് Unix timestamp ഫോർമാറ്റ്—പെട്ടെന്ന് ഒരു ശൂന്യമായ മൂല്യം നൽകുന്നു, തൽഫലമായി റിലേറ്റീവ്-ടൈം ഫങ്ക്ഷൻ ആ പഴയ എപ്പോക്ക്-സീറോ (epoch-zero) കണക്കുകൂട്ടലിലേക്ക് മാറുന്നു. ഇതിനുള്ള പരിഹാരം ആപ്ലിക്കേഷൻ ടൈംസോൺ, ഡാറ്റാബേസ് ടൈംസോൺ, ഓപ്പറേറ്റിംഗ് സിസ്റ്റം ക്ലോക്ക് എന്നിവ ഒരേപോലെ ക്രമീകരിക്കുക എന്നതാണ്, അങ്ങനെ 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