پیرو لغو شدن قانون تغییر ساعت رسمی کشور در بهار ۱۴۰۱، در مواردی که از تایمزون ایران در اپلیکیشن یا کانتینر استفاده میکنید، نیاز است از بهروز بودنِ پکیجِ مربوط به تبدیلِ تایمزون اطمینان حاصل فرمایید. در صورت بهروز نبودنِ پکیجِ تبدیلِ تایمزون، ممکن است با فرارسیدن فروردین مطابقِ قانونِ پیشین، ساعتِ تایمزون ایران در اپ شما یک ساعت به جلو کشیده شود و برای شما مشکل ایجاد کند.
تایمزون سرویسها و قوانین مربوط به تبدیل زمانِ UTC به هر یک از تایمزونها در سطح کانتینر و اپلیکیشن تنظیم میشوند و برای آپدیت و تغییر آنها نیاز اهست در سطح کانتینر و اپلیکیشن تغییرات مقتضی انجام گردد. این تنظیمات برای اپهای مختلف میتواند متفاوت باشد که در ادامه توضیح بیشتری خواهیم داد. اگر از تایمزون ایران استفاده نمیکنید یا در سطح اپلیکیشن تبدیل تاریخ انجام نمیدهید نگران نباشید؛ چرا که از زمان UTC به طور مستقیم استفاده میکنید و نیازی به تغییر نیست.
در بخش اول مدیریت تایمزون در سطح کانتینر را توضیح میدهیم و در بخش دوم مدیریت تایمزون در سطح کدِ اپلیکیشن را بررسی میکنیم.
۱. مدیریت تایمزون در لینوکس
پکیج tzdata در توزیعهای لینوکسی اطلاعات مربوط به تبدیل تایمزونها را مطابق با قوانین کشورها در اختیار دارد. در داکرایمجها نیز برای تبدیل تایمزون چنین پکیجی وجود دارد و اطلاعات مربوط به چگونگیِ تبدیلِ ساعت از UTC به هر تایمزونی را در اختیار دارد. همچنین تایمزون هر کانتینر میتواند از بقیهی کانتینرها متفاوت تنظیم شود. ممکن است در داکرایمج تایمزون خاصی تنظیم شده باشد یا از طریق متغیرهای محیطی مناسبی برای ایمج (بیشتر ایمجها برای تنظیم تایمزون از متغیر محیطی TZ استفاده میکنند) تنظیم شده باشد.
در صورت استفاده از timezone ایران برای کانتینر (اپ) لازم هست از آپدیت بودن پکیج مربوطه که اکثراً tzdata هست اطمینان حاصل کنید. در حالت کلی در صورت بهروز بودن تگِ ایمج، آخرین نسخه tzdata از قبل روی ایمج شما نصب خواهد بود. در ادامه نحوه بررسی ورژن tzdata و مقایسه آن با changelog پکیج tzdata را بررسی خواهیم کرد.
نصب آخرین ورژن tzdata در داکر ایمج
برای اطمینان از نصب آخرین ورژن tzdata، لازم است خط زیر را در داکر فایل خود اضافه کنید.
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get -y install tzdata |
بررسی ورژن tzdata
برای بررسی ورژن tzdata نصب شده در داکر ایمج خود، از طریق کنسول هم روش اپ خود را انتخاب کنید و در مرحله بعد با انتخاب گزینه “ترمینال” وارد ترمینال شوید. با زدن دستور زیر در ترمینال خود ورژن پکیج tzdata نصب شده به شما نمایش داده خواهد شد.
dpkg -s tzdata | grep -i version |
در نهایت با بررسی changelog پکیج نصب شده خود در Debian Package Tracker میتوانید از نصب بودن ورژن مورد نیاز خود اطمینان حاصل کنید.
اولین patch شامل تغییرات جدید در قانون ساعت رسمی کشور در تاریخ 17 آگوست 2022 منتشر شده است، بدیهی است که ورژن tzdata شما باید در این تاریخ یا بعد از این تاریخ منتشر شده باشد تا شامل آخرین تغییرات مربوط به قانون منسوخ شده باشد.
همچنین برای بررسی کلی changelog پکیج tzdata میتوانید از Changelog Launchpad نیز استفاده کنید.
استفاده از دستور date
روش دیگری که میتواند کمککننده باشد استفاده از دستور date هست. به عنوان مثال دستور زیر را در ترمینال وارد کنید:
export TZ="Asia/Tehran"; date -d '@1679473800' |
عدد 1679473800 ساعت ۱۲:۰۰ تاریخ ۱۴۰۲/۰۱/۰۲ را با فرمت epoch نمایش میدهد. دستور بالا تایمزون را به ایران تغییر داده و زمان را خروجی میدهد. در صورتی که ساعت ۱۳:۰۰ نمایش داده شود نشاندهندهی قدیمی بودن پکیج tzdata است.
در نمونهی بالا روش آپدیت و بررسی درست بودن پکیج tzdata را در یک ایمج با Debian package manager دیدیم. برای ایمجهای دیگر نیز میتوانید روش مشابهی را بررسی کنید و پکیجی که مربوط به تایمزون هست را آپدیت کنید.
توجه کنید داکرایمجهای برپایهی alpine اکثرا پکیج tzdata را ندارند و نتیجتاً ساعت را همواره بر مبنای UTC نمایش میدهند.
۲. بررسی کتابخانههای تبدیل تایمزون در کد
اگر در لایهی اپلیکیشن از کتابخانهای برای تبدیل تایمزون استفاده میکنید خوب است از بهروز بودن قوانین تبدیل آن اطمینان حاصل کنید. بیشتر کتابخانهها (به عنوان مثال کتابخانههای رایج زبان JavaScript و .net از زمان کانتینر استفاده میکنند و با بهروزرسانی پکیج tzdata در سطح کانتینر، در سطح اپلیکیشن نیز قوانین بهروز میشوند) اما ممکن است کتابخانهی مورد استفادهی شما از پکیج tzdata برای تبدیل تایمزون استفاده نکند و با قوانین مورد استفادهی خودش تبدیل را انجام دهد. در چنین شرایطی ممکن است در عین بهروز بودن پکیج tzdata تبدیل ساعت را با قوانین قدیمی انجام دهد. در واقع ساعتی که خود اپلکیشین پس از تبدیل به دست میآورد مستقل از پکیج tzdata میشود. در چنین شرایطی نیاز است متناسب با کتابخانهی مورد استفاده تغییرات مقتضی را در اپلیکیشن اعمال کنید. در بیشتر موارد این تغییر تنها شامل بهروزرسانی کتابخانهی تبدیلِ تایمزونیست که در اپلیکیشن استفاده شده است. پیشنهاد میشود base image را نیز در صورت امکان بهروزرسانی کنید.
به عنوان مثال فرض کنید اپی داریم که از base image با مقدار python:3.11.2-slim و برای تبدیل تایمزون از pytz ورژن 2020.5 استفاده میکند. این اپ که p.py نام دارد پس از اجرا زمان epochی که بالاتر اشاره کردیم را پس از تبدیل به تایمزون ایران چاپ میکند و از برنامه خارج میشود.
داکرفایل آن چنین چیزی است:
FROM python:3.11.2-slim
CMD ["python", "p.py"] |
و کد اپلیکیشن فرضی ما با نام p.py:
|
با اجرای کانتینر و فراخوانی اپ p.py مشاهده میکنیم که خروجی به اشتباه ۱۳:۰۰ خواهد بود درحالیکه ساعت ۱۲:۰۰ خروجی مورد انتظار است.
با توجه به بهروز بودن base image اپ پکیج tzdata بهروز است و دستور export TZ=”Asia/Tehran”; date -d ‘@1679473800’ به درستی ساعت ۱۲:۰۰ را نشان میدهد اما در سطح کد تبدیل به اشتباه انجام میشود. برای اصلاح مشکل، کتابخانهی pytz را بهروزرسانی میکنیم.
داکرفایل جدید مشابه زیر میشود:
|
در ادامه پس از بیلد و اجرای کانتینر مشاهده میکنیم اجرای python p.py نیز به درستی ساعت ۱۲:۰۰ را نمایش میدهد و مشکل برطرف شده است.
نکتهی مهم:
در صورت بهروز نبودن پکیج تبدیل تایمزون اپ شما، اگر از قبل مقادیری برای بعد از ساعت ۲۴ یکم فروردین ۱۴۰۲ (معادل 1679430600 epoch) ذخیره کردهاید، نیاز هست به صورت دستی تغییرات مورد نیاز را انجام دهید چون از قبل با قانون قدیمی آن ساعتها ذخیره شدهاند.
امیدواریم این مستند برای شما مفید بوده باشد. پیشاپیش عید شما مبارک.
2 نظر
سلام. شما یا بقیه دوستان تجربه مشکلات با mssql یا postgres رو ندارن؟ خود محیط container درسته اما mssql داره getdate() مقدار اشتباه نشون میده.
سلام. به طور کلی اگر با آپدیت پکیج tzdata بهروزرسانی مورد نظرتون انجام نشده میتونید آپدیت نسخهی ایمج رو امتحان کنید. با آپدیت نسخهی ایمج در اکثر مواقع قوانین جدید مربوط به تبدیل تایمزون نیز اضافه خواهند شد.
برای postgresql قاعدتاً با آپدیت tzdata باید قوانین جدید اعمال شوند. پس از آپدیت میتونید با دستور
select now() AT TIME ZONE 'Asia/Tehran';
تست کنید که آیا درست شده یا نه. در بعضی از سرویسها اطلاعات پکیج tzdata به صورت لوکال در اپ ذخیره میشود و نیاز هست به صورت دستی آپدیت رو انجام بدید. به طور مثال MySQL برای بحث هندل کردن تبدیل کردن تاریخ ها با تابع convert_tz() اطلاعات مربوط به تایمزونها رو داخل یه تیبل داخلیش ذخیره میکنه. این ینی صرف آپدیت کردن tzdata براش کافی نیست و شما باید اطلاعات مربوط به تایمزونها رو داخل اون تیبل مجدد ایمپورت کنید و حتما دیتابیس رو ریاستارت کنید وگرنه از کش میخونه و تایم غلط برمیگردونه.