有没有办法在Windows操作系统上按代码启用和禁用DST(夏令时)?
我一直在关注下一个link上提到的步骤,但没有成功......
此外,我一直在尝试更改DYNAMIC_TIME_ZONE_INFORMATION
结构的“偏向”属性,它允许我更改日期时间,但不允许我启用或禁用DST ...
有什么方法可以解决这个问题吗?
下一个源代码仅禁用DST,但我需要再次启用...
OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
TOKEN_PRIVILEGES tp;
LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
DYNAMIC_TIME_ZONE_INFORMATION dyTimeZoneInfo;
ZeroMemory(&dyTimeZoneInfo, sizeof(dyTimeZoneInfo));
DWORD tzId = GetDynamicTimeZoneInformation(&dyTimeZoneInfo);
dyTimeZoneInfo.DynamicDaylightTimeDisabled = !dyTimeZoneInfo.DynamicDaylightTimeDisabled;
dyTimeZoneInfo.DaylightBias = 0;
dyTimeZoneInfo.StandardDate.wDay = 0;
dyTimeZoneInfo.StandardDate.wDayOfWeek = 0;
dyTimeZoneInfo.StandardDate.wHour = 0;
dyTimeZoneInfo.StandardDate.wMilliseconds = 0;
dyTimeZoneInfo.StandardDate.wMinute = 0;
dyTimeZoneInfo.StandardDate.wMonth = 0;
dyTimeZoneInfo.StandardDate.wSecond = 0;
dyTimeZoneInfo.StandardDate.wYear = 0;
dyTimeZoneInfo.DaylightDate.wDay = 0;
dyTimeZoneInfo.DaylightDate.wDayOfWeek = 0;
dyTimeZoneInfo.DaylightDate.wHour = 0;
dyTimeZoneInfo.DaylightDate.wMilliseconds = 0;
dyTimeZoneInfo.DaylightDate.wMinute = 0;
dyTimeZoneInfo.DaylightDate.wMonth = 0;
dyTimeZoneInfo.DaylightDate.wSecond = 0;
dyTimeZoneInfo.DaylightDate.wYear = 0;
SetDynamicTimeZoneInformation(&dyTimeZoneInfo);
tp.Privileges[0].Attributes = NULL;
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
CloseHandle(hToken);
我会感激任何帮助。
您的原始代码大多是正确的。我看到的主要问题是:
dyTimeZoneInfo.DynamicDaylightTimeDisabled = !dyTimeZoneInfo.DynamicDaylightTimeDisabled;
这会切换自动DST功能,而其余代码则严格禁用它。而是将其设置为true。
dyTimeZoneInfo.DynamicDaylightTimeDisabled = TRUE;
要重新启用DST,您需要恢复DaylightBias
,DaylightStart
和StandardStart
字段的原始值。 (不要假设DaylightBias
总是-60,至少有一个是-30。)
最好只是恢复整个DYNAMIC_TIME_ZONE_INFORMATION
结构。为此,使用EnumDynamicTimeZoneInformation
函数迭代系统上的所有时区,并选择TimeZoneKeyName
与当前时区匹配的时区。
最后,您可能想要考虑为什么需要这样做。通常不再需要通过此机制禁用DST。这是一项遗留功能。全世界都有适当的时区条目,包括没有DST的区域。如果您只是想在自己的应用程序(可能是系统管理应用程序)中模拟操作系统的设置,那么很好。但是对于大多数其他目的,您不需要操纵此设置。
这个源代码解决了我的问题。
HANDLE hToken;
OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
TOKEN_PRIVILEGES tp;
LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &tp.Privileges[0].Luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
DYNAMIC_TIME_ZONE_INFORMATION dyTimeZoneInfo;
ZeroMemory(&dyTimeZoneInfo, sizeof(dyTimeZoneInfo));
DWORD tzId = GetDynamicTimeZoneInformation(&dyTimeZoneInfo);
dyTimeZoneInfo.DynamicDaylightTimeDisabled = !dyTimeZoneInfo.DynamicDaylightTimeDisabled;
if (dyTimeZoneInfo.DynamicDaylightTimeDisabled)
dyTimeZoneInfo.Bias = dyTimeZoneInfo.StandardBias;
else
dyTimeZoneInfo.Bias = dyTimeZoneInfo.DaylightBias;
SetDynamicTimeZoneInformation(&dyTimeZoneInfo);
tp.Privileges[0].Attributes = NULL;
AdjustTokenPrivileges(hToken, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
CloseHandle(hToken);