Date در جاوااسکریپت داره بهت دروغ میگه
خلاصهٔ کاملتر
شروع پست با سه نمونهٔ سادهست. رشتهٔ '2026-07-21' طبق اسپک بهعنوان نیمهشب UTC پارس میشه، پس getDate() برای کاربری که غرب UTC ـه عدد ۲۰ برمیگردونه نه ۲۱. سازندهٔ عددی هم ماهها رو از صفر میشمره، پس عدد 7 یعنی اوت نه ژوئیه. و چون اشیای Date تغییرپذیرن، setDate(32) بدون هیچ خطایی به ماه بعد سر میخوره:
const d2 = new Date(2026, 7, 21)
console.log(d2.toDateString()) // "Fri Aug 21 2026"نویسنده یادآوری میکنه که Date سال ۱۹۹۵ در ده روز و با الگوبرداری از java.util.Date نوشته شد — کلاسی که خود جاوا بعداً منسوخش کرد. وب دور همین API رشد کرد، فریمورکها دورش راهحل ساختن و تلهها نامرئی شدن.
دربارهٔ پارس هم میگه اسپک فقط ISO 8601 رو الزامی کرده و بقیهٔ فرمتها به پیادهسازی موتور واگذار شده؛ فرمت فقطتاریخِ YYYY-MM-DD بهعنوان UTC تفسیر میشه ولی بقیهٔ رشتهها محلی، پس دو رشتهای که برای آدم یکسان به نظر میرسن میتونن دوازده ساعت فاصله بدن. بدتر اینکه ورودی نامعتبر خطا نمیده و یه Invalid Date میسازه که بعداً به شکل NaN تو محاسبات یا رشتهٔ ذخیرهشده تو دیتابیس ظاهر میشه.
بخش تایمزون سنگینترین بخشه. Date یه لحظه (میلیثانیه از epoch) رو نگه میداره، ولی بیشتر متدهای روزمره اون لحظه رو به تایمزون محلی ماشین تصویر میکنن؛ قاطیکردن متدهای UTC و محلی همون باگ کلاسیک «یه روز اختلاف» تو گزارشها و فیلترهاست. DST هم لایهٔ بعدیه: بعضی روزهای محلی ۲۳ ساعتن و بعضی ۲۵، و اگه صورتحساب یا rate limit فرض کنه هر روز ۲۴ ساعته، داده بهمرور drift میکنه.
JSON.stringify هم همیشه ISO با UTC میده، پس نیت تایمزون اصلی موقع رفتن به سرویس بعدی گم میشه. قاعدهٔ امن پیشنهادی: لحظهها رو با toISOString() در UTC ذخیره و منتقل کن و هرجا معنای تقویمی لازمه، یه تایمزون صریح IANA بهش بچسبون.
راهحل ساختاری Temporal ـه که مفاهیم رو به تایپهای جدا میشکنه: Temporal.Instant برای نقطهٔ زمانی ماشینی، Temporal.ZonedDateTime برای حساب تقویمی آگاه از تایمزون، و Temporal.PlainDate برای تاریخ بدون تایمزون. فیلدهای تقویمی یکمبنا هستن و عملیاتها بهجای تغییر شیء، مقدار جدید برمیگردونن:
const invoiceDate = Temporal.PlainDate.from('2026-07-21')
const dueDate = invoiceDate.add({ days: 14 })
console.log(invoiceDate.toString()) // 2026-07-21
console.log(dueDate.toString()) // 2026-08-04نویسنده تأکید میکنه که برای کدهای موجود هم راه هست: کتابخونههایی مثل date-fns، dayjs و luxon تابعهای پارس سختگیر دارن که موقع نامنطبقبودن فرمت صریحاً خطا میدن — همون رفتاری که به گفتهٔ او Date باید از روز اول میداشت. همچنین هشدار میده حسابوکتاب با میلیثانیهٔ خام («سی روز جلو») تو گردشکارهای زمان محلی فرضهای نادرست جا میندازه و «یه ماه اضافه کن» با «سی روز اضافه کن» یکی نیست.
نکات کلیدی:
- فرمت YYYY-MM-DD بهعنوان UTC پارس میشه؛ بقیهٔ رشتهها محلی و وابسته به موتور
- ماهها در سازنده صفرمبنا هستن و اشیا تغییرپذیر، پس توابع کمکی ورودی رو بیخبر عوض میکنن
- سرریز روز و ماه بیصدا نرمال میشه؛ برای صورتحساب و انطباق خطرناکه
- JSON.stringify همیشه UTC میده و نیت تایمزون ورودی حفظ نمیشه
- Temporal با جداکردن تایپها، فیلدهای یکمبنا و عملیات غیرجهشدهنده این تلهها رو میبنده




