اگر آپ نے کبھی کوئی پوسٹ لائیو کی ہو اور پھر عوامی سائٹ پر اسے "57 سال پہلے" لکھا ہوا دیکھا ہو، جبکہ آپ کا ڈیش بورڈ سکون سے یہ دعویٰ کر رہا ہو کہ یہ پچھلے دس منٹ میں اپ لوڈ ہوئی ہے، تو آپ اس بگ (bug) کی خاص تکلیف کو جانتے ہوں گے۔ یہ لے آؤٹ کو خراب نہیں کرتا۔ یہ کوئی سنگین غلطی (fatal error) پیدا نہیں کرتا۔ یہ بس آپ کے مواد کو آدھی صدی پرانا کر دیتا ہے، اور آپ کے تھیم فائلز کو گھورنے سے یہ نمبر تبدیل نہیں ہوگا۔

یہ مسئلہ عام چیکس سے بچ نکلتا ہے۔ آپ single.php، archive.php اور functions.php میں کسی خراب get_the_date() کال کی تلاش میں grep کرتے ہیں۔ سب کچھ معمول کے مطابق نظر آتا ہے۔ آپ لائیو پیج کو ری لوڈ کرتے ہیں۔ 1968 کا سایہ اب بھی آپ کی بائی لائن (byline) پر منڈلا رہا ہوتا ہے۔ اس مقام پر، مسئلہ آپ کے ٹیمپلیٹس سے تقریباً کوئی تعلق نہیں رکھتا بلکہ اس بات سے ہے کہ وقت ورڈپریس اسٹیک (WordPress stack) کے ذریعے کیسے گزرتا ہے۔

یہ مخصوص نمبر بار بار کیوں ظاہر ہوتا ہے

"57 سال پہلے" کا ہندسہ کوئی اتفاقی نہیں ہے۔ ورڈپریس تھیمز اکثر human_time_diff() فنکشن کے ذریعے متعلقہ وقت (relative time) دکھاتے ہیں، جو پوسٹ کے ٹائم اسٹیمپ کا موجودہ وقت سے موازنہ کرتا ہے اور "2 گھنٹے پہلے" جیسا دوستانہ جملہ پرنٹ کرتا ہے۔ اس حساب کتاب کے کام کرنے کے لیے، PHP کو ایک درست Unix ٹائم اسٹیمپ کی ضرورت ہوتی ہے—جو 1 جنوری 1970 (Unix epoch) سے گزرے ہوئے سیکنڈز کی تعداد ہوتی ہے۔

جب کوئی چیز اس حساب کتاب تک پہنچنے سے پہلے ٹائم اسٹیمپ کو ہٹا دیتی ہے یا خراب کر دیتی ہے، تو فنکشن اکثر موجودہ وقت کا موازنہ صفر (یا اسی طرح کے کسی غلط آغاز کے نقطہ) سے کرنے لگتا ہے۔ اس کا نتیجہ تقریباً ساڑھے پانچ دہائیوں پرانا عرصہ ہوتا ہے، جو ہر سال ایک سال آگے بڑھتا ہے۔ یہ کسی گمشدہ یا غلط پڑھے گئے وقت کی ویلیو کی علامت ہے، نہ کہ ریٹرو بلاگ پوسٹس سے بھری ہوئی ڈیٹا بیس کی وجہ سے۔

ڈیش بورڈ کا دھوکہ

اس بگ کا ایک زیادہ مایوس کن پہلو آپ کے ایڈمن پینل کی دوہری شخصیت ہے۔ wp-admin کے اندر، پوسٹس کی فہرست صحیح اشاعت کی تاریخ دکھاتی ہے کیونکہ ورڈپریس اکثر اسے براہ راست MySQL کے wp_posts ٹیبل سے نکالتا ہے اور اسے ریلیٹیو ٹائم فلٹر سے گزارے بغیر سرور سائیڈ پر فارمیٹ کرتا ہے۔ تاہم، فرنٹ اینڈ کسی ایسے تھیم یا پلگ ان پر انحصار کر سکتا ہے جو human_time_diff() کو کال کرتا ہے، یا یہ خام ڈیٹا بیس ویلیو کو PHP ٹائم زون کنورژن کی ایک زنجیر کے ذریعے پاس کر سکتا ہے جسے بیک اینڈ مکمل طور پر نظر انداز کر دیتا ہے۔

لہذا ڈیٹا عام طور پر اب بھی درست ہوتا ہے۔ مسئلہ ڈیٹا بیس اور رینڈر شدہ (rendered) HTML کے درمیان موجود پائپ لائن میں خرابی کی وجہ سے ہوتا ہے۔

PHP ورژن اور ٹائم زون سیٹنگز

PHP سے آغاز کریں۔ ہوسٹنگ پینلز ورژن کی تبدیلی کو بے ضرر دکھاتے ہیں، لیکن PHP بڑے ریلیز کے دوران ٹائم آبجیکٹس کو مختلف طریقے سے ہینڈل کرتا ہے۔ ایک سائٹ جو اچانک PHP 8.1 کے ماحول میں پرانا PHP 7.4 کوڈ چلا رہی ہو، اسے DateTime آبجیکٹس کے خالی یا خراب اسٹرنگز کو انیشلائز (initialize) کرنے کے طریقے میں باریک فرق کا سامنا کرنا پڑ سکتا ہے۔ اگر آپ کی 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) حساب کتاب پر واپس چلا جاتا ہے۔ اس کا حل ایپلی کیشن ٹائم زون، ڈیٹا بیس ٹائم زون اور آپریٹنگ سسٹم کلاک کو ایک لائن میں لانا ہے تاکہ ورڈپریس کو یہ اندازہ نہ لگانا پڑے کہ کس ریفرنس فریم کا استعمال کرنا ہے۔

