کسی تاریخ میں مہینے جوڑنا جتنا آسان لگتا ہے اتنا ہے نہیں
کسی تاریخ میں 7 دن جوڑنا آسان ہے۔ ایک عدد ملتا ہے، آپ 7 بڑھا دیتے ہیں، بات ختم۔ لیکن ایک مہینہ جوڑنا بالکل مختلف مسئلہ ہے۔
مسئلہ یہ ہے کہ مہینوں کے دن یکساں نہیں ہوتے۔ جنوری میں 31 دن ہوتے ہیں۔ فروری میں 28، اور بعض اوقات 29۔ اگر آپ 31 جنوری پر ہیں اور ایک مہینہ جوڑتے ہیں تو نتیجہ 31 فروری بنتا ہے — جو موجود ہی نہیں۔
ہر کیلنڈر لائبریری، اسپریڈشیٹ اور ڈیٹابیس کے پاس اس کے بعد کیا کرنا ہے اس پر اپنی رائے ہوتی ہے۔
زیادہ تر ٹولز کیا کرتے ہیں
سب سے عام رویہ یہ ہے کہ ٹارگٹ مہینے کے آخری دن پر “سنیپ” کر دیا جاتا ہے۔ 31 جنوری + 1 مہینہ = 28 فروری (یا لیپ سال میں 29)۔ 31 مارچ + 1 مہینہ = 30 اپریل۔
اسے end-of-month clamping کہا جاتا ہے اور یہی Excel، Google Sheets، Python کی dateutil اور زیادہ تر date libraries بطور ڈیفالٹ کرتی ہیں۔
یہ معقول ہے، مگر اس میں ایک باریک مسئلہ ہے: یہ عمل reversible نہیں رہتا۔ اگر آپ 31 جنوری میں ایک مہینہ جوڑیں تو 28 فروری ملتا ہے۔ پھر اگر ایک مہینہ کم کریں تو 28 جنوری آئے گا — 31 جنوری نہیں۔ آپ نے تین دن “کھو” دیے۔
Overflow والا طریقہ
کچھ سسٹمز clamping کے بجائے تاریخ کو اگلے مہینے میں overflow ہونے دیتے ہیں۔ 31 جنوری + 1 مہینہ = 3 مارچ (یا لیپ سال میں 2 مارچ، کیونکہ فروری میں 29 دن ہوتے ہیں)۔
اس سے کل دنوں کی گنتی تو برقرار رہتی ہے، مگر نتیجہ اس مہینے میں چلا جاتا ہے جس کا آپ نے ارادہ نہیں کیا تھا۔ یہ حیران کن بھی ہے اور عام طور پر صارف کے نقطۂ نظر سے غلط بھی۔
کچھ ڈیٹابیسز میں SQL کی INTERVAL syntax کنفیگریشن کے مطابق یہی رویہ اختیار کرتی ہے۔ اگر آپ کو یہ معلوم نہ ہو کہ آپ کس رویے کے ساتھ کام کر رہے ہیں تو آسانی سے مسئلہ بن سکتا ہے۔
سال جوڑنے میں بھی یہی مسئلہ آتا ہے
29 فروری صرف لیپ سال میں ہوتی ہے۔ 29 فروری 2024 میں ایک سال جوڑیں تو 29 فروری 2025 بنتا ہے — جو موجود نہیں۔ clamping کے تحت نتیجہ 28 فروری 2025 ہوگا۔
وہی رویہ، وہی tradeoffs۔
یہ اصل میں کہاں bugs پیدا کرتا ہے
سبسکرپشن بلنگ کلاسک مثال ہے۔ صارف 31 جنوری کو سائن اپ کرتا ہے۔ اگلی بلنگ کی تاریخ 28 فروری بنتی ہے۔ پھر 28 مارچ۔ پھر 28 اپریل۔ پہلے مہینے کے بعد ہر مہینے ان سے 2–3 دن پہلے بل کٹنے لگتا ہے جتنا وہ توقع کرتے ہیں۔
ریکرنگ کیلنڈر ایونٹس میں بھی یہی مسئلہ ہے۔ “ہر مہینے 31 تاریخ کو” خاموشی سے “ہر مہینے آخری دن” بن جاتا ہے اُن مہینوں میں جن میں 31 دن نہیں ہوتے۔
قرض کی ادائیگی کے شیڈول، پے رول کی تاریخیں، اور ہر وہ چیز جس میں “ماہانہ” تکرار ہو — آخرکار اس edge case سے ٹکراتی ہے۔
دن جوڑنے میں یہ مسئلہ نہیں
اگر آپ “ایک مہینہ بعد” کی جگہ “اب سے 30 دن بعد” کہنا چاہتے ہیں تو صرف 30 دن جوڑ دیں۔ نتیجہ واضح اور reversible ہوتا ہے۔
یہ فرق اہم ہے: 30 دن کا بلنگ سائیکل اور ماہانہ بلنگ سائیکل ایک جیسا نہیں ہوتا، اور وقت کے ساتھ یہ تیزی سے مختلف ہوتے جاتے ہیں۔
اپنے ٹول یا لائبریری میں کیا چیک کریں
کسی بھی سسٹم میں date addition پر بھروسہ کرنے سے پہلے یہ جاننا مفید ہے:
- کیا وہ month-end تاریخوں پر clamp کرتا ہے یا overflow؟
- کیا وہ متعدد اضافوں میں day-of-month کو برقرار رکھتا ہے یا ہر بار دوبارہ clamp کرتا ہے؟
- لیپ سال کے معاملات میں Feb 29 + 1 year پر کیا ہوتا ہے؟
Date Calculator کسی بھی تاریخ اور offset کے لیے بالکل درست نتیجہ دکھاتا ہے — کوڈ میں حساب فکس کرنے سے پہلے sanity-check کرنے کے لیے مفید۔