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