تاریخ شمسی یا میلادی؟ راهنمای عملی برای محصول فارسی
تاریخ را در دیتابیس چطور ذخیره کنی، در رابط شمسی نشان بدهی و انتخابگر تاریخ خوب بسازی؛ راهنمای ساده برای سازندههای محصول فارسی.
نوشتهٔ تیم محصولهانت · ۶ بهمن ۱۴۰۴

اگر محصول فارسی میسازی، زود به این سؤال میرسی: تاریخ را شمسی نشان بدهم یا میلادی؟ جواب کوتاه این است: در دیتابیس یک چیز ذخیره کن و در رابط چیزی که کاربر به آن عادت دارد. در ادامه قدمبهقدم میگوییم یعنی چه.
اول ببین کاربرت کیست
اگر کاربرهایت ایرانیاند و محصولت کار روزمرهشان را راه میاندازد، مثلاً نوبتدهی، حسابداری ساده یا مدیریت کلاس، هر تاریخی که میبینند باید شمسی باشد. کاربر ایرانی در ذهنش میگوید «۱۵ آبان»، نه یک تاریخ میلادی. اگر میلادی نشانش بدهی، هر بار مجبور است در ذهنش تبدیل کند.
اگر محصولت دوزبانه است، تقویم را به زبان رابط وصل کن. کاربر فارسی را انتخاب کرد، شمسی ببیند. انگلیسی را انتخاب کرد، میلادی. لازم نیست کنار هر تاریخ شمسی، میلادیاش را هم داخل پرانتز بگذاری. این فقط صفحه را شلوغ میکند.
یک استثنا هست: وقتی داده ذاتاً میلادی است. مثلاً ابزاری برای برنامهنویسها که تاریخ کامیت یا لاگ سرور نشان میدهد. آنجا کاربر ایرانی هم معمولاً انتظار میلادی دارد. اگر شک داری، یک گزینه در تنظیمات بگذار.
در دیتابیس فقط یک چیز ذخیره کن
قاعده ساده است: زمان را به شکل UTC ذخیره کن. در Postgres یعنی ستون از نوع timestamptz. تاریخ شمسی را به شکل رشته مثل «1403/05/12» در دیتابیس نریز. مرتبسازی، فیلتر بازهای، گزارش و ارتباط با سرویسهای دیگر با رشتهی شمسی دردسر میشود.
تبدیل به شمسی را فقط در لایهی نمایش انجام بده. اینطوری اگر روزی نسخهی انگلیسی هم خواستی، به داده دست نمیزنی.
یک استثنای کوچک: تاریخهایی که ساعت ندارند، مثل تاریخ تولد یا تاریخ یک قرارداد. اینها را به شکل date (بدون ساعت) ذخیره کن تا با تغییر منطقهی زمانی یک روز جابهجا نشوند.
نمایش شمسی بدون دردسر
در جاوااسکریپت خود مرورگر تقویم شمسی را میشناسد. کافی است Intl.DateTimeFormat را با locale مثل fa-IR-u-ca-persian صدا بزنی و timeZone را Asia/Tehran بگذاری. خروجی هم ارقام فارسی دارد و هم نام ماههای شمسی. برای کارهای بیشتر، مثل جمع و تفریق روز یا گرفتن اول ماه شمسی، از یک کتابخانهی شناختهشده مثل date-fns-jalali کمک بگیر.
خودت فرمول تبدیل ننویس. محاسبهی سال کبیسه در تقویم شمسی ساده نیست و خطای یکروزه معمولاً درست در اسفند و فروردین پیدا میشود، یعنی وقتی کمتر از همیشه انتظارش را داری.
چند نکتهی دیگر که بهتر است بدانی. شش ماه اول سال ۳۱ روزند، پنج ماه بعد ۳۰ روز، و اسفند ۲۹ یا در سال کبیسه ۳۰ روز. هفته در ایران از شنبه شروع میشود و جمعه تعطیل است. ایران دیگر ساعت تابستانی ندارد، پس مطمئن شو دادهی منطقهی زمانی سرور و کتابخانههایت بهروز است.
تاریخهای نزدیک را نسبی بنویس
برای چیزهایی که همین چند روز پیش یا چند روز بعد اتفاق میافتند، تاریخ نسبی خواناتر است: «امروز»، «دیروز»، «۲ ساعت پیش»، «فردا». Intl.RelativeTimeFormat با locale فارسی این را برایت میسازد.
برای تاریخهای دورتر، ماه و روز کافی است: «۱۲ مرداد». اگر سال با سال جاری فرق دارد، سال را هم اضافه کن. در جدولها و گزارشها که کاربر میخواهد مقایسه کند، فرمت کامل و یکسان مثل «۱۴۰۳/۰۵/۱۲» بهتر است.
انتخابگر تاریخ که کاربر را کلافه نکند
تقویم انتخاب تاریخ جایی است که بیشترین خطا را میبینی. چند چیز را چک کن.
تقویم باید راستبهچپ باشد و ستون اول شنبه. نام ماهها شمسی و ارقام فارسی باشد. دکمهی «امروز» داشته باشد. اگر کاربر تاریخ را تایپ میکند، هم ارقام فارسی را قبول کن هم انگلیسی. مثلاً «۱۴۰۳/۵/۱۲» و «1403/5/12» باید هر دو کار کنند.
برای تاریخ تولد، بهجای تقویم ماهانه سه فیلد ساده روز، ماه و سال بگذار. هیچکس نمیخواهد سی سال عقب برود.
قبل از انتشار، انتخابگر را روی روزهای مرزی امتحان کن: اول فروردین، آخر اسفند در سال کبیسه و غیرکبیسه، و آخر شهریور که ماه ۳۱ روزه تمام میشود. اگر تست خودکار داری، همین تاریخها را داخلش بگذار.
جمعبندی سریع
UTC ذخیره کن، شمسی نمایش بده، تبدیل را به کتابخانه بسپار، و روزهای مرزی را تست کن. اگر دربارهی بقیهی جزئیات رابط فارسی هم سؤال داری، /blog/rtl-ux-five-principles را ببین.
محصول فارسی ساختهای؟ /submit را باز کن و رایگان ثبتش کن.