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

标签 c# windows-7 interop timezone

我编写了以下代码以编程方式在我的机器上设置时区。如果我使用正的 UTC 时间,例如新西兰标准时间,它就可以正常工作。如果我使用负 UTC 时间,例如山地标准时间,代码运行时没有错误,但时区设置为国际日期变更线西 (-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);

最佳答案

public struct TimeZoneinformation 中,我将 BiasStandardBias 定义为 long 而不是 int

Long 在 CLR 中始终是 64 位值,这与 C++ 不同,C++ 通常是 32 位值,但并不总是 32 位。这将我的结构的大小总共增加了 64 位,并导致 native 代码误解它看到的值。 +UTC 时区起作用纯属偶然。

我已经更正了上面的代码,如果有人感兴趣的话,它成功地设置了时区。

关于c# - 以编程方式设置时区仅适用于 + UTC 时区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6838433/

相关文章:

C# 解释器。用于 C++ 中的事件形状模型库

c# - 停止 wpf Storyboard 并保留实际值

c++ - Windows 7 蓝牙堆栈和 API 是否支持耳机连接

Windows 7 SCardGetStatusChange 中的 C++ 源代码返回代码 6

java - 使用java时防止windows打开打印对话框

vb.net - 按行 NUMBER 和列 LETTER 获取 Excel 单元格

c# - 基于词频的最大编辑距离和建议

c# - 从 C#/ASP.NET 应用程序将数据插入 SQL Server

c# - 列表查询比 IQueryable 快 20 倍?