2011-07-27 112 views
5

我已經編寫了以下代碼,以編程方式在我的機器上設置時區。如果我使用正確的UTC時間(例如新西蘭標準時間),它會正常工作。如果我使用UTC時間負值,例如Mountain Standard Time,則代碼運行時沒有錯誤,但時區設置爲國際日期行西(-12:00)。以編程方式設置時區僅適用於+ UTC時區

我錯過了什麼嗎?

這裏是我使用的代碼:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct TimeZoneInformation 
{ 
    public int Bias; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
    public string StandardName; 
    public SystemTime StandardDate; 
    public int StandardBias; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 
    public string DaylightName; 
    public SystemTime DaylightDate; 
    public int DaylightBias; 

    public static TimeZoneInformation FromTimeZoneInfo(TimeZoneInfo timeZoneInfo) 
    { 
     var timeZoneInformation = new TimeZoneInformation(); 

     timeZoneInformation.StandardName = timeZoneInfo.StandardName; 
     timeZoneInformation.DaylightName = timeZoneInfo.DaylightName; 

     var timeZoneRegistryPath = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\" + timeZoneInfo.Id; 
     var tzi = (byte[])Microsoft.Win32.Registry.GetValue(timeZoneRegistryPath, "TZI", new byte[] {}); 

     if (tzi == null || tzi.Length != 44) 
     { 
      throw new ArgumentException("Invalid REG_TZI_FORMAT"); 
     } 

     timeZoneInformation.Bias = BitConverter.ToInt32(tzi, 0); 
     timeZoneInformation.StandardBias = BitConverter.ToInt32(tzi, 4); 
     timeZoneInformation.DaylightBias = BitConverter.ToInt32(tzi, 8); 
     timeZoneInformation.StandardDate.Year = BitConverter.ToInt16(tzi, 12); 
     timeZoneInformation.StandardDate.Month = BitConverter.ToInt16(tzi, 14); 
     timeZoneInformation.StandardDate.DayOfWeek = BitConverter.ToInt16(tzi, 0x10); 
     timeZoneInformation.StandardDate.Day = BitConverter.ToInt16(tzi, 0x12); 
     timeZoneInformation.StandardDate.Hour = BitConverter.ToInt16(tzi, 20); 
     timeZoneInformation.StandardDate.Minute = BitConverter.ToInt16(tzi, 0x16); 
     timeZoneInformation.StandardDate.Second = BitConverter.ToInt16(tzi, 0x18); 
     timeZoneInformation.StandardDate.Millisecond = BitConverter.ToInt16(tzi, 0x1a); 
     timeZoneInformation.DaylightDate.Year = BitConverter.ToInt16(tzi, 0x1c); 
     timeZoneInformation.DaylightDate.Month = BitConverter.ToInt16(tzi, 30); 
     timeZoneInformation.DaylightDate.DayOfWeek = BitConverter.ToInt16(tzi, 0x20); 
     timeZoneInformation.DaylightDate.Day = BitConverter.ToInt16(tzi, 0x22); 
     timeZoneInformation.DaylightDate.Hour = BitConverter.ToInt16(tzi, 0x24); 
     timeZoneInformation.DaylightDate.Minute = BitConverter.ToInt16(tzi, 0x26); 
     timeZoneInformation.DaylightDate.Second = BitConverter.ToInt16(tzi, 40); 
     timeZoneInformation.DaylightDate.Millisecond = BitConverter.ToInt16(tzi, 0x2a); 

     return timeZoneInformation; 
    } 
} 

[DllImport("kernel32.dll", SetLastError = true)] 
public static extern bool SetTimeZoneInformation([In] ref TimeZoneInformation timeZoneInformation); 

var t = TimeZoneInformation.FromTimeZoneInfo(TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time")); 
SetTimeZoneInformation(ref t); 
+2

哦,該死的 - 我不小心寫了Bias和StandardBias字段,而不是我的代碼中的整數。 CLR中的長整數是64位,混亂了我的結構佈局。看起來我設法回答我自己的問題。 – Nathanael

+3

您應該將答案作爲答案發布並接受。 –

回答

7

public struct TimeZoneinformation我定義BiasStandardBias作爲long而不是int

Long在CLR中總是一個64位的值,與C++不同,它通常並不總是32位。這使我的結構體積增加了64位,導致本機代碼誤解了它所看到的值。 + UTC時區工作純屬偶然。

我修正了上面的代碼,它成功地設置了時區,如果有人感興趣。