اصلاح daylight saving time ویندوز تا 90 سال بعد
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: چهار دقیقه

چند سالی هست (از سال 2009) که آپدیت‌های daylight saving time ویندوز شامل حال تنظیمات رسمی ایران نمی‌شود. برای نمونه، همین یکی دو روز قبل بود که ساعت ویندوز به صورت خودکار تغییر کرد؛ درحالیکه باید در انتهای روز 30 شهریور اینکار صورت می‌گرفت.
اطلاعات daylight saving time یا بازه صرفه جویی زمانی ویندوز در دو مدخل رجیستری زیر ثبت می‌شوند:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Iran Standard Time]



تصویر سوم مرتبط است به ویندوزهای ویستا به بعد که مفهوم dynamic daylight saving time در آن‌ها معرفی شده است.
در اینجا یک نمونه اطلاعات زمانی ثبت شده مرتبط با ایران را مشاهده می‌کنید:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Iran Standard Time]
"Display"="(GMT+03:30) Tehran"
"Dlt"="Iran Daylight Time"
"Std"="Iran Standard Time"
"MapID"="-1,72"
"Index"=dword:000000a0
"TZI"=hex:2e,ff,ff,ff,00,00,00,00,c4,ff,ff,ff,00,00,09,00,04,00,03,00,17,00,3b,\
  00,3b,00,00,00,00,00,03,00,02,00,03,00,17,00,3b,00,3b,00,00,00
TZI ایی که در اینجا وجود دارد، دارای یک چنین ساختاری است:
using System.Runtime.InteropServices;

namespace TimeZoneInfo.Core
{
    [StructLayout(LayoutKind.Sequential)]
    public struct TZI
    {
        public int Bias;
        public int StandardBias;
        public int DaylightBias;
        public SystemTime StandardDate;
        public SystemTime DaylightDate;
    }
}
و SystemTime آن نیز به نحو زیر تعریف شده است:
using System;
using System.Runtime.InteropServices;

namespace TimeZoneInfo.Core
{
    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct SystemTime
    {
        public short Year;
        public short Month;
        public short DayOfWeek;
        public short Day;
        public short Hour;
        public short Minute;
        public short Second;
        public short Milliseconds;
    }
}
برای مثال اگر اطلاعات درج شده در TZI به صورت زیر باشد:
2C 01 00 00 00 00 00 00
C4 FF FF FF 00 00 0A 00
00 00 05 00 02 00 00 00
00 00 00 00 00 00 04 00
00 00 01 00 02 00 00 00
00 00 00 00
نمونه رمزگشایی شده آن به نحو ذیل خواهد بود:
(little-endian)   => (big-endian)
  2C 01 00 00     => 00 00 01 2C = 300 Bias
  00 00 00 00     => 00 00 00 00 = 0 Std Bias
  C4 FF FF FF     => FF FF FF C4 = 4294967236 Dlt Bias
( SYSTEM TIME ) StandardDate
  00 00           => 00 00 = Year
  0A 00           => 00 0A = Month
  00 00           => 00 00 = Day of Week
  05 00           => 00 05 = Day
  02 00           => 00 02 = Hour
  00 00           => 00 00 = Minutes
  00 00           => 00 00 = Seconds
  00 00           => 00 00 = Milliseconds
( SYSTEM TIME ) DaylightDate
  00 00           => 00 00 = Year
  04 00           => 00 04 = Month
  00 00           => 00 00 = Day of Week
  01 00           => 00 01 = Day
  02 00           => 00 02 = Hour
  00 00           => 00 00 = Minutes
  00 00           => 00 00 = Seconds
  00 00           => 00 00 = Milliseconds
در ساختار SystemTime متناظر با TZI، فیلد Day دارای مقدار روز در یک ماه نیست. به معنای شماره هفته است. مثلا پنج شنبه (DayOfWeek) هفته سوم (Day) ماه 9 سال 2012.
همچنین Day از یک شروع می‌شود و DayOfWeek از صفر. Year اگر صفر وارد شود به معنای زمان نسبی است و برای سال بعد نیز می‌تواند کاربرد داشته باشد (و عموما صفر تعریف شده است).
بنابراین برای تبدیل DateTime به SystemTime سازگار با TZI به فرمول زیر خواهیم رسید:
        public static SystemTime ToSystemTime(DateTime time)
        {
            var result = new SystemTime
            {
                Year = 0, // سال نسبی وارد می‌شود نه مطلق
                Month = (short)time.Month,
                DayOfWeek = (short)time.DayOfWeek,
                Hour = (short)time.Hour,
                Minute = (short)time.Minute,
                Second = (short)time.Second,
                Milliseconds = (short)time.Millisecond
            };

            int weekdayOfMonth = 1; // شماره هفته است نه شماره روز
            for (int dd = time.Day; dd > 7; dd -= 7)
                weekdayOfMonth++;

            result.Day = (short)weekdayOfMonth;

            return result;
        }
