مقدمه
لحظاتی مانده به بامداد ۲ فروردین ۱۴۰۲، در حال کار کردن با کامپیوتر یا گوشیهوشمند خودتان هستید و ناگهان شگفتزده میشوید. تلاش برای رفتن به سایت Time بیفایده بوده و عملکرد رمزسازهای OTP نیز با اختلال همراه شده است. برعکس، شاید شما هم جزو چند درصد افراد خوششانس بودهاید و متوجه تغییر یا اختلالی نمیشوید. اینها قسمتی از اتفاقات ناخوشایند بامداد روز گذشته بود. بنابراین تصمیم گرفتم راهحل مشکلات ناشی از لغو قانون ساعت تابستانی را تا حد امکان مستندسازی کنم.
لغو ساعت تابستانی و گوشیهای هوشمند قدیمی
از زمان آخرین آپدیت گوشی اندرویدیتان بیشتر از ۵ سال گذشته است؟ خوشبختانه هنوز جای امیدواری وجود دارد! سیستمعامل اندروید اطلاعات منطقههای زمانی را در فایلی به نام tzdata در مسیر /system/usr/share/zoneinfo ذخیره میکند. نهاد IANA، پایگاهداده منطقههای زمانی را بر اساس تغییرات قوانین زمان، بروزرسانی و در اختیار همگان قرار میدهد. این تغییرات در نهایت توسط شرکت سازنده بر روی گوشی شما اعمال میشود، اما هنگامی که پشتیبانی از گوشی شما به پایان رسیده باشد اوضاع کمی متفاوت است و خودتان باید دستبهکار شوید.
آموزش پیشِرو بر روی نسخههای 6.0.1 و 4.4.4 اندروید امتحان شده است، اما از لحاظ تئوری و به دلیل یکسان بودن ساختار فایل tzdata در نسخههای 4.x تا 6.x اندروید نباید مشکلی در اجرای آن وجود داشته باشد. همچنین ساختار اطلاعات منطقههای زمانی در اندروید 7.x به بعد دچار تغییراتی شده است، بنابراین نمیتوانم کارکرد درست این آموزش در نسخههای بعد از 7.x را تأیید یا رد کنم.
سلب مسئولیت
پیش از شروع، اگر تجربه قبلی از توسعه اندروید ندارید، توصیه میکنم از انجام آن خودداری کنید. زیرا احتمال Soft Brick یا حتی Hard Brick شدن گوشی شما وجود دارد. پس مسئولیت اینکار کاملاً به عهده شماست.
آمادهسازی محیط
برای شروع، به دسترسی روت نیاز داریم. در صورت استفاده از یک کاستوم ریکاوری مانند TWRP، با قابلیت خواندن و نوشتن بر روی فایلسیستم و عدم دسترسی روت در سیستمعامل اندروید، مانعی جهت انجام این روش وجود ندارد.
در ادامه از یک توزیع مبتنی بر Debian جهت اجرای دستورات استفاده شده است، اما استفاده از توزیعهای دیگر نیز مانعی نداشته و روش انجام کار یکسان است.
ابتدا نصب بودن jdk بر روی کامپیوتر خود را با استفاده از دستور javac -version بررسی کنید.
| |
سپس نصب بودن ابزار zic را با استفاده از دستور which zic بررسی کنید. اگر خروجی دستور چیزی مانند: /usr/sbin/zic بود میتوانید قسمت بعدی را نادیده بگیرید، در غیراینصورت نیاز به کامپایل کردن ابزار zic داریم.
کامپایل کردن ابزار zic
نصب بودن gcc و make را بر روی کامپیوتر خود بررسی کنید.
| |
سپس یک نسخه قدیمی از tzcode{version}.tar.gz را دانلود کنید. برای مثال در ادامه از نسخه 2016b استفاده کردهایم. دلیل آن نیز سازگاری با نسخههای قدیمی اندروید است.
پس از دانلود نیاز به استخراج و در نهایت کامپایل zic داریم.
مراحل کامل را میتوانید از طریق دستورات زیر انجام دهید:
| |
در صورت اجرای موفقیتآمیز دستور make، یک فایل اجرایی با نام zic خواهید داشت. سپس در Home Directory خود دایرکتوری جدیدی با نام newtz ساخته و فایل اجرایی zic را به آنجا منتقل کنید:
| |
جهت فراخوانی ابزار zic در مرحله بعد باید به شکل زیر عمل کنید:
| |
کامپایل کردن پایگاهداده منطقههای زمانی
دریافت آخرین نسخه پایگاهداده منطقههای زمانی
ابتدا آخرین نسخه فایل tzdata{version}.tar.gz را از اینجا دانلود کنید. آخرین نسخه به هنگام نوشتن این پست، 2022g است.
در Home Directory خود یک دایرکتوری جدید با نام newtz ساخته و فایل دانلود شده را در آنجا استخراج کنید.
| |
کامپایل کردن منطقههای زمانی
حال به قسمت کامپایل منطقههای زمانی با کمک ابزار zic میرسیم. فراموش نکنید که باید در دایرکتوری newtz باشید. سپس به شکل زیر عمل کنید:
| |
در صورت اجرای موفقیتآمیز دستور zic، یک دایرکتوری با نام data حاوی منطقههای زمانی کامپایل شده به شکل زیر خواهید داشت:

