2011-07-27 17 views
5

He escrito el siguiente código para programar zonas horarias en mi máquina. Funciona bien si utilizo una hora UTC positiva, por ejemplo, la hora estándar de Nueva Zelanda. Si utilizo una hora UTC negativa, como Mountain Standard Time, el código se ejecuta sin errores, pero la zona horaria se establece en International Date Line west (-12: 00).Establecer la zona horaria programada solo funciona para las zonas horarias + UTC

¿Echo de menos algo?

Aquí está el código que estoy usando:

[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

Oh maldita sea - Accidentalmente escribí los campos Bias y StandardBias como longs en lugar de enter en mi código. Anhela que el CLR sea de 64bits estropeó el diseño de mi estructura. Parece que logré responder mi propia pregunta. – Nathanael

+3

Debe publicar la respuesta como respuesta y aceptarla. –

Respuesta

7

En public struct TimeZoneinformation he definido Bias y StandardBias como long en lugar de int.

Long en el CLR es siempre un valor de 64 bits, a diferencia de C++, donde generalmente aunque no siempre es de 32bits. Esto aumentó el tamaño de mi estructura en un total de 64 bits y provocó que el código nativo malinterpretara los valores que veía. Fue puramente por accidente que funcionaron las zonas horarias + UTC.

He corregido el código anterior, y establece con éxito la zona horaria si a alguien le interesa.

Cuestiones relacionadas