در ادامه نیاز خواهیم داشت تا ساختار TZI سفارشی و بازسازی شده خودمان را بتوانیم به آرایه‌ای از بایت‌ها تبدیل کنیم تا بتوان در همان مدخل رجیستری نوشت. اینکار را توسط متد SerializeByteArray زیر می‌توان انجام داد:
using System;
using System.Runtime.InteropServices;

namespace TimeZoneInfo.Core
{
    public static class ByteUtils
    {
        public static Byte[] SerializeByteArray<T>(T msg) where T : struct
        {
            int objsize = Marshal.SizeOf(typeof(T));
            Byte[] ret = new Byte[objsize];

            IntPtr buff = Marshal.AllocHGlobal(objsize);
            Marshal.StructureToPtr(msg, buff, true);
            Marshal.Copy(buff, ret, 0, objsize);
            Marshal.FreeHGlobal(buff);

            return ret;
        }
    }
}
و اگر اینکار را تا بیش از 90 سال بعد بر اساس تاریخ ایران انجام داده و مداخل رجیستری ویندوز را تکمیل کنیم، خروجی آن فایل reg زیر خواهد بود که به سادگی با کلیک راست و انتخاب گزینه‌ی merge به رجیستری ویندوز اضافه شده و تا چندین سال بعد، مشکل تنظیمات DST را برطرف خواهد کرد:
پس از اعمال تغییرات فوق، نیاز است یکبار ویندوز را ری استارت کنید.
  • #
    ‫۱۲ سال و ۱ ماه قبل، شنبه ۱ مهر ۱۳۹۱، ساعت ۰۱:۱۲
    البته برای ریستارت عجله نکنید، چون 6 ماه وقت دارید :)
    • #
      ‫۱۰ سال و ۶ ماه قبل، سه‌شنبه ۲۷ اسفند ۱۳۹۲، ساعت ۱۷:۴۹
      با سلام
      متاسفانه برنامه شما خروجی اشتباه تولید می‌کند برای مثال زمان تغییر ساعت نوروز 93 ، 2014/March/22 میباشد اما برنامه شما تاریخ 2014/March/21 را تولید میکند.
      با احترام
      محمد حسین عامری

      • #
        ‫۱۰ سال و ۶ ماه قبل، سه‌شنبه ۲۷ اسفند ۱۳۹۲، ساعت ۱۷:۵۴
        خیر. به ساعت آن هم باید دقت کنید. تنظیم شده به 23:59 دقیقه، روز 21 مارس:

  • #
    ‫۱۰ سال و ۶ ماه قبل، شنبه ۲ فروردین ۱۳۹۳، ساعت ۱۸:۲۰
    خیلی ممنون مشکل من رو هم برطرف کرد. برای تهران daylight روی ویندوز ویستا تعریف نشده بود. 
    اگر میشه یه چندتا جمله دیگه به آخر متنتون اضافه کنید که داخل جستجوگرها لینک شما نشون داده بشه. 
    مثلا 
    problem Daylight Saving Time not Defined for Tehran Iran 
    Vista Daylight Saving Time for Teharn 
    Vista Automatically adjust clock for Daylight Saving Time for Teharn 
    Fix Automatically adjust clock for Daylight Saving Time for Teharn 
  • #
    ‫۱۰ سال و ۶ ماه قبل، سه‌شنبه ۵ فروردین ۱۳۹۳، ساعت ۱۷:۱۹
    این patch رو در ویندوز سرور 2003 تست کردم اما برای نوروز 93 درست کار نکرد.
    • #
      ‫۱۰ سال و ۶ ماه قبل، سه‌شنبه ۵ فروردین ۱۳۹۳، ساعت ۱۷:۴۳
      بله. ویندوز XP و ویندوز سرور 2003 دارای dynamic daylight saving time توضیح داده شده در بحث نیستند.
      patch ارائه شده به کمک dynamic daylight saving time سال‌های مختلف را اضافه کرده و این مورد از ویندوز ویستا به بعد به ساختار ویندوز اضافه شده‌است.
      برای ویندوز‌های XP و 2003 از برنامه TZEdit مایکروسافت استفاده کنید (هر سال هم باید یکبار انجام شود؛ برخلاف ویندوزهای ویستا به بعد که با استفاده از روش dynamic معرفی شده فقط یکبار نیاز به تنظیم دارند).
      • #
        ‫۱۰ سال و ۶ ماه قبل، چهارشنبه ۶ فروردین ۱۳۹۳، ساعت ۱۲:۴۹
        درود بر شما
        آیا در ویندوز سرور 2008 و 2012 هم جواب می‌دهد؟
        • #
          ‫۱۰ سال و ۶ ماه قبل، چهارشنبه ۶ فروردین ۱۳۹۳، ساعت ۱۳:۱۳
          بله. فایل win7-8-dst-patch.zip را برای ویندوزهای جدید اجرا کنید.
  • #
    ‫۲ سال و ۵ ماه قبل، پنجشنبه ۱۹ اسفند ۱۴۰۰، ساعت ۱۴:۱۴
    جهت اطلاع!
    لغو قانون «تغییر ساعت»
    ابوترابی عضو کمیسیون امور داخلی کشور و شوراها: با موافقت نمایندگان مجلس قانون «تغییر ساعت» لغو شد. براساس نظر کارشناسان تغییر ساعت توجیه اقتصادی نداشته و مضرات زیادی نیز دارد. طبق قانون از سال ۱۴۰۱ ساعت قدیم و جدید وجود نخواهد داشت.
    پ.ن.
    این طرح قطعی نشده‌است و این موضوع هفته آینده در نوبت دستور کار صحن مجلس قرار دارد.
      • #
        ‫۲ سال و ۵ ماه قبل، پنجشنبه ۲۶ اسفند ۱۴۰۰، ساعت ۱۶:۴۱
        قانون لغو تغییر ساعت شاید به ۱۴۰۱ نرسد؛ سخنگوی شورای نگهبان: مصوبه لغو تغییر ساعت رسمی باید در ابعاد مختلف فنی و انرژی سنجیده شود تا شورا بتواند نظر خود را اعلام کند.
      • #
        ‫۲ سال و ۵ ماه قبل، جمعه ۲۷ اسفند ۱۴۰۰، ساعت ۰۰:۲۸
        ساعت رسمی کشور امسال هم تغییر می‌کند. درویشوند، سرپرست معاونت امور حقوقی دولت: باتوجه به این که مصوبه مجلس در خصوص عدم تغییر ساعت رسمی کشور به تصویب نهایی نرسیده و به قانون تبدیل نشده، دولت موظف به اجرای قانون موجود است و ساعت رسمی کشور در آغاز سال ۱۴۰۱، یک ساعت به جلو کشیده خواهد شد. 
  • #
    ‫۲ سال و ۵ ماه قبل، چهارشنبه ۲۵ اسفند ۱۴۰۰، ساعت ۱۳:۲۰
    وصله‌ای برای غیرفعال کردن تنظیمات تغییر ساعت (daylight saving time) در ویندوز: disable_daylight_saving_time.zip
    • #
      ‫۲ سال و ۵ ماه قبل، پنجشنبه ۲۶ اسفند ۱۴۰۰، ساعت ۱۵:۱۲
      دو تا سوال
      1. این وصله فقط برای غیر فعال کردن تغییر ساعت سال بعد (1401) می‌باشد؟
      2. بعد از اعمال کردن این وصله راهی وجود داره که نیاز به ریستارت کردن سرور نباشه؟
      • #
        ‫۲ سال و ۵ ماه قبل، پنجشنبه ۲۶ اسفند ۱۴۰۰، ساعت ۱۵:۵۳
        - از لحظه‌ی اعمال به بعد
        - خیر.
    • #
      ‫۱ سال و ۴ ماه قبل، دوشنبه ۴ اردیبهشت ۱۴۰۲، ساعت ۱۵:۰۷
      یک نکته‌ی تکمیلی
      دات نت، اطلاعات time zone را از سیستم عامل دریافت می‌کند. برای آزمایش آن، قطعه کد زیر را اجرا کنید:
      var iranStandardTime = TimeZoneInfo.GetSystemTimeZones()
                                             .FirstOrDefault(timeZoneInfo =>
                                                                 timeZoneInfo.StandardName.Contains("Iran",
                                                                  StringComparison.OrdinalIgnoreCase));
      Console.WriteLine(iranStandardTime.BaseUtcOffset); // 03:30:00
      اگر وصله‌ی فوق را اعمال نکرده باشید، خروجی 3:30 را مشاهده نخواهید کرد.
      روش دیگر تنظیم آن هم به صورت زیر است:

  • #
    ‫۲ سال و ۳ ماه قبل، دوشنبه ۲ خرداد ۱۴۰۱، ساعت ۲۲:۱۱

        

    • #
      ‫۱ سال و ۱۱ ماه قبل، سه‌شنبه ۲۹ شهریور ۱۴۰۱، ساعت ۱۴:۴۵
      آخرین تغییر ساعت رسمی کشور

      - ساعت رسمی کشور از ساعت ۲۴ روز چهارشنبه، سی‌ام شهریور، یک ساعت به عقب کشیده خواهد شد.
      - این آخرین تغییر ساعت رسمی کشور است و دیگر تغییر ساعتی در آغاز سال نو نخواهیم داشت.