گردآوری فایل tzdata
دانلود و کامپایل ZoneCompactor
جهت تبدیل دایرکتوری data به یک فایل tzdata نیاز به برنامهی جاوایی ZoneCompactor.java داریم. بهمانند قبل، پیش از اجرای دستورات باید در دایرکتوری newtz باشید.
نحوه دانلود و کامپایل ZoneCompactor.java به شکل زیر است:
| |
ساخت فایل setup
پیش از اجرای ZoneCompactor نیاز به مشخص کردن منطقههای زمانی موجود در فایل tzdata داریم. تایپ دستی این لیست کاری بیهوده است، پس اسکریپت پایتونی مربوط به این بخش را بازنویسی کردهام تا با python3 سازگار شده و به صورت کاملاً خودکار یک لیست حاوی منطقههای زمانی برای شما بسازد. با یک ویرایشگر متنی مانند vim در دایرکتوری newtz فایلی با نام writeSetupFile.py ساخته و اسکریپت زیر را در آن جایگذاری کنید:
| |
| |
سپس آن را اجرا کنید:
| |
در صورت اجرای موفقیت آمیز اسکریپت، یک فایل خروجی حاوی اسم منطقههای زمانی با نام setup خواهید داشت.
مرحله نهایی و ساخت tzdata
در نهایت نوبت به اجرای ZoneCompactor و گردآوری فایل tzdata میرسد. نحوه فراخوانی ZoneCompactor به شکل زیر است:
| |
و پارامترهای آن به این ترتیب هستند:
<setup file>: فایل خروجی مرحله ساخت فایل setup
<data directory>: آدرس دایرکتوری ساخته شده در مرحله کامپایل پایگاهداده منطقههای زمانی
<zone.tab file>: فایل zone.tab که در آرشیو tzdata قرار دارد
<output directory>: آدرس دایرکتوری خروجی فایل tzdata
<tzdata version>: نسخه فعلی پایگاهداده منطقههای زمانی که فرمت آن باید شبیه به tzdata{current_version} باشد. آخرین نسخه در زمان نوشتن این پست tzdata2022g است.
حال که کاربرد هر یک از پارامترها را متوجه شدیم آن را اجرا میکنیم، فراموش نکنید که پیش از اجرا، در دایرکتوری newtz یک دایرکتوری جدید به نام output نیز بسازید:
| |
در صورت موفقیتآمیز بودن اجرا، فایل tzdata درون دایرکتوری output قابل دسترس است.
انتقال tzdata به گوشی
جهت انتقال و جایگزینی فایل جدید با فایل قدیمی راههای متعددی وجود دارد، در صورت داشتن دسترسی روت در سیستمعامل اندروید میتوانید از یک Root Explorer استفاده کنید یا از طریق adb و دستور adb shell آن را جایگزین کنید. پیشنهاد میکنم این کار را از طریق بوت کردن یک کاستوم ریکاوری مانند TWRP و دستور adb shell انجام دهید. در ادامه نیز همین روش را پیش خواهیم برد.
برای شروع لازم است تا گوشی خودتان را در حالت ریکاوری بوت کنید. پس از آن گوشی را با کمک کابل به کامپیوتر خود متصل کنید.
در صورت نصب نبودن adb، میتوانید با استفاده از دستور زیر آن را نصب کنید:
| |
سپس با استفاده از دستور adb devices، درست شناسایی شدن گوشی خود توسط کامپیوتر را بررسی کرده و در ادامه با استفاده از دستور adb shell به شِل گوشی خود دسترسی پیدا کنید.
Mount بودن فایلسیستم را با استفاده از دستور df -h بررسی کرده و در صورت Mount نبودن دستور زیر را اجرا کنید:
| |
حال در یک تَب ترمینال دیگر با استفاده از دستور adb push، فایل tzdata ساخته شده را به حافظه داخلی گوشی خود انتقال دهید. توجه داشته باشید که ممکن است مسیر حافظه داخلی گوشی شما با مسیر استفاده شده در این آموزش، متفاوت باشد!
| |
به شِل گوشی برگشته و دستورات زیر را اجرا کنید:
| |
حال با وارد کردن دستور reboot در شِل گوشی، از حالت ریکاوری خارج شوید. پس از راهاندازی مجدد و بوت شدن، به تنظیمات زمان و تاریخ گوشی خود رفته و خودکار بودن منطقه زمانی و تاریخوساعت را بررسی کنید. اگر در حالت خودکار، منطقه زمانی دستگاه نمایانگر Iran Standard Time باشد، فرآیند جایگزینی و بروزرسانی با موفقیت انجام شده است.

