win.py (7435B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\dateutil\tz\win.py 2 import datetime 3 import struct 4 from six.moves import winreg 5 from six import text_type 6 try: 7 import ctypes 8 from ctypes import wintypes 9 except ValueError: 10 raise ImportError('Running tzwin on non-Windows system') 11 12 from ._common import tzname_in_python2, _tzinfo 13 from ._common import tzrangebase 14 __all__ = ['tzwin', 'tzwinlocal', 'tzres'] 15 ONEWEEK = datetime.timedelta(7) 16 TZKEYNAMENT = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones' 17 TZKEYNAME9X = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones' 18 TZLOCALKEYNAME = 'SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation' 19 20 def _settzkeyname(): 21 handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) 22 try: 23 winreg.OpenKey(handle, TZKEYNAMENT).Close() 24 TZKEYNAME = TZKEYNAMENT 25 except WindowsError: 26 TZKEYNAME = TZKEYNAME9X 27 28 handle.Close() 29 return TZKEYNAME 30 31 32 TZKEYNAME = _settzkeyname() 33 34 class tzres(object): 35 p_wchar = ctypes.POINTER(wintypes.WCHAR) 36 37 def __init__(self, tzres_loc = 'tzres.dll'): 38 user32 = ctypes.WinDLL('user32') 39 user32.LoadStringW.argtypes = (wintypes.HINSTANCE, 40 wintypes.UINT, 41 wintypes.LPWSTR, 42 ctypes.c_int) 43 self.LoadStringW = user32.LoadStringW 44 self._tzres = ctypes.WinDLL(tzres_loc) 45 self.tzres_loc = tzres_loc 46 47 def load_name(self, offset): 48 resource = self.p_wchar() 49 lpBuffer = ctypes.cast(ctypes.byref(resource), wintypes.LPWSTR) 50 nchar = self.LoadStringW(self._tzres._handle, offset, lpBuffer, 0) 51 return resource[:nchar] 52 53 def name_from_string(self, tzname_str): 54 if not tzname_str.startswith('@'): 55 return tzname_str 56 name_splt = tzname_str.split(',-') 57 try: 58 offset = int(name_splt[1]) 59 except: 60 raise ValueError('Malformed timezone string.') 61 62 return self.load_name(offset) 63 64 65 class tzwinbase(tzrangebase): 66 67 def __init__(self): 68 raise NotImplementedError('tzwinbase is an abstract base class') 69 70 def __eq__(self, other): 71 if not isinstance(other, tzwinbase): 72 return NotImplemented 73 return self._std_offset == other._std_offset and self._dst_offset == other._dst_offset and self._stddayofweek == other._stddayofweek and self._dstdayofweek == other._dstdayofweek and self._stdweeknumber == other._stdweeknumber and self._dstweeknumber == other._dstweeknumber and self._stdhour == other._stdhour and self._dsthour == other._dsthour and self._stdminute == other._stdminute and self._dstminute == other._dstminute and self._std_abbr == other._std_abbr and self._dst_abbr == other._dst_abbr 74 75 @staticmethod 76 def list(): 77 with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: 78 with winreg.OpenKey(handle, TZKEYNAME) as tzkey: 79 result = [ winreg.EnumKey(tzkey, i) for i in range(winreg.QueryInfoKey(tzkey)[0]) ] 80 return result 81 82 def display(self): 83 return self._display 84 85 def transitions(self, year): 86 if not self.hasdst: 87 return None 88 dston = picknthweekday(year, self._dstmonth, self._dstdayofweek, self._dsthour, self._dstminute, self._dstweeknumber) 89 dstoff = picknthweekday(year, self._stdmonth, self._stddayofweek, self._stdhour, self._stdminute, self._stdweeknumber) 90 dstoff -= self._dst_base_offset 91 return (dston, dstoff) 92 93 def _get_hasdst(self): 94 return self._dstmonth != 0 95 96 @property 97 def _dst_base_offset(self): 98 return self._dst_base_offset_ 99 100 101 class tzwin(tzwinbase): 102 103 def __init__(self, name): 104 self._name = name 105 with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: 106 tzkeyname = text_type('{kn}\\{name}').format(kn=TZKEYNAME, name=name) 107 with winreg.OpenKey(handle, tzkeyname) as tzkey: 108 keydict = valuestodict(tzkey) 109 self._std_abbr = keydict['Std'] 110 self._dst_abbr = keydict['Dlt'] 111 self._display = keydict['Display'] 112 tup = struct.unpack('=3l16h', keydict['TZI']) 113 stdoffset = -tup[0] - tup[1] 114 dstoffset = stdoffset - tup[2] 115 self._std_offset = datetime.timedelta(minutes=stdoffset) 116 self._dst_offset = datetime.timedelta(minutes=dstoffset) 117 self._stdmonth, self._stddayofweek, self._stdweeknumber, self._stdhour, self._stdminute = tup[4:9] 118 self._dstmonth, self._dstdayofweek, self._dstweeknumber, self._dsthour, self._dstminute = tup[12:17] 119 self._dst_base_offset_ = self._dst_offset - self._std_offset 120 self.hasdst = self._get_hasdst() 121 122 def __repr__(self): 123 return 'tzwin(%s)' % repr(self._name) 124 125 def __reduce__(self): 126 return (self.__class__, (self._name,)) 127 128 129 class tzwinlocal(tzwinbase): 130 131 def __init__(self): 132 with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: 133 with winreg.OpenKey(handle, TZLOCALKEYNAME) as tzlocalkey: 134 keydict = valuestodict(tzlocalkey) 135 self._std_abbr = keydict['StandardName'] 136 self._dst_abbr = keydict['DaylightName'] 137 try: 138 tzkeyname = text_type('{kn}\\{sn}').format(kn=TZKEYNAME, sn=self._std_abbr) 139 with winreg.OpenKey(handle, tzkeyname) as tzkey: 140 _keydict = valuestodict(tzkey) 141 self._display = _keydict['Display'] 142 except OSError: 143 self._display = None 144 145 stdoffset = -keydict['Bias'] - keydict['StandardBias'] 146 dstoffset = stdoffset - keydict['DaylightBias'] 147 self._std_offset = datetime.timedelta(minutes=stdoffset) 148 self._dst_offset = datetime.timedelta(minutes=dstoffset) 149 tup = struct.unpack('=8h', keydict['StandardStart']) 150 self._stdmonth, self._stdweeknumber, self._stdhour, self._stdminute = tup[1:5] 151 self._stddayofweek = tup[7] 152 tup = struct.unpack('=8h', keydict['DaylightStart']) 153 self._dstmonth, self._dstweeknumber, self._dsthour, self._dstminute = tup[1:5] 154 self._dstdayofweek = tup[7] 155 self._dst_base_offset_ = self._dst_offset - self._std_offset 156 self.hasdst = self._get_hasdst() 157 158 def __repr__(self): 159 return 'tzwinlocal()' 160 161 def __str__(self): 162 return 'tzwinlocal(%s)' % repr(self._std_abbr) 163 164 def __reduce__(self): 165 return (self.__class__, ()) 166 167 168 def picknthweekday(year, month, dayofweek, hour, minute, whichweek): 169 first = datetime.datetime(year, month, 1, hour, minute) 170 weekdayone = first.replace(day=(dayofweek - first.isoweekday()) % 7 + 1) 171 wd = weekdayone + (whichweek - 1) * ONEWEEK 172 if wd.month != month: 173 wd -= ONEWEEK 174 return wd 175 176 177 def valuestodict(key): 178 dout = {} 179 size = winreg.QueryInfoKey(key)[1] 180 tz_res = None 181 for i in range(size): 182 key_name, value, dtype = winreg.EnumValue(key, i) 183 if dtype == winreg.REG_DWORD or dtype == winreg.REG_DWORD_LITTLE_ENDIAN: 184 if value & 2147483648L: 185 value = value - 4294967296L 186 elif dtype == winreg.REG_SZ: 187 if value.startswith('@tzres'): 188 tz_res = tz_res or tzres() 189 value = tz_res.name_from_string(value) 190 value = value.rstrip('\x00') 191 dout[key_name] = value 192 193 return dout