C#修改Windows时区

1. 修改时区的Windows API

// 针对于旧Windows系统,如Windows XP
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetTimeZoneInformation(ref TimeZoneInformation lpTimeZoneInformation);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool SetTimeZoneInformation(ref TimeZoneInformation lpTimeZoneInformation);

// 针对于新Windows系统,如Windows 7, Windows8, Windows10
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetDynamicTimeZoneInformation(ref DynamicTimeZoneInformation lpDynamicTimeZoneInformation);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool SetDynamicTimeZoneInformation(ref DynamicTimeZoneInformation lpDynamicTimeZoneInformation);

2. 相关结构struct类型

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct TimeZoneInformation
{
    [MarshalAs(UnmanagedType.I4)]
    internal int bias; // 以分钟为单位
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
    internal string standardName; // 标准时间的名称
    internal SystemTime standardDate;
    [MarshalAs(UnmanagedType.I4)]
    internal int standardBias; // 标准偏移
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
    internal string daylightName; // 夏令时的名称
    internal SystemTime daylightDate;
    [MarshalAs(UnmanagedType.I4)]
    internal int daylightBias; // 夏令时偏移
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct DynamicTimeZoneInformation
{
    [MarshalAs(UnmanagedType.I4)]
    internal int bias; // 偏移,以分钟为单位
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
    internal string standardName; // 标准时间的名称
    internal SystemTime standardDate;
    [MarshalAs(UnmanagedType.I4)]
    internal int standardBias; // 标准偏移
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
    internal string daylightName; // 夏令时的名称
    internal SystemTime daylightDate;
    [MarshalAs(UnmanagedType.I4)]
    internal int daylightBias; // 夏令时偏移
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x80)]
    internal string timeZoneKeyName; // 时区名
    [MarshalAs(UnmanagedType.Bool)]
    internal bool dynamicDaylightTimeDisabled; // 是否自动调整时钟的夏令时
}

[StructLayout(LayoutKind.Sequential)]
struct SystemTime
{
    [MarshalAs(UnmanagedType.U2)]
    internal ushort year; // 年
    [MarshalAs(UnmanagedType.U2)]
    internal ushort month; // 月
    [MarshalAs(UnmanagedType.U2)]
    internal ushort dayOfWeek; // 星期
    [MarshalAs(UnmanagedType.U2)]
    internal ushort day; // 日
    [MarshalAs(UnmanagedType.U2)]
    internal ushort hour; // 时
    [MarshalAs(UnmanagedType.U2)]
    internal ushort minute; // 分
    [MarshalAs(UnmanagedType.U2)]
    internal ushort second; // 秒
    [MarshalAs(UnmanagedType.U2)]
    internal ushort milliseconds; // 毫秒
}

3. 调用Windows API实现时区的获取与修改

/// 
/// 获取本地时区
/// 
/// 
public string getLocalTimeZone()
{
    // 检测当前系统是否为旧系统
    if (IsOldOsVersion())
    {
        TimeZoneInformation tzi = new TimeZoneInformation();
        GetTimeZoneInformation(ref tzi);
        return TimeZoneInfo2CustomString(tzi);
    }
    DynamicTimeZoneInformation dtzi = new DynamicTimeZoneInformation();
    GetDynamicTimeZoneInformation(ref dtzi);
    return DynamicTimeZoneInfo2CustomString(dtzi);
}

/// 
/// 设置本地时区
/// 参数取值"China Standard Time",即可设置为中国时区
/// 
/// 
/// 
public bool setLocalTimeZone(string timeZoneName_en)
{
    if (grantPrivilege(SE_TIME_ZONE_NAME))
    {
        DynamicTimeZoneInformation dtzi = timeZoneName2DynamicTimeZoneInformation(timeZoneName_en);
        bool success = false;
        // 检测当前系统是否为旧系统
        if (IsOldOsVersion())
        {
            TimeZoneInformation tzi = DynamicTimeZoneInformation2TimeZoneInformation(dtzi);
            success = SetTimeZoneInformation(ref tzi);
        }
        else
        {
            success = SetDynamicTimeZoneInformation(ref dtzi);
        }
        if (success)
        {
            TimeZoneInfo.ClearCachedData();  // 清除缓存
        }
        if (!revokePrivilege(SE_TIME_ZONE_NAME))
        {
            // 撤权失败
        }
        return success;
    }
    // 授权失败
    return false;
}

/// 
/// 将TimeZoneInformation转换为自定义string
/// 
/// 
/// 
private string TimeZoneInfo2CustomString(TimeZoneInformation tzi)
{
    return tzi.standardName + "(" + tzi.bias + ")";
}

/// 
/// 将DynamicTimeZoneInformation转换为自定义string
/// 
/// 
/// 
private string DynamicTimeZoneInfo2CustomString(DynamicTimeZoneInformation dtzi)
{
    return dtzi.standardName + "(" + dtzi.bias + ")";
}

/// 
/// 根据时区名获取对应的DynamicTimeZoneInformation
/// 
/// 
/// 
private DynamicTimeZoneInformation timeZoneName2DynamicTimeZoneInformation(string timeZoneName)
{
    TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);

    DynamicTimeZoneInformation dtzi = new DynamicTimeZoneInformation();
    dtzi.standardName = timeZoneInfo.StandardName;
    dtzi.standardDate = new SystemTime();
    dtzi.daylightName = timeZoneInfo.DaylightName;
    dtzi.daylightDate = new SystemTime();
    dtzi.timeZoneKeyName = timeZoneInfo.Id;
    dtzi.dynamicDaylightTimeDisabled = false;
    dtzi.bias = -Convert.ToInt32(timeZoneInfo.BaseUtcOffset.TotalMinutes);
    return dtzi;
}

/// 
/// 将DynamicTimeZoneInformation转换为TimeZoneInformation
/// 
/// 
/// 
private TimeZoneInformation DynamicTimeZoneInformation2TimeZoneInformation(DynamicTimeZoneInformation dtzi)
{
    return new TimeZoneInformation
    {
        bias = dtzi.bias,
        standardName = dtzi.standardName,
        standardDate = dtzi.standardDate,
        standardBias = dtzi.standardBias,
        daylightName = dtzi.daylightName,
        daylightDate = dtzi.daylightDate,
        daylightBias = dtzi.daylightBias
    };
}

/// 
/// 判断Windows系统是否为旧版本
/// 
/// 
private bool IsOldOsVersion()
{
    OperatingSystem os = Environment.OSVersion;
    return os.Platform != PlatformID.Win32NT || os.Version.Major < 6;
}

4. 注意事项:
① 上述代码中的grantPrivilege(SE_TIME_ZONE_NAME)和revokePrivilege(SE_TIME_ZONE_NAME)用于授予/撤销进程修改时区的权限,这里没有给出具体的代码;
② 可以参考子丰的博文:点击打开链接
③ 也可以直接下载代码:点击打开链接

你可能感兴趣的:(程序)