如何获取各时区专属参数以调用win32api.SetTimeZoneInformation()
获取全时区
SetTimeZoneInformation参数的可行方法 要生成所有时区的SetTimeZoneInformation参数表,有两种最可靠的方案,均基于Windows系统原生数据,避免手动维护的误差:
1. 读取Windows时区注册表项
Windows系统将所有时区的完整信息存储在注册表路径HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones下,每个子项对应一个时区,可直接解析出SetTimeZoneInformation需要的参数。
关键映射关系
Bias/StandardBias/DaylightBias:从子项的TZI二进制值中解析(该二进制结构与TIME_ZONE_INFORMATION结构体完全对应)StandardName/DaylightName:对应子项的Std和Dlt字符串值StandardDate/DaylightDate:从TZI二进制值中解析出SYSTEMTIME结构,转换为你需要的元组格式
Python示例代码
import win32api import win32con import struct # 打开时区注册表根键 tz_root = win32api.RegOpenKeyEx(win32con.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones", 0, win32con.KEY_READ) index = 0 while True: try: tz_name, _, _ = win32api.RegEnumKeyEx(tz_root, index) index += 1 # 打开当前时区子项 tz_key = win32api.RegOpenKeyEx(tz_root, tz_name, 0, win32con.KEY_READ) # 解析TZI二进制数据 tzi_data, _ = win32api.RegQueryValueEx(tz_key, "TZI") bias = struct.unpack("<l", tzi_data[0:4])[0] standard_bias = struct.unpack("<l", tzi_data[4:8])[0] daylight_bias = struct.unpack("<l", tzi_data[8:12])[0] # 解析StandardDate std_st = struct.unpack("<8H", tzi_data[12:28]) standard_date = (std_st[0], std_st[1], std_st[2], std_st[3], std_st[4], std_st[5], std_st[6], std_st[7]) # 解析DaylightDate dlt_st = struct.unpack("<8H", tzi_data[28:44]) daylight_date = (dlt_st[0], dlt_st[1], dlt_st[2], dlt_st[3], dlt_st[4], dlt_st[5], dlt_st[6], dlt_st[7]) # 读取时区名称 standard_name, _ = win32api.RegQueryValueEx(tz_key, "Std") daylight_name, _ = win32api.RegQueryValueEx(tz_key, "Dlt") # 组装成SetTimeZoneInformation所需的元组 tzi_tuple = (bias, standard_name, standard_date, standard_bias, daylight_name, daylight_date, daylight_bias) print(f"时区: {tz_name}") print(f"参数元组: {tzi_tuple}\n") win32api.RegCloseKey(tz_key) except win32api.error: break win32api.RegCloseKey(tz_root)
2. 调用EnumDynamicTimeZoneInformation API
该API是Windows提供的原生接口,可枚举系统中所有动态时区(包含历史夏令时规则等完整信息),返回的DYNAMIC_TIME_ZONE_INFORMATION结构体可直接转换为SetTimeZoneInformation需要的参数格式。
Python示例代码(使用ctypes)
import ctypes from ctypes import wintypes # 定义SYSTEMTIME结构体 class SYSTEMTIME(ctypes.Structure): _fields_ = [ ("wYear", wintypes.WORD), ("wMonth", wintypes.WORD), ("wDayOfWeek", wintypes.WORD), ("wDay", wintypes.WORD), ("wHour", wintypes.WORD), ("wMinute", wintypes.WORD), ("wSecond", wintypes.WORD), ("wMilliseconds", wintypes.WORD) ] # 定义DYNAMIC_TIME_ZONE_INFORMATION结构体 class DYNAMIC_TIME_ZONE_INFORMATION(ctypes.Structure): _fields_ = [ ("Bias", wintypes.LONG), ("StandardName", wintypes.WCHAR * 32), ("StandardDate", SYSTEMTIME), ("StandardBias", wintypes.LONG), ("DaylightName", wintypes.WCHAR * 32), ("DaylightDate", SYSTEMTIME), ("DaylightBias", wintypes.LONG), ("TimeZoneKeyName", wintypes.WCHAR * 128), ("DynamicDaylightTimeDisabled", wintypes.BOOL) ] # 加载kernel32并调用API kernel32 = ctypes.WinDLL("kernel32", use_last_error=True) EnumDynamicTimeZoneInformation = kernel32.EnumDynamicTimeZoneInformation EnumDynamicTimeZoneInformation.argtypes = [wintypes.DWORD, ctypes.POINTER(DYNAMIC_TIME_ZONE_INFORMATION)] EnumDynamicTimeZoneInformation.restype = wintypes.DWORD index = 0 while True: dtzi = DYNAMIC_TIME_ZONE_INFORMATION() result = EnumDynamicTimeZoneInformation(index, ctypes.byref(dtzi)) if result != 0: break # 转换为SetTimeZoneInformation所需元组 standard_date = ( dtzi.StandardDate.wYear, dtzi.StandardDate.wMonth, dtzi.StandardDate.wDayOfWeek, dtzi.StandardDate.wDay, dtzi.StandardDate.wHour, dtzi.StandardDate.wMinute, dtzi.StandardDate.wSecond, dtzi.StandardDate.wMilliseconds ) daylight_date = ( dtzi.DaylightDate.wYear, dtzi.DaylightDate.wMonth, dtzi.DaylightDate.wDayOfWeek, dtzi.DaylightDate.wDay, dtzi.DaylightDate.wHour, dtzi.DaylightDate.wMinute, dtzi.DaylightDate.wSecond, dtzi.DaylightDate.wMilliseconds ) tzi_tuple = ( dtzi.Bias, dtzi.StandardName, standard_date, dtzi.StandardBias, dtzi.DaylightName, daylight_date, dtzi.DaylightBias ) print(f"时区: {dtzi.TimeZoneKeyName}") print(f"参数元组: {tzi_tuple}\n") index += 1
注意事项
- 无夏令时的时区,
DaylightName可能为空字符串,StandardDate和DaylightDate的year字段会设为0,不影响SetTimeZoneInformation的调用。 - 两种方案均直接获取系统原生数据,与时区规则完全同步,无需手动维护参数表。
内容的提问来源于stack exchange,提问作者School of Iris
相关产品推荐
相关产品推荐

