چند سالی هست (از سال 2009) که آپدیتهای daylight saving time ویندوز شامل حال تنظیمات رسمی ایران نمیشود. برای نمونه، همین یکی دو روز قبل بود که ساعت ویندوز به صورت خودکار تغییر کرد؛ درحالیکه باید در انتهای روز 30 شهریور اینکار صورت میگرفت.
اطلاعات daylight saving time یا بازه صرفه جویی زمانی ویندوز در دو مدخل رجیستری زیر ثبت میشوند:
تصویر سوم مرتبط است به ویندوزهای ویستا به بعد که مفهوم dynamic daylight saving time در آنها معرفی شده است.
در اینجا یک نمونه اطلاعات زمانی ثبت شده مرتبط با ایران را مشاهده میکنید:
TZI ایی که در اینجا وجود دارد، دارای یک چنین ساختاری است:
و SystemTime آن نیز به نحو زیر تعریف شده است:
برای مثال اگر اطلاعات درج شده در TZI به صورت زیر باشد:
نمونه رمزگشایی شده آن به نحو ذیل خواهد بود:
در ساختار SystemTime متناظر با TZI، فیلد Day دارای مقدار روز در یک ماه نیست. به معنای شماره هفته است. مثلا پنج شنبه (DayOfWeek) هفته سوم (Day) ماه 9 سال 2012.
همچنین Day از یک شروع میشود و DayOfWeek از صفر. Year اگر صفر وارد شود به معنای زمان نسبی است و برای سال بعد نیز میتواند کاربرد داشته باشد (و عموما صفر تعریف شده است).
بنابراین برای تبدیل DateTime به SystemTime سازگار با TZI به فرمول زیر خواهیم رسید:
در ادامه نیاز خواهیم داشت تا ساختار TZI سفارشی و بازسازی شده خودمان را بتوانیم به آرایهای از بایتها تبدیل کنیم تا بتوان در همان مدخل رجیستری نوشت. اینکار را توسط متد SerializeByteArray زیر میتوان انجام داد:
و اگر اینکار را تا بیش از 90 سال بعد بر اساس تاریخ ایران انجام داده و مداخل رجیستری ویندوز را تکمیل کنیم، خروجی آن فایل reg زیر خواهد بود که به سادگی با کلیک راست و انتخاب گزینهی merge به رجیستری ویندوز اضافه شده و تا چندین سال بعد، مشکل تنظیمات DST را برطرف خواهد کرد:
پس از اعمال تغییرات فوق، نیاز است یکبار ویندوز را ری استارت کنید.
اطلاعات 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
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; } }
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; } }
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
همچنین 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; }
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; } } }
پس از اعمال تغییرات فوق، نیاز است یکبار ویندوز را ری استارت کنید.