ڈیٹا بیس ٹائم اسٹیمپ فارمیٹس

WordPress core پوسٹ کی تاریخوں کو MySQL کے DATETIME کالمز میں محفوظ کرتا ہے، نہ کہ TIMESTAMP فیلڈز میں۔ یہ فرق اہم ہے کیونکہ پرانے MySQL ورژنز میں DATETIME ٹائم زون کی آگاہی کے بغیر کیلنڈر کی ویلیو رکھتا ہے، جبکہ 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;

اگر خام کالمز (raw columns) درست نظر آتے ہیں لیکن سائٹ اب بھی قدیم تاریخیں دکھا رہی ہے، تو خرابی کوئری کے بعد ہو رہی ہے۔ اگر کالمز میں خود زیرو موجود ہیں، تو آپ نے مسئلے کی اصل جڑ تلاش کر لی ہے۔

تاریخ کے فنکشنز کے ساتھ پلگ ان کے تصادم (Conflicts)

تاریخ کے آؤٹ پٹ کو فلٹر کرنے والے پلگ ان عام طور پر اس کی وجہ ہوتے ہیں۔ WPML یا Polylang جیسے کثیر لسانی (multilingual) ٹولز مہینوں کے ناموں کا ترجمہ کرنے کے لیے get_the_date کا استعمال کرتے ہیں۔ Caching پلگ انز حتمی HTML کو روک لیتے ہیں۔ ان میں سے کوئی بھی لیئر غلطی سے کسی ایسے فنکشن میں غیر فارمیٹ شدہ اسٹرنگ بھیج سکتی ہے جو Unix انٹیجر کی توقع رکھتا ہو۔

ایک ترجمہ پلگ ان "March 15, 2024" کو اس کے مقامی متبادل سے بدل سکتا ہے، لیکن اگر کوئی تھیم اس مقامی اسٹرنگ کو کسی کسٹم فنکشن کے اندر strtotime() میں بھیجتا ہے، تو پارسر غیر انگریزی حروف پر ناکام ہو جاتا ہے اور false واپس کرتا ہے۔ وہ false ویلیو human_time_diff() تک پہنچتی ہے، جو زیرو کا موازنہ موجودہ وقت سے کرتی ہے، جس کے نتیجے میں وہ مشہور نصف صدی کا فرق پیدا ہو جاتا ہے۔

Object cache لیئرز اس معاملے کو مزید پیچیدہ بنا دیتی ہیں۔ Redis یا Memcached ایک ایسی درخواست سے حاصل شدہ serialized WP_Post آبجیکٹ کو محفوظ کر سکتے ہیں جس میں تاریخ کو پارس کرنے میں عارضی طور پر ناکامی ہوئی ہو۔ ہر آنے والا وزیٹر براہ راست RAM سے وہی خراب آبجیکٹ حاصل کرتا ہے، جس سے ڈیٹا بیس مکمل طور پر نظر انداز ہو جاتا ہے۔ یہ مسئلہ لائیو سائٹ پر برقرار رہتا ہے کیونکہ آپ کے پروڈکشن اسٹیک میں کیش انفراسٹرکچر موجود ہے جو آپ کی لوکل انسٹالیشن میں نہیں ہے۔

ڈیبگنگ کے لیے ایک عملی چیک لسٹ

چونکہ علامت (symptom) اسٹیک میں بہت گہرائی میں چھپی ہوتی ہے، اس لیے آپ کو ترتیب وار تہوں کو ہٹانا ہوگا جب تک کہ تاریخیں درست نہ ہو جائیں۔

  1. براہ راست ڈیٹا بیس کو کوئری کریں۔ phpMyAdmin کھولیں یا WP-CLI چلائیں اور خام post_date ویلیوز کا معائنہ کریں۔ اگر وہ درست ہیں، تو ڈیٹا بیس مسئلہ نہیں ہے۔
  2. ڈیفالٹ تھیم پر سوئچ کریں۔ Twenty Twenty-Four یا Twenty Twenty-Three کو ایکٹیویٹ کریں۔ اگر بگ ختم ہو جاتا ہے، تو اپنے ایکٹیو تھیم اور چائلڈ تھیم میں ٹائم آؤٹ پٹ کو ریپ (wrap) کرنے والے کسٹم فنکشنز کا جائزہ لیں۔
  3. پلگ انز کو خاموش کریں۔ عارضی طور پر /wp-content/plugins فولڈر کا نام تبدیل کریں، یا ڈیش بورڈ سے تمام پلگ انز کو غیر فعال کر دیں۔ انہیں ایک ایک کر کے دوبارہ فعال کریں، اور ہر ایکٹیویشن کے بعد فرنٹ اینڈ کو چیک کریں۔
  4. ایرر لاگ (error log) پڑھیں۔ ٹائم زون وارننگز، DateTime ایررز، یا strtotime() کی شکایات تلاش کریں۔ وہ اکثر بالکل