]>
Commit | Line | Data |
---|---|---|
374ca955 A |
1 | /* |
2 | ********************************************************************** | |
46f4442e | 3 | * Copyright (c) 2003-2007, International Business Machines |
374ca955 A |
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 | ||
46f4442e | 18 | #include "unicode/basictz.h" |
374ca955 A |
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 | */ | |
46f4442e | 116 | class OlsonTimeZone: public BasicTimeZone { |
374ca955 A |
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 | */ | |
46f4442e | 156 | U_I18N_API static UClassID U_EXPORT2 getStaticClassID(); |
374ca955 A |
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 | ||
46f4442e A |
184 | /** |
185 | * BasicTimeZone API. | |
186 | */ | |
187 | virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, | |
188 | int32_t& rawoff, int32_t& dstoff, UErrorCode& ec) /*const*/; | |
189 | ||
374ca955 A |
190 | /** |
191 | * TimeZone API. This method has no effect since objects of this | |
192 | * class are quasi-immutable (the base class allows the ID to be | |
193 | * changed). | |
194 | */ | |
195 | virtual void setRawOffset(int32_t offsetMillis); | |
196 | ||
197 | /** | |
198 | * TimeZone API. For a historical zone, the raw offset can change | |
199 | * over time, so this API is not useful. In order to approximate | |
200 | * expected behavior, this method returns the raw offset for the | |
201 | * current moment in time. | |
202 | */ | |
203 | virtual int32_t getRawOffset() const; | |
204 | ||
205 | /** | |
206 | * TimeZone API. For a historical zone, whether DST is used or | |
207 | * not varies over time. In order to approximate expected | |
208 | * behavior, this method returns TRUE if DST is observed at any | |
209 | * point in the current year. | |
210 | */ | |
211 | virtual UBool useDaylightTime() const; | |
212 | ||
213 | /** | |
214 | * TimeZone API. | |
215 | */ | |
216 | virtual UBool inDaylightTime(UDate date, UErrorCode& ec) const; | |
217 | ||
46f4442e A |
218 | /** |
219 | * TimeZone API. | |
220 | */ | |
73c04bcf A |
221 | virtual int32_t getDSTSavings() const; |
222 | ||
46f4442e A |
223 | /** |
224 | * TimeZone API. Also comare historic transitions. | |
225 | */ | |
226 | virtual UBool hasSameRules(const TimeZone& other) const; | |
227 | ||
228 | /** | |
229 | * BasicTimeZone API. | |
230 | * Gets the first time zone transition after the base time. | |
231 | * @param base The base time. | |
232 | * @param inclusive Whether the base time is inclusive or not. | |
233 | * @param result Receives the first transition after the base time. | |
234 | * @return TRUE if the transition is found. | |
235 | */ | |
236 | virtual UBool getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/; | |
237 | ||
238 | /** | |
239 | * BasicTimeZone API. | |
240 | * Gets the most recent time zone transition before the base time. | |
241 | * @param base The base time. | |
242 | * @param inclusive Whether the base time is inclusive or not. | |
243 | * @param result Receives the most recent transition before the base time. | |
244 | * @return TRUE if the transition is found. | |
245 | */ | |
246 | virtual UBool getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/; | |
247 | ||
248 | /** | |
249 | * BasicTimeZone API. | |
250 | * Returns the number of <code>TimeZoneRule</code>s which represents time transitions, | |
251 | * for this time zone, that is, all <code>TimeZoneRule</code>s for this time zone except | |
252 | * <code>InitialTimeZoneRule</code>. The return value range is 0 or any positive value. | |
253 | * @param status Receives error status code. | |
254 | * @return The number of <code>TimeZoneRule</code>s representing time transitions. | |
255 | */ | |
256 | virtual int32_t countTransitionRules(UErrorCode& status) /*const*/; | |
257 | ||
258 | /** | |
259 | * Gets the <code>InitialTimeZoneRule</code> and the set of <code>TimeZoneRule</code> | |
260 | * which represent time transitions for this time zone. On successful return, | |
261 | * the argument initial points to non-NULL <code>InitialTimeZoneRule</code> and | |
262 | * the array trsrules is filled with 0 or multiple <code>TimeZoneRule</code> | |
263 | * instances up to the size specified by trscount. The results are referencing the | |
264 | * rule instance held by this time zone instance. Therefore, after this time zone | |
265 | * is destructed, they are no longer available. | |
266 | * @param initial Receives the initial timezone rule | |
267 | * @param trsrules Receives the timezone transition rules | |
268 | * @param trscount On input, specify the size of the array 'transitions' receiving | |
269 | * the timezone transition rules. On output, actual number of | |
270 | * rules filled in the array will be set. | |
271 | * @param status Receives error status code. | |
272 | * @draft ICU 3.8 | |
273 | */ | |
274 | virtual void getTimeZoneRules(const InitialTimeZoneRule*& initial, | |
275 | const TimeZoneRule* trsrules[], int32_t& trscount, UErrorCode& status) /*const*/; | |
276 | ||
277 | private: | |
374ca955 A |
278 | /** |
279 | * Default constructor. Creates a time zone with an empty ID and | |
280 | * a fixed GMT offset of zero. | |
281 | */ | |
282 | OlsonTimeZone(); | |
283 | ||
46f4442e | 284 | private: |
374ca955 A |
285 | |
286 | void constructEmpty(); | |
287 | ||
46f4442e A |
288 | void getHistoricalOffset(UDate date, UBool local, |
289 | int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt, | |
290 | int32_t& rawoff, int32_t& dstoff) const; | |
374ca955 A |
291 | |
292 | int32_t zoneOffset(int16_t index) const; | |
293 | int32_t rawOffset(int16_t index) const; | |
294 | int32_t dstOffset(int16_t index) const; | |
295 | ||
296 | /** | |
297 | * Number of transitions, 0..~370 | |
298 | */ | |
299 | int16_t transitionCount; | |
300 | ||
301 | /** | |
302 | * Number of types, 1..255 | |
303 | */ | |
304 | int16_t typeCount; | |
305 | ||
306 | /** | |
307 | * Time of each transition in seconds from 1970 epoch. | |
308 | * Length is transitionCount int32_t's. | |
309 | */ | |
310 | const int32_t *transitionTimes; // alias into res; do not delete | |
311 | ||
312 | /** | |
313 | * Offset from GMT in seconds for each type. | |
314 | * Length is typeCount int32_t's. | |
315 | */ | |
316 | const int32_t *typeOffsets; // alias into res; do not delete | |
317 | ||
318 | /** | |
319 | * Type description data, consisting of transitionCount uint8_t | |
320 | * type indices (from 0..typeCount-1). | |
321 | * Length is transitionCount int8_t's. | |
322 | */ | |
323 | const uint8_t *typeData; // alias into res; do not delete | |
324 | ||
325 | /** | |
326 | * The last year for which the transitions data are to be used | |
327 | * rather than the finalZone. If there is no finalZone, then this | |
328 | * is set to INT32_MAX. NOTE: This corresponds to the year _before_ | |
329 | * the one indicated by finalMillis. | |
330 | */ | |
331 | int32_t finalYear; | |
332 | ||
333 | /** | |
334 | * The millis for the start of the first year for which finalZone | |
335 | * is to be used, or DBL_MAX if finalZone is 0. NOTE: This is | |
336 | * 0:00 GMT Jan 1, <finalYear + 1> (not <finalMillis>). | |
337 | */ | |
338 | double finalMillis; | |
339 | ||
340 | /** | |
341 | * A SimpleTimeZone that governs the behavior for years > finalYear. | |
342 | * If and only if finalYear == INT32_MAX then finalZone == 0. | |
343 | */ | |
344 | SimpleTimeZone *finalZone; // owned, may be NULL | |
345 | ||
46f4442e A |
346 | /* BasicTimeZone support */ |
347 | void clearTransitionRules(void); | |
348 | void deleteTransitionRules(void); | |
349 | void initTransitionRules(UErrorCode& status); | |
350 | ||
351 | InitialTimeZoneRule *initialRule; | |
352 | TimeZoneTransition *firstTZTransition; | |
353 | int16_t firstTZTransitionIdx; | |
354 | TimeZoneTransition *firstFinalTZTransition; | |
355 | TimeArrayTimeZoneRule **historicRules; | |
356 | int16_t historicRuleCount; | |
357 | SimpleTimeZone *finalZoneWithStartYear; // hack | |
358 | UBool transitionRulesInitialized; | |
374ca955 A |
359 | }; |
360 | ||
361 | inline int32_t | |
362 | OlsonTimeZone::zoneOffset(int16_t index) const { | |
363 | index <<= 1; | |
364 | return typeOffsets[index] + typeOffsets[index+1]; | |
365 | } | |
366 | ||
367 | inline int32_t | |
368 | OlsonTimeZone::rawOffset(int16_t index) const { | |
369 | return typeOffsets[(uint32_t)(index << 1)]; | |
370 | } | |
371 | ||
372 | inline int32_t | |
373 | OlsonTimeZone::dstOffset(int16_t index) const { | |
374 | return typeOffsets[(uint32_t)((index << 1) + 1)]; | |
375 | } | |
376 | ||
377 | U_NAMESPACE_END | |
378 | ||
379 | #endif // !UCONFIG_NO_FORMATTING | |
380 | #endif // OLSONTZ_H | |
381 | ||
382 | //eof |