]>
Commit | Line | Data |
---|---|---|
374ca955 A |
1 | /* |
2 | ********************************************************************** | |
3 | * Copyright (c) 2003-2004, International Business Machines | |
4 | * Corporation and others. All Rights Reserved. | |
5 | ********************************************************************** | |
6 | * Author: Alan Liu | |
7 | * Created: July 21 2003 | |
8 | * Since: ICU 2.8 | |
9 | ********************************************************************** | |
10 | */ | |
11 | #ifndef OLSONTZ_H | |
12 | #define OLSONTZ_H | |
13 | ||
14 | #include "unicode/utypes.h" | |
15 | ||
16 | #if !UCONFIG_NO_FORMATTING | |
17 | ||
18 | #include "unicode/timezone.h" | |
19 | ||
20 | struct UResourceBundle; | |
21 | ||
22 | U_NAMESPACE_BEGIN | |
23 | ||
24 | class SimpleTimeZone; | |
25 | ||
26 | /** | |
27 | * A time zone based on the Olson database. Olson time zones change | |
28 | * behavior over time. The raw offset, rules, presence or absence of | |
29 | * daylight savings time, and even the daylight savings amount can all | |
30 | * vary. | |
31 | * | |
32 | * This class uses a resource bundle named "zoneinfo". Zoneinfo is a | |
33 | * table containing different kinds of resources. In several places, | |
34 | * zones are referred to using integers. A zone's integer is a number | |
35 | * from 0..n-1, where n is the number of zones, with the zones sorted | |
36 | * in lexicographic order. | |
37 | * | |
38 | * 1. Zones. These have keys corresponding to the Olson IDs, e.g., | |
39 | * "Asia/Shanghai". Each resource describes the behavior of the given | |
40 | * zone. Zones come in several formats, which are differentiated | |
41 | * based on length. | |
42 | * | |
43 | * a. Alias (int, length 1). An alias zone is an int resource. The | |
44 | * integer is the zone number of the target zone. The key of this | |
45 | * resource is an alternate name for the target zone. Aliases | |
46 | * represent Olson links and ICU compatibility IDs. | |
47 | * | |
48 | * b. Simple zone (array, length 3). The three subelements are: | |
49 | * | |
50 | * i. An intvector of transitions. These are given in epoch | |
51 | * seconds. This may be an empty invector (length 0). If the | |
52 | * transtions list is empty, then the zone's behavior is fixed and | |
53 | * given by the offset list, which will contain exactly one pair. | |
54 | * Otherwise each transtion indicates a time after which (inclusive) | |
55 | * the associated offset pair is in effect. | |
56 | * | |
57 | * ii. An intvector of offsets. These are in pairs of raw offset / | |
58 | * DST offset, in units of seconds. There will be at least one pair | |
59 | * (length >= 2 && length % 2 == 0). | |
60 | * | |
61 | * iii. A binary resource. This is of the same length as the | |
62 | * transitions vector, so length may be zero. Each unsigned byte | |
63 | * corresponds to one transition, and has a value of 0..n-1, where n | |
64 | * is the number of pairs in the offset vector. This forms a map | |
65 | * between transitions and offset pairs. | |
66 | * | |
67 | * c. Simple zone with aliases (array, length 4). This is like a | |
68 | * simple zone, but also contains a fourth element: | |
69 | * | |
70 | * iv. An intvector of aliases. This list includes this zone | |
71 | * itself, and lists all aliases of this zone. | |
72 | * | |
73 | * d. Complex zone (array, length 5). This is like a simple zone, | |
74 | * but contains two more elements: | |
75 | * | |
76 | * iv. A string, giving the name of a rule. This is the "final | |
77 | * rule", which governs the zone's behavior beginning in the "final | |
78 | * year". The rule ID is given without leading underscore, e.g., | |
79 | * "EU". | |
80 | * | |
81 | * v. An intvector of length 2, containing the raw offset for the | |
82 | * final rule (in seconds), and the final year. The final rule | |
83 | * takes effect for years >= the final year. | |
84 | * | |
85 | * e. Complex zone with aliases (array, length 6). This is like a | |
86 | * complex zone, but also contains a sixth element: | |
87 | * | |
88 | * vi. An intvector of aliases. This list includes this zone | |
89 | * itself, and lists all aliases of this zone. | |
90 | * | |
91 | * 2. Rules. These have keys corresponding to the Olson rule IDs, | |
92 | * with an underscore prepended, e.g., "_EU". Each resource describes | |
93 | * the behavior of the given rule using an intvector, containing the | |
94 | * onset list, the cessation list, and the DST savings. The onset and | |
95 | * cessation lists consist of the month, dowim, dow, time, and time | |
96 | * mode. The end result is that the 11 integers describing the rule | |
97 | * can be passed directly into the SimpleTimeZone 13-argument | |
98 | * constructor (the other two arguments will be the raw offset, taken | |
99 | * from the complex zone element 5, and the ID string, which is not | |
100 | * used), with the times and the DST savings multiplied by 1000 to | |
101 | * scale from seconds to milliseconds. | |
102 | * | |
103 | * 3. Countries. These have keys corresponding to the 2-letter ISO | |
104 | * country codes, with a percent sign prepended, e.g., "%US". Each | |
105 | * resource is an intvector listing the zones associated with the | |
106 | * given country. The special entry "%" corresponds to "no country", | |
107 | * that is, the category of zones assigned to no country in the Olson | |
108 | * DB. | |
109 | * | |
110 | * 4. Metadata. Metadata is stored under the key "_". It is an | |
111 | * intvector of length three containing the number of zones resources, | |
112 | * rule resources, and country resources. For the purposes of this | |
113 | * count, the metadata entry itself is considered a rule resource, | |
114 | * since its key begins with an underscore. | |
115 | */ | |
116 | class U_I18N_API OlsonTimeZone: public TimeZone { | |
117 | public: | |
118 | /** | |
119 | * Construct from a resource bundle. | |
120 | * @param top the top-level zoneinfo resource bundle. This is used | |
121 | * to lookup the rule that `res' may refer to, if there is one. | |
122 | * @param res the resource bundle of the zone to be constructed | |
123 | * @param ec input-output error code | |
124 | */ | |
125 | OlsonTimeZone(const UResourceBundle* top, | |
126 | const UResourceBundle* res, UErrorCode& ec); | |
127 | ||
128 | /** | |
129 | * Copy constructor | |
130 | */ | |
131 | OlsonTimeZone(const OlsonTimeZone& other); | |
132 | ||
133 | /** | |
134 | * Destructor | |
135 | */ | |
136 | virtual ~OlsonTimeZone(); | |
137 | ||
138 | /** | |
139 | * Assignment operator | |
140 | */ | |
141 | OlsonTimeZone& operator=(const OlsonTimeZone& other); | |
142 | ||
143 | /** | |
144 | * Returns true if the two TimeZone objects are equal. | |
145 | */ | |
146 | virtual UBool operator==(const TimeZone& other) const; | |
147 | ||
148 | /** | |
149 | * TimeZone API. | |
150 | */ | |
151 | virtual TimeZone* clone() const; | |
152 | ||
153 | /** | |
154 | * TimeZone API. | |
155 | */ | |
156 | static UClassID U_EXPORT2 getStaticClassID(); | |
157 | ||
158 | /** | |
159 | * TimeZone API. | |
160 | */ | |
161 | virtual UClassID getDynamicClassID() const; | |
162 | ||
163 | /** | |
164 | * TimeZone API. Do not call this; prefer getOffset(UDate,...). | |
165 | */ | |
166 | virtual int32_t getOffset(uint8_t era, int32_t year, int32_t month, | |
167 | int32_t day, uint8_t dayOfWeek, | |
168 | int32_t millis, UErrorCode& ec) const; | |
169 | ||
170 | /** | |
171 | * TimeZone API. Do not call this; prefer getOffset(UDate,...). | |
172 | */ | |
173 | virtual int32_t getOffset(uint8_t era, int32_t year, int32_t month, | |
174 | int32_t day, uint8_t dayOfWeek, | |
175 | int32_t millis, int32_t monthLength, | |
176 | UErrorCode& ec) const; | |
177 | ||
178 | /** | |
179 | * TimeZone API. | |
180 | */ | |
181 | virtual void getOffset(UDate date, UBool local, int32_t& rawOffset, | |
182 | int32_t& dstOffset, UErrorCode& ec) const; | |
183 | ||
184 | /** | |
185 | * TimeZone API. This method has no effect since objects of this | |
186 | * class are quasi-immutable (the base class allows the ID to be | |
187 | * changed). | |
188 | */ | |
189 | virtual void setRawOffset(int32_t offsetMillis); | |
190 | ||
191 | /** | |
192 | * TimeZone API. For a historical zone, the raw offset can change | |
193 | * over time, so this API is not useful. In order to approximate | |
194 | * expected behavior, this method returns the raw offset for the | |
195 | * current moment in time. | |
196 | */ | |
197 | virtual int32_t getRawOffset() const; | |
198 | ||
199 | /** | |
200 | * TimeZone API. For a historical zone, whether DST is used or | |
201 | * not varies over time. In order to approximate expected | |
202 | * behavior, this method returns TRUE if DST is observed at any | |
203 | * point in the current year. | |
204 | */ | |
205 | virtual UBool useDaylightTime() const; | |
206 | ||
207 | /** | |
208 | * TimeZone API. | |
209 | */ | |
210 | virtual UBool inDaylightTime(UDate date, UErrorCode& ec) const; | |
211 | ||
212 | protected: | |
213 | /** | |
214 | * Default constructor. Creates a time zone with an empty ID and | |
215 | * a fixed GMT offset of zero. | |
216 | */ | |
217 | OlsonTimeZone(); | |
218 | ||
219 | private: | |
220 | ||
221 | void constructEmpty(); | |
222 | ||
223 | int16_t findTransition(double time, UBool local) const; | |
224 | ||
225 | int32_t zoneOffset(int16_t index) const; | |
226 | int32_t rawOffset(int16_t index) const; | |
227 | int32_t dstOffset(int16_t index) const; | |
228 | ||
229 | /** | |
230 | * Number of transitions, 0..~370 | |
231 | */ | |
232 | int16_t transitionCount; | |
233 | ||
234 | /** | |
235 | * Number of types, 1..255 | |
236 | */ | |
237 | int16_t typeCount; | |
238 | ||
239 | /** | |
240 | * Time of each transition in seconds from 1970 epoch. | |
241 | * Length is transitionCount int32_t's. | |
242 | */ | |
243 | const int32_t *transitionTimes; // alias into res; do not delete | |
244 | ||
245 | /** | |
246 | * Offset from GMT in seconds for each type. | |
247 | * Length is typeCount int32_t's. | |
248 | */ | |
249 | const int32_t *typeOffsets; // alias into res; do not delete | |
250 | ||
251 | /** | |
252 | * Type description data, consisting of transitionCount uint8_t | |
253 | * type indices (from 0..typeCount-1). | |
254 | * Length is transitionCount int8_t's. | |
255 | */ | |
256 | const uint8_t *typeData; // alias into res; do not delete | |
257 | ||
258 | /** | |
259 | * The last year for which the transitions data are to be used | |
260 | * rather than the finalZone. If there is no finalZone, then this | |
261 | * is set to INT32_MAX. NOTE: This corresponds to the year _before_ | |
262 | * the one indicated by finalMillis. | |
263 | */ | |
264 | int32_t finalYear; | |
265 | ||
266 | /** | |
267 | * The millis for the start of the first year for which finalZone | |
268 | * is to be used, or DBL_MAX if finalZone is 0. NOTE: This is | |
269 | * 0:00 GMT Jan 1, <finalYear + 1> (not <finalMillis>). | |
270 | */ | |
271 | double finalMillis; | |
272 | ||
273 | /** | |
274 | * A SimpleTimeZone that governs the behavior for years > finalYear. | |
275 | * If and only if finalYear == INT32_MAX then finalZone == 0. | |
276 | */ | |
277 | SimpleTimeZone *finalZone; // owned, may be NULL | |
278 | ||
279 | }; | |
280 | ||
281 | inline int32_t | |
282 | OlsonTimeZone::zoneOffset(int16_t index) const { | |
283 | index <<= 1; | |
284 | return typeOffsets[index] + typeOffsets[index+1]; | |
285 | } | |
286 | ||
287 | inline int32_t | |
288 | OlsonTimeZone::rawOffset(int16_t index) const { | |
289 | return typeOffsets[(uint32_t)(index << 1)]; | |
290 | } | |
291 | ||
292 | inline int32_t | |
293 | OlsonTimeZone::dstOffset(int16_t index) const { | |
294 | return typeOffsets[(uint32_t)((index << 1) + 1)]; | |
295 | } | |
296 | ||
297 | U_NAMESPACE_END | |
298 | ||
299 | #endif // !UCONFIG_NO_FORMATTING | |
300 | #endif // OLSONTZ_H | |
301 | ||
302 | //eof |