اشکال یابی
در صورتی که پس از اعمال تغییرات تازه، تمام منطقههای زمانی نمایانگر زمان +00:00 هستند و عملکرد گوشی شما در مواردی مانند شناسایی سیمکارت و شبکه دچار اختلال شده، میتوانید راههای زیر را امتحان کنید:
دریافت فایل از پیش گردآوری شده tzdata
ابتدا فایل tzdata حاوی آخرین تغییرات منطقههای زمانی را از اینجا دریافت کنید. سپس آموزش را از قسمت انتقال tzdata به گوشی ادامه دهید.
چک کردن نسخه zic
آیا از ابزار zic درون سیستمعامل خود استفاده میکنید؟ این احتمال وجود دارد که ابزار zic سیستمعامل شما برای نسخه اندرویدتان بیش از اندازه جدید باشد. برای مثال نسخه 2.35 از ابزار zic که به صورت پیشفرض در Ubuntu 22.04 LTS وجود دارد، باعث ایجاد مشکل در برخی از گوشیهای قدیمی شرکت Xiaomi که MIUI 10 را اجرا میکنند، میشود.
با اجرای دستور zic --version میتوانید نسخه فعلی ابزار zic را مشاهده کنید. اگر نسخه نمایان شده بزرگتر از 2.31 بود، میتوانید آموزش را با یک نسخه قدیمیتر نیز امتحان کنید. برای دسترسی به نسخههای قدیمیتر به دو شکل میتوان عمل کرد:
۱- کامپایل کردن یک نسخه قدیمی از ابزار zic
۲- استخراج ابزار zic از پکیجهای قدیمی libc
در صورت استفاده از یک توزیع مبتنی بر Debian مانند Ubuntu، بهتر است از روش دوم استفاده کنید. ابتدا نسخههای قدیمی پکیج libc را از اینجا پیدا کرده و پکیج آن را مطابق با معماری پردازنده کامپیوتر خود دانلود کنید. برای مثال روند انجام این کار در یک کامپیوتر با پردازنده ۶۴بیتی و نسخه 2.31 از پکیج libc به شکل زیر است:
(پیش از شروع دایرکتوری خود را به newtz تغییر دهید)
| |
حال یک نسخه قابلاجرا از ابزار zic در دایرکتوری newtz خواهید داشت. پس از آن، آموزش را از قسمت کامپایل کردن منطقههای زمانی ادامه دهید و توجه کنید که باید دستور این قسمت را به شکل زیر فراخوانی کرده تا از ابزار zic موجود در دایرکتوری newtz جهت کامپایل منطقههای زمانی استفاده شود:
| |
پیش از اجرای دستور فوق بهتر است تا دایرکتوری data را حذف کنید.
بازگردانی تغییرات اعمال شده
در صورت موفقیتآمیز نبودن هیچیک راهحلهای مطرح شده، باید فایل قدیمی tzdata را بازگردانی کنید. این به معنای سازگار نبودن آموزش با نسخه اندروید گوشی شما یا استفاده شرکت سازنده دستگاه از روشهای دیگر جهت ایجاد tzdata میباشد.
جهت بازگردانی فایل tzdata قدیمی، گوشی خود را مجدداً در حالت ریکاوری قرار داده و آن را با کمک کابل به کامپیوتر خود متصل کنید. با استفاده از دستور adb shell به شِل گوشی خود دسترسی پیدا کنید. سپس Mount بودن فایلسیستم را بررسی کرده و دستورات زیر را اجرا کنید:
| |
سخن پایانی
این پست بهمرور زمان و در مواجهه با چالشهای تازه یا بهبود راهحلها، بهروزرسانی خواهد شد.