1 # -*- coding: latin-1 -*- |
|
2 |
|
3 """ Timezone information. |
|
4 |
|
5 XXX This module still has prototype status and is undocumented. |
|
6 |
|
7 XXX Double check the offsets given in the zonetable below. |
|
8 |
|
9 XXX Add TZ environment variable parsing functions. The REs are already |
|
10 there. |
|
11 |
|
12 Copyright (c) 1998-2000, Marc-Andre Lemburg; mailto:mal@lemburg.com |
|
13 Copyright (c) 2000-2007, eGenix.com Software GmbH; mailto:info@egenix.com |
|
14 See the documentation for further information on copyrights, |
|
15 or contact the author. All Rights Reserved. |
|
16 |
|
17 """ |
|
18 import DateTime |
|
19 import re,string |
|
20 |
|
21 ### REs |
|
22 |
|
23 # time zone parsing |
|
24 isozone = ('(?P<zone>[+-]\d\d:?(?:\d\d)?|Z)') |
|
25 zone = ('(?P<zone>[A-Z]+|[+-]\d\d?:?(?:\d\d)?)') |
|
26 zoneoffset = ('(?:' |
|
27 '(?P<zonesign>[+-])?' |
|
28 '(?P<hours>\d\d?)' |
|
29 ':?' |
|
30 '(?P<minutes>\d\d)?' |
|
31 '(?P<extra>\d+)?' |
|
32 ')' |
|
33 ) |
|
34 |
|
35 # TZ environment variable parsing |
|
36 dstswitchtime = ('(?P<hour>\d\d?):?' |
|
37 '(?P<minute>\d\d)?:?' |
|
38 '(?P<second>\d\d)?') |
|
39 dstswitch = ('(?:' |
|
40 '(?P<doy>\d+)|' |
|
41 '(?:J(?P<jdoy>\d+))|' |
|
42 '(?:M(?P<month>\d+).(?P<week>\d+).(?P<day>\d+))' |
|
43 ')' |
|
44 '(?:/' + dstswitchtime + ')?' |
|
45 ) |
|
46 |
|
47 # XXX Doesn't work since re doesn't like multiple occurrences of |
|
48 # group names. |
|
49 #tz = ('(?::(?P<filename>.+))|' |
|
50 # '(?P<std>[A-Z]+)' + zoneoffset + |
|
51 # '(?:' |
|
52 # '(?P<dst>[A-Z]+)' + zoneoffset + '?'+ |
|
53 # '(?:[;,]' + dstswitch + '[;,]' + dstswitch + ')' |
|
54 # ')?' |
|
55 # ) |
|
56 |
|
57 # Compiled RE objects |
|
58 isozoneRE = re.compile(zone) |
|
59 zoneRE = re.compile(zone) |
|
60 zoneoffsetRE = re.compile(zoneoffset) |
|
61 #tzRE= re.compile(tz) |
|
62 |
|
63 ### Time zone offset table |
|
64 # |
|
65 # The offset given here represent the difference between UTC and the |
|
66 # given time zone. |
|
67 # |
|
68 # Additions and corrections are always welcome :-) |
|
69 # |
|
70 # Note that some zone names are ambiguous, e.g. IST can refer to Irish |
|
71 # Summer Time, Indian Standard Time, Israel Standard Time. We've |
|
72 # usualy chosen meaning with the most wide-spread use. |
|
73 # |
|
74 zonetable = { |
|
75 # Timezone abbreviations |
|
76 # Std Summer |
|
77 |
|
78 # Standards |
|
79 'UT':0, |
|
80 'UTC':0, |
|
81 'GMT':0, |
|
82 |
|
83 # A few common timezone abbreviations |
|
84 'CET':1, 'CEST':2, 'CETDST':2, # Central European |
|
85 'MET':1, 'MEST':2, 'METDST':2, # Mean European |
|
86 'MEZ':1, 'MESZ':2, # Mitteleuropäische Zeit |
|
87 'EET':2, 'EEST':3, 'EETDST':3, # Eastern Europe |
|
88 'WET':0, 'WEST':1, 'WETDST':1, # Western Europe |
|
89 'MSK':3, 'MSD':4, # Moscow |
|
90 'IST':5.5, # India |
|
91 'JST':9, # Japan |
|
92 'KST':9, # Korea |
|
93 'HKT':8, # Hong Kong |
|
94 |
|
95 # US time zones |
|
96 'AST':-4, 'ADT':-3, # Atlantic |
|
97 'EST':-5, 'EDT':-4, # Eastern |
|
98 'CST':-6, 'CDT':-5, # Central |
|
99 'MST':-7, 'MDT':-6, # Midwestern |
|
100 'PST':-8, 'PDT':-7, # Pacific |
|
101 |
|
102 # Australian time zones |
|
103 'CAST':9.5, 'CADT':10.5, # Central |
|
104 'EAST':10, 'EADT':11, # Eastern |
|
105 'WAST':8, 'WADT':9, # Western |
|
106 'SAST':9.5, 'SADT':10.5, # Southern |
|
107 |
|
108 # US military time zones |
|
109 'Z': 0, |
|
110 'A': 1, |
|
111 'B': 2, |
|
112 'C': 3, |
|
113 'D': 4, |
|
114 'E': 5, |
|
115 'F': 6, |
|
116 'G': 7, |
|
117 'H': 8, |
|
118 'I': 9, |
|
119 'K': 10, |
|
120 'L': 11, |
|
121 'M': 12, |
|
122 'N':-1, |
|
123 'O':-2, |
|
124 'P':-3, |
|
125 'Q':-4, |
|
126 'R':-5, |
|
127 'S':-6, |
|
128 'T':-7, |
|
129 'U':-8, |
|
130 'V':-9, |
|
131 'W':-10, |
|
132 'X':-11, |
|
133 'Y':-12 |
|
134 } |
|
135 |
|
136 def utc_offset(zone, |
|
137 |
|
138 atoi=string.atoi,zoneoffset=zoneoffsetRE, |
|
139 zonetable=zonetable,zerooffset=DateTime.DateTimeDelta(0), |
|
140 oneMinute=DateTime.oneMinute,upper=string.upper): |
|
141 |
|
142 """ utc_offset(zonestring) |
|
143 |
|
144 Return the UTC time zone offset as DateTimeDelta instance. |
|
145 |
|
146 zone must be string and can either be given as +-HH:MM, |
|
147 +-HHMM, +-HH numeric offset or as time zone |
|
148 abbreviation. Daylight saving time must be encoded into the |
|
149 zone offset. |
|
150 |
|
151 Timezone abbreviations are treated case-insensitive. |
|
152 |
|
153 """ |
|
154 if not zone: |
|
155 return zerooffset |
|
156 uzone = upper(zone) |
|
157 if zonetable.has_key(uzone): |
|
158 return zonetable[uzone]*DateTime.oneHour |
|
159 offset = zoneoffset.match(zone) |
|
160 if not offset: |
|
161 raise ValueError,'wrong format or unknown time zone: "%s"' % zone |
|
162 zonesign,hours,minutes,extra = offset.groups() |
|
163 if extra: |
|
164 raise ValueError,'illegal time zone offset: "%s"' % zone |
|
165 offset = int(hours or 0) * 60 + int(minutes or 0) |
|
166 if zonesign == '-': |
|
167 offset = -offset |
|
168 return offset*oneMinute |
|
169 |
|