3752dffac8898555ad2f860e3bc3b178c3927b69
[sdc/sdc-distribution-client.git] /
1 try:
2     import _winreg as winreg
3 except ImportError:
4     try:
5         import winreg
6     except ImportError:
7         winreg = None
8
9 from babel.core import get_global
10 import pytz
11
12
13 # When building the cldr data on windows this module gets imported.
14 # Because at that point there is no global.dat yet this call will
15 # fail.  We want to catch it down in that case then and just assume
16 # the mapping was empty.
17 try:
18     tz_names = get_global('windows_zone_mapping')
19 except RuntimeError:
20     tz_names = {}
21
22
23 def valuestodict(key):
24     """Convert a registry key's values to a dictionary."""
25     dict = {}
26     size = winreg.QueryInfoKey(key)[1]
27     for i in range(size):
28         data = winreg.EnumValue(key, i)
29         dict[data[0]] = data[1]
30     return dict
31
32
33 def get_localzone_name():
34     # Windows is special. It has unique time zone names (in several
35     # meanings of the word) available, but unfortunately, they can be
36     # translated to the language of the operating system, so we need to
37     # do a backwards lookup, by going through all time zones and see which
38     # one matches.
39     handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
40
41     TZLOCALKEYNAME = r'SYSTEM\CurrentControlSet\Control\TimeZoneInformation'
42     localtz = winreg.OpenKey(handle, TZLOCALKEYNAME)
43     keyvalues = valuestodict(localtz)
44     localtz.Close()
45     if 'TimeZoneKeyName' in keyvalues:
46         # Windows 7 (and Vista?)
47
48         # For some reason this returns a string with loads of NUL bytes at
49         # least on some systems. I don't know if this is a bug somewhere, I
50         # just work around it.
51         tzkeyname = keyvalues['TimeZoneKeyName'].split('\x00', 1)[0]
52     else:
53         # Windows 2000 or XP
54
55         # This is the localized name:
56         tzwin = keyvalues['StandardName']
57
58         # Open the list of timezones to look up the real name:
59         TZKEYNAME = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones'
60         tzkey = winreg.OpenKey(handle, TZKEYNAME)
61
62         # Now, match this value to Time Zone information
63         tzkeyname = None
64         for i in range(winreg.QueryInfoKey(tzkey)[0]):
65             subkey = winreg.EnumKey(tzkey, i)
66             sub = winreg.OpenKey(tzkey, subkey)
67             data = valuestodict(sub)
68             sub.Close()
69             if data['Std'] == tzwin:
70                 tzkeyname = subkey
71                 break
72
73         tzkey.Close()
74         handle.Close()
75
76     if tzkeyname is None:
77         raise LookupError('Can not find Windows timezone configuration')
78
79     timezone = tz_names.get(tzkeyname)
80     if timezone is None:
81         # Nope, that didn't work. Try adding 'Standard Time',
82         # it seems to work a lot of times:
83         timezone = tz_names.get(tzkeyname + ' Standard Time')
84
85     # Return what we have.
86     if timezone is None:
87         raise pytz.UnknownTimeZoneError('Can not find timezone ' + tzkeyname)
88
89     return timezone
90
91
92 def _get_localzone():
93     if winreg is None:
94         raise pytz.UnknownTimeZoneError(
95             'Runtime support not available')
96     return pytz.timezone(get_localzone_name())