以编程方式设置时区仅适用于+ UTC时区

Nat*_*ael 5 c# timezone interop windows-7

我编写了以下代码,以编程方式在我的机器上设置时区.如果我使用正的UTC时间,例如新西兰标准时间,它可以正常工作.如果我使用负的UTC时间,例如Mountain Standard Time,则代码运行时没有错误,但时区设置为International Date Line west(-12:00).

我错过了什么?

这是我正在使用的代码:

[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);
Run Code Online (Sandbox Code Playgroud)

Nat*_*ael 7

public struct TimeZoneinformation我定义BiasStandardBias作为long代替int.

LongCLR中的值总是64位,与C++不同,它通常不是32位.这使我的结构的大小增加了总共64位,并导致本机代码误解了它看到的值.+ UTC时区的工作原理纯属偶然.

我已经纠正了上面的代码,如果有人感兴趣,它会成功设置时区.