|
1 /* |
|
2 ********************************************************************** |
|
3 * Copyright (c) 2003-2013, 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/basictz.h" |
|
19 #include "umutex.h" |
|
20 |
|
21 struct UResourceBundle; |
|
22 |
|
23 U_NAMESPACE_BEGIN |
|
24 |
|
25 class SimpleTimeZone; |
|
26 |
|
27 /** |
|
28 * A time zone based on the Olson tz database. Olson time zones change |
|
29 * behavior over time. The raw offset, rules, presence or absence of |
|
30 * daylight savings time, and even the daylight savings amount can all |
|
31 * vary. |
|
32 * |
|
33 * This class uses a resource bundle named "zoneinfo". Zoneinfo is a |
|
34 * table containing different kinds of resources. In several places, |
|
35 * zones are referred to using integers. A zone's integer is a number |
|
36 * from 0..n-1, where n is the number of zones, with the zones sorted |
|
37 * in lexicographic order. |
|
38 * |
|
39 * 1. Zones. These have keys corresponding to the Olson IDs, e.g., |
|
40 * "Asia/Shanghai". Each resource describes the behavior of the given |
|
41 * zone. Zones come in two different formats. |
|
42 * |
|
43 * a. Zone (table). A zone is a table resource contains several |
|
44 * type of resources below: |
|
45 * |
|
46 * - typeOffsets:intvector (Required) |
|
47 * |
|
48 * Sets of UTC raw/dst offset pairs in seconds. Entries at |
|
49 * 2n represents raw offset and 2n+1 represents dst offset |
|
50 * paired with the raw offset at 2n. The very first pair represents |
|
51 * the initial zone offset (before the first transition) always. |
|
52 * |
|
53 * - trans:intvector (Optional) |
|
54 * |
|
55 * List of transition times represented by 32bit seconds from the |
|
56 * epoch (1970-01-01T00:00Z) in ascending order. |
|
57 * |
|
58 * - transPre32/transPost32:intvector (Optional) |
|
59 * |
|
60 * List of transition times before/after 32bit minimum seconds. |
|
61 * Each time is represented by a pair of 32bit integer. |
|
62 * |
|
63 * - typeMap:bin (Optional) |
|
64 * |
|
65 * Array of bytes representing the mapping between each transition |
|
66 * time (transPre32/trans/transPost32) and its corresponding offset |
|
67 * data (typeOffsets). |
|
68 * |
|
69 * - finalRule:string (Optional) |
|
70 * |
|
71 * If a recurrent transition rule is applicable to a zone forever |
|
72 * after the final transition time, finalRule represents the rule |
|
73 * in Rules data. |
|
74 * |
|
75 * - finalRaw:int (Optional) |
|
76 * |
|
77 * When finalRule is available, finalRaw is required and specifies |
|
78 * the raw (base) offset of the rule. |
|
79 * |
|
80 * - finalYear:int (Optional) |
|
81 * |
|
82 * When finalRule is available, finalYear is required and specifies |
|
83 * the start year of the rule. |
|
84 * |
|
85 * - links:intvector (Optional) |
|
86 * |
|
87 * When this zone data is shared with other zones, links specifies |
|
88 * all zones including the zone itself. Each zone is referenced by |
|
89 * integer index. |
|
90 * |
|
91 * b. Link (int, length 1). A link zone is an int resource. The |
|
92 * integer is the zone number of the target zone. The key of this |
|
93 * resource is an alternate name for the target zone. This data |
|
94 * is corresponding to Link data in the tz database. |
|
95 * |
|
96 * |
|
97 * 2. Rules. These have keys corresponding to the Olson rule IDs, |
|
98 * with an underscore prepended, e.g., "_EU". Each resource describes |
|
99 * the behavior of the given rule using an intvector, containing the |
|
100 * onset list, the cessation list, and the DST savings. The onset and |
|
101 * cessation lists consist of the month, dowim, dow, time, and time |
|
102 * mode. The end result is that the 11 integers describing the rule |
|
103 * can be passed directly into the SimpleTimeZone 13-argument |
|
104 * constructor (the other two arguments will be the raw offset, taken |
|
105 * from the complex zone element 5, and the ID string, which is not |
|
106 * used), with the times and the DST savings multiplied by 1000 to |
|
107 * scale from seconds to milliseconds. |
|
108 * |
|
109 * 3. Regions. An array specifies mapping between zones and regions. |
|
110 * Each item is either a 2-letter ISO country code or "001" |
|
111 * (UN M.49 - World). This data is generated from "zone.tab" |
|
112 * in the tz database. |
|
113 */ |
|
114 class U_I18N_API OlsonTimeZone: public BasicTimeZone { |
|
115 public: |
|
116 /** |
|
117 * Construct from a resource bundle. |
|
118 * @param top the top-level zoneinfo resource bundle. This is used |
|
119 * to lookup the rule that `res' may refer to, if there is one. |
|
120 * @param res the resource bundle of the zone to be constructed |
|
121 * @param tzid the time zone ID |
|
122 * @param ec input-output error code |
|
123 */ |
|
124 OlsonTimeZone(const UResourceBundle* top, |
|
125 const UResourceBundle* res, |
|
126 const UnicodeString& tzid, |
|
127 UErrorCode& ec); |
|
128 |
|
129 /** |
|
130 * Copy constructor |
|
131 */ |
|
132 OlsonTimeZone(const OlsonTimeZone& other); |
|
133 |
|
134 /** |
|
135 * Destructor |
|
136 */ |
|
137 virtual ~OlsonTimeZone(); |
|
138 |
|
139 /** |
|
140 * Assignment operator |
|
141 */ |
|
142 OlsonTimeZone& operator=(const OlsonTimeZone& other); |
|
143 |
|
144 /** |
|
145 * Returns true if the two TimeZone objects are equal. |
|
146 */ |
|
147 virtual UBool operator==(const TimeZone& other) const; |
|
148 |
|
149 /** |
|
150 * TimeZone API. |
|
151 */ |
|
152 virtual TimeZone* clone() const; |
|
153 |
|
154 /** |
|
155 * TimeZone API. |
|
156 */ |
|
157 static UClassID U_EXPORT2 getStaticClassID(); |
|
158 |
|
159 /** |
|
160 * TimeZone API. |
|
161 */ |
|
162 virtual UClassID getDynamicClassID() const; |
|
163 |
|
164 /** |
|
165 * TimeZone API. Do not call this; prefer getOffset(UDate,...). |
|
166 */ |
|
167 virtual int32_t getOffset(uint8_t era, int32_t year, int32_t month, |
|
168 int32_t day, uint8_t dayOfWeek, |
|
169 int32_t millis, UErrorCode& ec) const; |
|
170 |
|
171 /** |
|
172 * TimeZone API. Do not call this; prefer getOffset(UDate,...). |
|
173 */ |
|
174 virtual int32_t getOffset(uint8_t era, int32_t year, int32_t month, |
|
175 int32_t day, uint8_t dayOfWeek, |
|
176 int32_t millis, int32_t monthLength, |
|
177 UErrorCode& ec) const; |
|
178 |
|
179 /** |
|
180 * TimeZone API. |
|
181 */ |
|
182 virtual void getOffset(UDate date, UBool local, int32_t& rawOffset, |
|
183 int32_t& dstOffset, UErrorCode& ec) const; |
|
184 |
|
185 /** |
|
186 * BasicTimeZone API. |
|
187 */ |
|
188 virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt, |
|
189 int32_t& rawoff, int32_t& dstoff, UErrorCode& ec) const; |
|
190 |
|
191 /** |
|
192 * TimeZone API. This method has no effect since objects of this |
|
193 * class are quasi-immutable (the base class allows the ID to be |
|
194 * changed). |
|
195 */ |
|
196 virtual void setRawOffset(int32_t offsetMillis); |
|
197 |
|
198 /** |
|
199 * TimeZone API. For a historical zone, the raw offset can change |
|
200 * over time, so this API is not useful. In order to approximate |
|
201 * expected behavior, this method returns the raw offset for the |
|
202 * current moment in time. |
|
203 */ |
|
204 virtual int32_t getRawOffset() const; |
|
205 |
|
206 /** |
|
207 * TimeZone API. For a historical zone, whether DST is used or |
|
208 * not varies over time. In order to approximate expected |
|
209 * behavior, this method returns TRUE if DST is observed at any |
|
210 * point in the current year. |
|
211 */ |
|
212 virtual UBool useDaylightTime() const; |
|
213 |
|
214 /** |
|
215 * TimeZone API. |
|
216 */ |
|
217 virtual UBool inDaylightTime(UDate date, UErrorCode& ec) const; |
|
218 |
|
219 /** |
|
220 * TimeZone API. |
|
221 */ |
|
222 virtual int32_t getDSTSavings() const; |
|
223 |
|
224 /** |
|
225 * TimeZone API. Also comare historic transitions. |
|
226 */ |
|
227 virtual UBool hasSameRules(const TimeZone& other) const; |
|
228 |
|
229 /** |
|
230 * BasicTimeZone API. |
|
231 * Gets the first time zone transition after the base time. |
|
232 * @param base The base time. |
|
233 * @param inclusive Whether the base time is inclusive or not. |
|
234 * @param result Receives the first transition after the base time. |
|
235 * @return TRUE if the transition is found. |
|
236 */ |
|
237 virtual UBool getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const; |
|
238 |
|
239 /** |
|
240 * BasicTimeZone API. |
|
241 * Gets the most recent time zone transition before the base time. |
|
242 * @param base The base time. |
|
243 * @param inclusive Whether the base time is inclusive or not. |
|
244 * @param result Receives the most recent transition before the base time. |
|
245 * @return TRUE if the transition is found. |
|
246 */ |
|
247 virtual UBool getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const; |
|
248 |
|
249 /** |
|
250 * BasicTimeZone API. |
|
251 * Returns the number of <code>TimeZoneRule</code>s which represents time transitions, |
|
252 * for this time zone, that is, all <code>TimeZoneRule</code>s for this time zone except |
|
253 * <code>InitialTimeZoneRule</code>. The return value range is 0 or any positive value. |
|
254 * @param status Receives error status code. |
|
255 * @return The number of <code>TimeZoneRule</code>s representing time transitions. |
|
256 */ |
|
257 virtual int32_t countTransitionRules(UErrorCode& status) const; |
|
258 |
|
259 /** |
|
260 * Gets the <code>InitialTimeZoneRule</code> and the set of <code>TimeZoneRule</code> |
|
261 * which represent time transitions for this time zone. On successful return, |
|
262 * the argument initial points to non-NULL <code>InitialTimeZoneRule</code> and |
|
263 * the array trsrules is filled with 0 or multiple <code>TimeZoneRule</code> |
|
264 * instances up to the size specified by trscount. The results are referencing the |
|
265 * rule instance held by this time zone instance. Therefore, after this time zone |
|
266 * is destructed, they are no longer available. |
|
267 * @param initial Receives the initial timezone rule |
|
268 * @param trsrules Receives the timezone transition rules |
|
269 * @param trscount On input, specify the size of the array 'transitions' receiving |
|
270 * the timezone transition rules. On output, actual number of |
|
271 * rules filled in the array will be set. |
|
272 * @param status Receives error status code. |
|
273 */ |
|
274 virtual void getTimeZoneRules(const InitialTimeZoneRule*& initial, |
|
275 const TimeZoneRule* trsrules[], int32_t& trscount, UErrorCode& status) const; |
|
276 |
|
277 /** |
|
278 * Internal API returning the canonical ID of this zone. |
|
279 * This ID won't be affected by setID(). |
|
280 */ |
|
281 const UChar *getCanonicalID() const; |
|
282 |
|
283 private: |
|
284 /** |
|
285 * Default constructor. Creates a time zone with an empty ID and |
|
286 * a fixed GMT offset of zero. |
|
287 */ |
|
288 OlsonTimeZone(); |
|
289 |
|
290 private: |
|
291 |
|
292 void constructEmpty(); |
|
293 |
|
294 void getHistoricalOffset(UDate date, UBool local, |
|
295 int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt, |
|
296 int32_t& rawoff, int32_t& dstoff) const; |
|
297 |
|
298 int16_t transitionCount() const; |
|
299 |
|
300 int64_t transitionTimeInSeconds(int16_t transIdx) const; |
|
301 double transitionTime(int16_t transIdx) const; |
|
302 |
|
303 /* |
|
304 * Following 3 methods return an offset at the given transition time index. |
|
305 * When the index is negative, return the initial offset. |
|
306 */ |
|
307 int32_t zoneOffsetAt(int16_t transIdx) const; |
|
308 int32_t rawOffsetAt(int16_t transIdx) const; |
|
309 int32_t dstOffsetAt(int16_t transIdx) const; |
|
310 |
|
311 /* |
|
312 * Following methods return the initial offset. |
|
313 */ |
|
314 int32_t initialRawOffset() const; |
|
315 int32_t initialDstOffset() const; |
|
316 |
|
317 /** |
|
318 * Number of transitions in each time range |
|
319 */ |
|
320 int16_t transitionCountPre32; |
|
321 int16_t transitionCount32; |
|
322 int16_t transitionCountPost32; |
|
323 |
|
324 /** |
|
325 * Time of each transition in seconds from 1970 epoch before 32bit second range (<= 1900). |
|
326 * Each transition in this range is represented by a pair of int32_t. |
|
327 * Length is transitionCount int32_t's. NULL if no transitions in this range. |
|
328 */ |
|
329 const int32_t *transitionTimesPre32; // alias into res; do not delete |
|
330 |
|
331 /** |
|
332 * Time of each transition in seconds from 1970 epoch in 32bit second range. |
|
333 * Length is transitionCount int32_t's. NULL if no transitions in this range. |
|
334 */ |
|
335 const int32_t *transitionTimes32; // alias into res; do not delete |
|
336 |
|
337 /** |
|
338 * Time of each transition in seconds from 1970 epoch after 32bit second range (>= 2038). |
|
339 * Each transition in this range is represented by a pair of int32_t. |
|
340 * Length is transitionCount int32_t's. NULL if no transitions in this range. |
|
341 */ |
|
342 const int32_t *transitionTimesPost32; // alias into res; do not delete |
|
343 |
|
344 /** |
|
345 * Number of types, 1..255 |
|
346 */ |
|
347 int16_t typeCount; |
|
348 |
|
349 /** |
|
350 * Offset from GMT in seconds for each type. |
|
351 * Length is typeCount int32_t's. At least one type (a pair of int32_t) |
|
352 * is required. |
|
353 */ |
|
354 const int32_t *typeOffsets; // alias into res; do not delete |
|
355 |
|
356 /** |
|
357 * Type description data, consisting of transitionCount uint8_t |
|
358 * type indices (from 0..typeCount-1). |
|
359 * Length is transitionCount int16_t's. NULL if no transitions. |
|
360 */ |
|
361 const uint8_t *typeMapData; // alias into res; do not delete |
|
362 |
|
363 /** |
|
364 * A SimpleTimeZone that governs the behavior for date >= finalMillis. |
|
365 */ |
|
366 SimpleTimeZone *finalZone; // owned, may be NULL |
|
367 |
|
368 /** |
|
369 * For date >= finalMillis, the finalZone will be used. |
|
370 */ |
|
371 double finalStartMillis; |
|
372 |
|
373 /** |
|
374 * For year >= finalYear, the finalZone will be used. |
|
375 */ |
|
376 int32_t finalStartYear; |
|
377 |
|
378 /* |
|
379 * Canonical (CLDR) ID of this zone |
|
380 */ |
|
381 const UChar *canonicalID; |
|
382 |
|
383 /* BasicTimeZone support */ |
|
384 void clearTransitionRules(void); |
|
385 void deleteTransitionRules(void); |
|
386 void checkTransitionRules(UErrorCode& status) const; |
|
387 |
|
388 public: // Internal, for access from plain C code |
|
389 void initTransitionRules(UErrorCode& status); |
|
390 private: |
|
391 |
|
392 InitialTimeZoneRule *initialRule; |
|
393 TimeZoneTransition *firstTZTransition; |
|
394 int16_t firstTZTransitionIdx; |
|
395 TimeZoneTransition *firstFinalTZTransition; |
|
396 TimeArrayTimeZoneRule **historicRules; |
|
397 int16_t historicRuleCount; |
|
398 SimpleTimeZone *finalZoneWithStartYear; // hack |
|
399 UInitOnce transitionRulesInitOnce; |
|
400 }; |
|
401 |
|
402 inline int16_t |
|
403 OlsonTimeZone::transitionCount() const { |
|
404 return transitionCountPre32 + transitionCount32 + transitionCountPost32; |
|
405 } |
|
406 |
|
407 inline double |
|
408 OlsonTimeZone::transitionTime(int16_t transIdx) const { |
|
409 return (double)transitionTimeInSeconds(transIdx) * U_MILLIS_PER_SECOND; |
|
410 } |
|
411 |
|
412 inline int32_t |
|
413 OlsonTimeZone::zoneOffsetAt(int16_t transIdx) const { |
|
414 int16_t typeIdx = (transIdx >= 0 ? typeMapData[transIdx] : 0) << 1; |
|
415 return typeOffsets[typeIdx] + typeOffsets[typeIdx + 1]; |
|
416 } |
|
417 |
|
418 inline int32_t |
|
419 OlsonTimeZone::rawOffsetAt(int16_t transIdx) const { |
|
420 int16_t typeIdx = (transIdx >= 0 ? typeMapData[transIdx] : 0) << 1; |
|
421 return typeOffsets[typeIdx]; |
|
422 } |
|
423 |
|
424 inline int32_t |
|
425 OlsonTimeZone::dstOffsetAt(int16_t transIdx) const { |
|
426 int16_t typeIdx = (transIdx >= 0 ? typeMapData[transIdx] : 0) << 1; |
|
427 return typeOffsets[typeIdx + 1]; |
|
428 } |
|
429 |
|
430 inline int32_t |
|
431 OlsonTimeZone::initialRawOffset() const { |
|
432 return typeOffsets[0]; |
|
433 } |
|
434 |
|
435 inline int32_t |
|
436 OlsonTimeZone::initialDstOffset() const { |
|
437 return typeOffsets[1]; |
|
438 } |
|
439 |
|
440 inline const UChar* |
|
441 OlsonTimeZone::getCanonicalID() const { |
|
442 return canonicalID; |
|
443 } |
|
444 |
|
445 |
|
446 U_NAMESPACE_END |
|
447 |
|
448 #endif // !UCONFIG_NO_FORMATTING |
|
449 #endif // OLSONTZ_H |
|
450 |
|
451 //eof |