root/django/trunk/contrib/dateutil/tzwin.py

Revision 84, 5.7 kB (checked in by steadicat, 15 months ago)

Added loads of useful contrib.

  • Property svn:keywords set to Id
Line 
1# This code was originally contributed by Jeffrey Harris.
2import datetime
3import struct
4import _winreg
5
6__author__ = "Jeffrey Harris & Gustavo Niemeyer <gustavo@niemeyer.net>"
7
8__all__ = ["tzwin", "tzwinlocal"]
9
10ONEWEEK = datetime.timedelta(7)
11
12TZKEYNAMENT = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
13TZKEYNAME9X = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones"
14TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
15
16def _settzkeyname():
17    global TZKEYNAME
18    handle = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
19    try:
20        _winreg.OpenKey(handle, TZKEYNAMENT).Close()
21        TZKEYNAME = TZKEYNAMENT
22    except WindowsError:
23        TZKEYNAME = TZKEYNAME9X
24    handle.Close()
25
26_settzkeyname()
27
28class tzwinbase(datetime.tzinfo):
29    """tzinfo class based on win32's timezones available in the registry."""
30
31    def utcoffset(self, dt):
32        if self._isdst(dt):
33            return datetime.timedelta(minutes=self._dstoffset)
34        else:
35            return datetime.timedelta(minutes=self._stdoffset)
36
37    def dst(self, dt):
38        if self._isdst(dt):
39            minutes = self._dstoffset - self._stdoffset
40            return datetime.timedelta(minutes=minutes)
41        else:
42            return datetime.timedelta(0)
43       
44    def tzname(self, dt):
45        if self._isdst(dt):
46            return self._dstname
47        else:
48            return self._stdname
49
50    def list():
51        """Return a list of all time zones known to the system."""
52        handle = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
53        tzkey = _winreg.OpenKey(handle, TZKEYNAME)
54        result = [_winreg.EnumKey(tzkey, i)
55                  for i in range(_winreg.QueryInfoKey(tzkey)[0])]
56        tzkey.Close()
57        handle.Close()
58        return result
59    list = staticmethod(list)
60
61    def display(self):
62        return self._display
63   
64    def _isdst(self, dt):
65        dston = picknthweekday(dt.year, self._dstmonth, self._dstdayofweek,
66                               self._dsthour, self._dstminute,
67                               self._dstweeknumber)
68        dstoff = picknthweekday(dt.year, self._stdmonth, self._stddayofweek,
69                                self._stdhour, self._stdminute,
70                                self._stdweeknumber)
71        if dston < dstoff:
72            return dston <= dt.replace(tzinfo=None) < dstoff
73        else:
74            return not dstoff <= dt.replace(tzinfo=None) < dston
75
76
77class tzwin(tzwinbase):
78
79    def __init__(self, name):
80        self._name = name
81
82        handle = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
83        tzkey = _winreg.OpenKey(handle, "%s\%s" % (TZKEYNAME, name))
84        keydict = valuestodict(tzkey)
85        tzkey.Close()
86        handle.Close()
87
88        self._stdname = keydict["Std"].encode("iso-8859-1")
89        self._dstname = keydict["Dlt"].encode("iso-8859-1")
90
91        self._display = keydict["Display"]
92       
93        # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm
94        tup = struct.unpack("=3l16h", keydict["TZI"])
95        self._stdoffset = -tup[0]-tup[1]         # Bias + StandardBias * -1
96        self._dstoffset = self._stdoffset-tup[2] # + DaylightBias * -1
97       
98        (self._stdmonth,
99         self._stddayofweek,  # Sunday = 0
100         self._stdweeknumber, # Last = 5
101         self._stdhour,
102         self._stdminute) = tup[4:9]
103
104        (self._dstmonth,
105         self._dstdayofweek,  # Sunday = 0
106         self._dstweeknumber, # Last = 5
107         self._dsthour,
108         self._dstminute) = tup[12:17]
109
110    def __repr__(self):
111        return "tzwin(%s)" % repr(self._name)
112
113    def __reduce__(self):
114        return (self.__class__, (self._name,))
115
116
117class tzwinlocal(tzwinbase):
118   
119    def __init__(self):
120
121        handle = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
122
123        tzlocalkey = _winreg.OpenKey(handle, TZLOCALKEYNAME)
124        keydict = valuestodict(tzlocalkey)
125        tzlocalkey.Close()
126
127        self._stdname = keydict["StandardName"].encode("iso-8859-1")
128        self._dstname = keydict["DaylightName"].encode("iso-8859-1")
129
130        try:
131            tzkey = _winreg.OpenKey(handle, "%s\%s"%(TZKEYNAME, self._stdname))
132            _keydict = valuestodict(tzkey)
133            self._display = _keydict["Display"]
134            tzkey.Close()
135        except OSError:
136            self._display = None
137
138        handle.Close()
139       
140        self._stdoffset = -keydict["Bias"]-keydict["StandardBias"]
141        self._dstoffset = self._stdoffset-keydict["DaylightBias"]
142
143
144        # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm
145        tup = struct.unpack("=8h", keydict["StandardStart"])
146
147        (self._stdmonth,
148         self._stddayofweek,  # Sunday = 0
149         self._stdweeknumber, # Last = 5
150         self._stdhour,
151         self._stdminute) = tup[1:6]
152
153        tup = struct.unpack("=8h", keydict["DaylightStart"])
154
155        (self._dstmonth,
156         self._dstdayofweek,  # Sunday = 0
157         self._dstweeknumber, # Last = 5
158         self._dsthour,
159         self._dstminute) = tup[1:6]
160
161    def __reduce__(self):
162        return (self.__class__, ())
163
164def picknthweekday(year, month, dayofweek, hour, minute, whichweek):
165    """dayofweek == 0 means Sunday, whichweek 5 means last instance"""
166    first = datetime.datetime(year, month, 1, hour, minute)
167    weekdayone = first.replace(day=((dayofweek-first.isoweekday())%7+1))
168    for n in xrange(whichweek):
169        dt = weekdayone+(whichweek-n)*ONEWEEK
170        if dt.month == month:
171            return dt
172
173def valuestodict(key):
174    """Convert a registry key's values to a dictionary."""
175    dict = {}
176    size = _winreg.QueryInfoKey(key)[1]
177    for i in range(size):
178        data = _winreg.EnumValue(key, i)
179        dict[data[0]] = data[1]
180    return dict
Note: See TracBrowser for help on using the browser.