यदि आपने कभी कोई पोस्ट लाइव की हो और सार्वजनिक साइट पर उसे "57 साल पहले" लिखा हुआ देखा हो, जबकि आपका डैशबोर्ड शांति से यह दावा कर रहा हो कि वह एक घंटे के दस मिनट बाद अपलोड हुई थी, तो आप इस बग की चुभन को समझते हैं। यह लेआउट को खराब नहीं करता। यह कोई घातक त्रुटि (fatal error) उत्पन्न नहीं करता। यह बस आपकी सामग्री को आधी सदी पुराना बना देता है, और अपनी थीम फ़ाइलों को घूरने से यह संख्या नहीं बदलेगी।
यह समस्या सामान्य जाँचों में भी बच निकलती है। आप single.php, archive.php, और functions.php में किसी खराब get_the_date() कॉल की तलाश में grep करते हैं। सब कुछ मानक (standard) दिखता है। आप लाइव पेज को रीलोड करते हैं। 1968 का भूत अभी भी आपकी बायलाइन (byline) में बना रहता है। उस बिंदु पर, समस्या का आपके टेम्पलेट्स से लगभग कोई लेना-देना नहीं होता, बल्कि इसका सीधा संबंध इस बात से है कि वर्डप्रेस स्टैक (WordPress stack) के माध्यम से समय कैसे गुजरता है।
वह विशिष्ट संख्या बार-बार क्यों दिखाई देती है
"57 साल पहले" का आंकड़ा रैंडम नहीं है। वर्डप्रेस थीम अक्सर human_time_diff() फ़ंक्शन के माध्यम से सापेक्ष समय (relative time) प्रदर्शित करती हैं, जो पोस्ट के टाइमस्टैम्प की तुलना वर्तमान समय से करती है और "2 घंटे पहले" जैसा एक सरल वाक्यांश प्रिंट करती है। उस गणित के काम करने के लिए, PHP को एक वैध Unix टाइमस्टैम्प की आवश्यकता होती है—जो 1 जनवरी, 1970 (Unix epoch) से अब तक के सेकंडों की गिनती है।
जब कोई चीज़ उस गणना तक पहुँचने से पहले टाइमस्टैम्प को हटा देती है या उसे दूषित (corrupt) कर देती है, तो फ़ंक्शन अक्सर वर्तमान समय की तुलना शून्य (या इसी तरह के किसी अमान्य शुरुआती बिंदु) से करने लगता है। इसका परिणाम लगभग साढ़े पांच दशकों का अंतराल होता है, जो हर कैलेंडर वर्ष के साथ थोड़ा आगे बढ़ता है। यह किसी गायब या गलत पढ़े गए समय मान (time value) का लक्षण है, न कि रेट्रो ब्लॉग पोस्ट से भरी डेटाबेस का।
डैशबोर्ड का भ्रम
इस बग के सबसे निराशाजनक पहलुओं में से एक आपके एडमिन पैनल का दोहरा व्यक्तित्व है। wp-admin के अंदर, पोस्ट सूची सही प्रकाशन तिथि दिखाती है क्योंकि वर्डप्रेस अक्सर इसे सीधे MySQL wp_posts टेबल से निकालता है और सापेक्ष-समय फ़िल्टर (relative-time filter) के माध्यम से चलाए बिना सर्वर-साइड पर ही फॉर्मेट कर देता है। हालाँकि, फ्रंटएंड किसी ऐसी थीम या प्लगइन पर निर्भर हो सकता है जो human_time_diff() को कॉल करता है, या यह कच्चे डेटाबेस मान को PHP टाइमज़ोन रूपांतरणों की एक श्रृंखला के माध्यम से पास कर सकता है जिसे बैकएंड पूरी तरह से बायपास कर देता है।
इसलिए डेटा आमतौर पर अभी भी सुरक्षित रहता है। समस्या डेटाबेस और रेंडर किए गए HTML के बीच के पाइपलाइन में आती है।
PHP वर्शन और टाइमज़ोन सेटिंग्स
PHP से शुरुआत करें। होस्टिंग पैनल वर्शन बदलने को हानिरहित दिखाते हैं, लेकिन PHP प्रमुख रिलीज़ के दौरान टाइम ऑब्जेक्ट्स को अलग-अलग तरह से संभालता है। अचानक PHP 8.1 वातावरण में पुराना PHP 7.4 कोड चलाने वाली साइट को DateTime ऑब्जेक्ट्स द्वारा खाली या खराब स्ट्रिंग्स को इनिशियलाइज़ करने के तरीके में सूक्ष्म बदलावों का सामना करना पड़ सकता है। यदि आपकी php.ini फ़ाइल में date.timezone को अनडिफाइंड (undefined) छोड़ दिया गया है, तो PHP डिफ़ॉल्ट रूप से UTC पर सेट हो जाता है और मान लेता है कि सर्वर को सबसे बेहतर पता है। वर्डप्रेस इससे असहमत हो सकता है।
जाँचें कि क्या किसी ने wp-config.php के अंदर टाइमज़ोन डिक्लेरेशन को हार्डकोड किया है। date_default_timezone_set( 'Asia/Kolkata' ); जैसी लाइन मददगार लग सकती है, लेकिन वर्डप्रेस Settings > General के तहत सेट किए गए मान के माध्यम से अपनी घड़ी को प्रबंधित करने की अपेक्षा करता है। PHP-स्तर का ऑफसेट (offset) लागू करने से एक 'रेस कंडीशन' (race condition) पैदा हो सकती है जहाँ कोर (core) का मानना है कि समय स्थानीय है और PHP का मानना है कि यह सार्वभौमिक (universal) है। जब टाइमस्टैम्प रूपांतरण के दौरान ये ऑफसेट आपस में टकराते हैं, तो आपके टेम्पलेट को मिलने वाला परिणाम शून्य हो सकता है।
सर्वर टाइम ज़ोन कॉन्फ़िगरेशन
आपका MySQL सर्वर स्थानीय समय के बारे में अपनी अलग धारणा रखता है। वर्डप्रेस प्रत्येक पोस्ट के लिए दो तारीखें लिखता है: साइट के स्थानीय समय में 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 क्लस्टर पर ले जाता है। आपकी थीम कभी नहीं बदलती। आपकी वर्डप्रेस सेटिंग्स कभी नहीं बदलतीं। फिर भी get_the_time( 'U' )—Unix टाइमस्टैम्प फॉर्मेट—अचानक कुछ पोस्ट के लिए एक खाली मान लौटाता है, और सापेक्ष-समय फ़ंक्शन उस epoch-zero गणना पर वापस चला जाता है। इसका समाधान एप्लिकेशन टाइमज़ोन, डेटाबेस टाइमज़ोन और ऑपरेटिंग सिस्टम क्लॉक को एक समान (align) करना है ताकि वर्डप्रेस को यह अनुमान न लगाना पड़े कि किस संदर्भ (frame of reference) का उपयोग करना है।
डेटाबेस टाइमस्टैम्प फॉर्मेट्स
WordPress core पोस्ट की तारीखों को MySQL DATETIME कॉलम में स्टोर करता है, TIMESTAMP फ़ील्ड में नहीं। यह अंतर महत्वपूर्ण है क्योंकि पुराने MySQL वर्ज़न में DATETIME बिना zone awareness के कैलेंडर वैल्यू रखता है, जबकि TIMESTAMP पर्दे के पीछे सब कुछ UTC में बदल देता है। यदि किसी प्लगइन या माइग्रेशन टूल ने आपके wp_posts स्कीमा को बदल दिया है, या यदि किसी पुराने बैकअप ने टेबल में अमान्य ज़ीरो डेट्स (zero dates) को रिस्टोर कर दिया है, तो WordPress 0000-00-00 00:00:00 जैसी वैल्यू पढ़ सकता है और चुपचाप इसे आपके थीम को सौंप सकता है।
आधुनिक MySQL मोड, विशेष रूप से NO_ZERO_DATE और STRICT_TRANS_TABLES, उन ज़ीरो प्लेसहोल्डर्स को रिजेक्ट कर देते हैं। यदि माइग्रेशन के दौरान किसी बैकअप स्क्रिप्ट ने उन्हें डाला था, तो डेटाबेस इम्पोर्ट के समय उन्हें ट्रंकेट (truncate) या नल (null) कर सकता है। आप एक डायरेक्ट SQL क्वेरी के साथ इसकी जल्दी से पुष्टि कर सकते हैं:
SELECT ID, post_title, post_date, post_date_gmt
FROM wp_posts
WHERE post_status = 'publish'
ORDER BY post_date DESC
LIMIT 10;
यदि रॉ कॉलम सही दिखते हैं लेकिन साइट अभी भी बहुत पुरानी तारीखें दिखा रही है, तो करप्शन (corruption) क्वेरी के बाद हो रहा है। यदि कॉलम में खुद ज़ीरो हैं, तो आपने समस्या की जड़ ढूंढ ली है।
डेट फ़ंक्शंस के साथ प्लगइन संघर्ष (Conflicts)
डेट आउटपुट को फ़िल्टर करने वाले प्लगइन अक्सर इसके दोषी होते हैं। WPML या Polylang जैसे मल्टीलिंगुअल टूल्स महीने के नामों का अनुवाद करने के लिए get_the_date में हुक करते हैं। कैशिंग प्लगइन्स अंतिम HTML को इंटरसेप्ट करते हैं। इनमें से कोई भी लेयर गलती से एक अनफ़ॉर्मेटेड स्ट्रिंग को ऐसे फ़ंक्शन में पास कर सकती है जो Unix इंटीजर की अपेक्षा करता है।
एक ट्रांसलेशन प्लगइन “March 15, 2024” को उसके स्थानीय समकक्ष (localized equivalent) से बदल सकता है, लेकिन यदि थीम फिर उस स्थानीय स्ट्रिंग को किसी कस्टम फ़ंक्शन के अंदर strtotime() में भेजती है, तो पार्सर गैर-अंग्रेजी वर्णों (non-English characters) पर विफल हो जाता है और false रिटर्न करता है। वह false वैल्यू human_time_diff() तक पहुँचती है, जो 'अब' (now) के साथ ज़ीरो की तुलना करती है, जिससे वह कुख्यात आधी सदी का अंतर पैदा होता है।
ऑब्जेक्ट कैश लेयर्स इसे और अधिक जटिल बना देती हैं। Redis या Memcached एक ऐसे अनुरोध (request) से सीरियलाइज़्ड WP_Post ऑब्जेक्ट को स्टोर कर सकते हैं जो तारीख को पार्स करने में विफल रहा था। इसके बाद आने वाला हर विज़िटर सीधे RAM से उस करप्टेड ऑब्जेक्ट को प्राप्त करता है, जिससे डेटाबेस पूरी तरह से बायपास हो जाता है। यह समस्या लाइव साइट पर बनी रहती है क्योंकि आपके प्रोडक्शन स्टैक में कैश इंफ्रास्ट्रक्चर है जो आपके लोकल इंस्टॉलेशन में नहीं है।
एक व्यावहारिक डिबगिंग चेकलिस्ट
क्योंकि लक्षण स्टैक में गहराई में छिपे होते हैं, इसलिए आपको व्यवस्थित रूप से परतों को हटाना होगा जब तक कि तारीखें सही न हो जाएं।
- डेटाबेस को सीधे क्वेरी करें। phpMyAdmin खोलें या WP-CLI चलाएं और रॉ
post_dateवैल्यूज़ का निरीक्षण करें। यदि वे सही हैं, तो डेटाबेस समस्या नहीं है। - डिफ़ॉल्ट थीम पर स्विच करें। Twenty Twenty-Four या Twenty Twenty-Three को एक्टिवेट करें। यदि बग गायब हो जाता है, तो अपने एक्टिव थीम और चाइल्ड थीम में टाइम आउटपुट को रैप करने वाले कस्टम फ़ंक्शंस का ऑडिट करें।
- प्लगइन्स को शांत करें। अस्थायी रूप से
/wp-content/pluginsफ़ोल्डर का नाम बदलें, या डैशबोर्ड से सभी प्लगइन्स को डिसेबल करें। उन्हें एक-एक करके फिर से इनेबल करें, और प्रत्येक एक्टिवेशन के बाद फ्रंटएंड की जाँच करें। - एरर लॉग पढ़ें। टाइमज़ोन चेतावनियों,
DateTimeएरर्स, याstrtotime()की शिकायतों को देखें। वे अक्सर सटीक
