]>
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 | 3 | /*********************************************************************** |
b75a7d8f | 4 | * COPYRIGHT: |
729e4ab9 | 5 | * Copyright (c) 1997-2010, International Business Machines Corporation |
374ca955 A |
6 | * and others. All Rights Reserved. |
7 | ***********************************************************************/ | |
b75a7d8f A |
8 | |
9 | #include "unicode/utypes.h" | |
10 | ||
11 | #if !UCONFIG_NO_FORMATTING | |
12 | ||
13 | #include "tzbdtest.h" | |
14 | #include "unicode/timezone.h" | |
15 | #include "unicode/simpletz.h" | |
16 | #include "unicode/gregocal.h" | |
374ca955 | 17 | #include "putilimp.h" |
b75a7d8f A |
18 | |
19 | void TimeZoneBoundaryTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) | |
20 | { | |
21 | if (exec) logln("TestSuite TestTimeZoneBoundary"); | |
22 | switch (index) { | |
23 | case 0: | |
24 | name = "TestBoundaries"; | |
25 | if (exec) { | |
26 | logln("TestBoundaries---"); logln(""); | |
27 | TestBoundaries(); | |
28 | } | |
29 | break; | |
30 | case 1: | |
31 | name = "TestNewRules"; | |
32 | if (exec) { | |
33 | logln("TestNewRules---"); logln(""); | |
34 | TestNewRules(); | |
35 | } | |
36 | break; | |
37 | case 2: | |
38 | name = "TestStepwise"; | |
39 | if (exec) { | |
40 | logln("TestStepwise---"); logln(""); | |
41 | TestStepwise(); | |
42 | } | |
43 | break; | |
44 | default: name = ""; break; | |
45 | } | |
46 | } | |
47 | ||
48 | // ***************************************************************************** | |
49 | // class TimeZoneBoundaryTest | |
50 | // ***************************************************************************** | |
51 | ||
52 | TimeZoneBoundaryTest::TimeZoneBoundaryTest() | |
53 | : | |
54 | ONE_SECOND(1000), | |
55 | ONE_MINUTE(60 * ONE_SECOND), | |
56 | ONE_HOUR(60 * ONE_MINUTE), | |
57 | ONE_DAY(24 * ONE_HOUR), | |
58 | ONE_YEAR(uprv_floor(365.25 * ONE_DAY)), | |
59 | SIX_MONTHS(ONE_YEAR / 2) | |
60 | { | |
61 | } | |
62 | ||
63 | const int32_t TimeZoneBoundaryTest::MONTH_LENGTH[] = { | |
64 | 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 | |
65 | }; | |
66 | ||
67 | const UDate TimeZoneBoundaryTest::PST_1997_BEG = 860320800000.0; | |
68 | ||
69 | const UDate TimeZoneBoundaryTest::PST_1997_END = 877856400000.0; | |
70 | ||
71 | const UDate TimeZoneBoundaryTest::INTERVAL = 10; | |
72 | ||
73 | // ------------------------------------- | |
74 | ||
75 | void | |
76 | TimeZoneBoundaryTest::findDaylightBoundaryUsingDate(UDate d, const char* startMode, UDate expectedBoundary) | |
77 | { | |
78 | UnicodeString str; | |
79 | if (dateToString(d, str).indexOf(startMode) == - 1) { | |
80 | logln(UnicodeString("Error: ") + startMode + " not present in " + str); | |
81 | } | |
82 | UDate min = d; | |
83 | UDate max = min + SIX_MONTHS; | |
84 | while ((max - min) > INTERVAL) { | |
85 | UDate mid = (min + max) / 2; | |
86 | UnicodeString* s = &dateToString(mid, str); | |
87 | if (s->indexOf(startMode) != - 1) { | |
88 | min = mid; | |
89 | } | |
90 | else { | |
91 | max = mid; | |
92 | } | |
93 | } | |
94 | logln("Date Before: " + showDate(min)); | |
95 | logln("Date After: " + showDate(max)); | |
96 | UDate mindelta = expectedBoundary - min; | |
97 | UDate maxdelta = max - expectedBoundary; | |
98 | if (mindelta >= 0 && | |
99 | mindelta <= INTERVAL && | |
100 | maxdelta >= 0 && | |
101 | maxdelta <= INTERVAL) logln(UnicodeString("PASS: Expected boundary at ") + expectedBoundary); | |
729e4ab9 | 102 | else dataerrln(UnicodeString("FAIL: Expected boundary at ") + expectedBoundary); |
b75a7d8f A |
103 | } |
104 | ||
105 | // ------------------------------------- | |
106 | ||
107 | void | |
108 | TimeZoneBoundaryTest::findDaylightBoundaryUsingTimeZone(UDate d, UBool startsInDST, UDate expectedBoundary) | |
109 | { | |
110 | TimeZone *zone = TimeZone::createDefault(); | |
111 | findDaylightBoundaryUsingTimeZone(d, startsInDST, expectedBoundary, zone); | |
112 | delete zone; | |
113 | } | |
114 | ||
115 | // ------------------------------------- | |
116 | ||
117 | void | |
118 | TimeZoneBoundaryTest::findDaylightBoundaryUsingTimeZone(UDate d, UBool startsInDST, UDate expectedBoundary, TimeZone* tz) | |
119 | { | |
120 | UErrorCode status = U_ZERO_ERROR; | |
121 | UnicodeString str; | |
122 | UDate min = d; | |
123 | UDate max = min + SIX_MONTHS; | |
124 | if (tz->inDaylightTime(d, status) != startsInDST) { | |
729e4ab9 | 125 | dataerrln("FAIL: " + tz->getID(str) + " inDaylightTime(" + dateToString(d) + ") != " + (startsInDST ? "true" : "false")); |
b75a7d8f A |
126 | startsInDST = !startsInDST; |
127 | } | |
729e4ab9 | 128 | if (failure(status, "TimeZone::inDaylightTime", TRUE)) return; |
b75a7d8f | 129 | if (tz->inDaylightTime(max, status) == startsInDST) { |
729e4ab9 | 130 | dataerrln("FAIL: " + tz->getID(str) + " inDaylightTime(" + dateToString(max) + ") != " + (startsInDST ? "false" : "true")); |
b75a7d8f A |
131 | return; |
132 | } | |
133 | if (failure(status, "TimeZone::inDaylightTime")) return; | |
134 | while ((max - min) > INTERVAL) { | |
135 | UDate mid = (min + max) / 2; | |
136 | UBool isIn = tz->inDaylightTime(mid, status); | |
137 | if (failure(status, "TimeZone::inDaylightTime")) return; | |
138 | if (isIn == startsInDST) { | |
139 | min = mid; | |
140 | } | |
141 | else { | |
142 | max = mid; | |
143 | } | |
144 | } | |
145 | logln(tz->getID(str) + " Before: " + showDate(min)); | |
146 | logln(tz->getID(str) + " After: " + showDate(max)); | |
147 | UDate mindelta = expectedBoundary - min; | |
148 | UDate maxdelta = max - expectedBoundary; | |
149 | if (mindelta >= 0 && | |
150 | mindelta <= INTERVAL && | |
151 | maxdelta >= 0 && | |
152 | maxdelta <= INTERVAL) logln(UnicodeString("PASS: Expected boundary at ") + expectedBoundary); | |
153 | else errln(UnicodeString("FAIL: Expected boundary at ") + expectedBoundary); | |
154 | } | |
155 | ||
156 | // ------------------------------------- | |
157 | /* | |
158 | UnicodeString* | |
159 | TimeZoneBoundaryTest::showDate(int32_t l) | |
160 | { | |
161 | return showDate(new Date(l)); | |
162 | } | |
163 | */ | |
164 | // ------------------------------------- | |
165 | ||
166 | UnicodeString | |
167 | TimeZoneBoundaryTest::showDate(UDate d) | |
168 | { | |
169 | int32_t y, m, day, h, min, sec; | |
170 | dateToFields(d, y, m, day, h, min, sec); | |
171 | return UnicodeString("") + y + "/" + showNN(m + 1) + "/" + | |
172 | showNN(day) + " " + showNN(h) + ":" + showNN(min) + | |
173 | " \"" + dateToString(d) + "\" = " + uprv_floor(d+0.5); | |
174 | } | |
175 | ||
176 | // ------------------------------------- | |
177 | ||
178 | UnicodeString | |
179 | TimeZoneBoundaryTest::showNN(int32_t n) | |
180 | { | |
374ca955 A |
181 | UnicodeString nStr; |
182 | if (n < 10) { | |
183 | nStr += UnicodeString("0", ""); | |
184 | } | |
185 | return nStr + n; | |
b75a7d8f A |
186 | } |
187 | ||
188 | // ------------------------------------- | |
189 | ||
190 | void | |
191 | TimeZoneBoundaryTest::verifyDST(UDate d, TimeZone* time_zone, UBool expUseDaylightTime, UBool expInDaylightTime, UDate expZoneOffset, UDate expDSTOffset) | |
192 | { | |
193 | UnicodeString str; | |
194 | UErrorCode status = U_ZERO_ERROR; | |
195 | logln("-- Verifying time " + dateToString(d) + " in zone " + time_zone->getID(str)); | |
196 | if (time_zone->inDaylightTime(d, status) == expInDaylightTime) | |
197 | logln(UnicodeString("PASS: inDaylightTime = ") + (time_zone->inDaylightTime(d, status)?"true":"false")); | |
73c04bcf | 198 | else |
729e4ab9 A |
199 | dataerrln(UnicodeString("FAIL: inDaylightTime = ") + (time_zone->inDaylightTime(d, status)?"true":"false")); |
200 | if (failure(status, "TimeZone::inDaylightTime", TRUE)) | |
73c04bcf | 201 | return; |
b75a7d8f A |
202 | if (time_zone->useDaylightTime() == expUseDaylightTime) |
203 | logln(UnicodeString("PASS: useDaylightTime = ") + (time_zone->useDaylightTime()?"true":"false")); | |
73c04bcf | 204 | else |
729e4ab9 | 205 | dataerrln(UnicodeString("FAIL: useDaylightTime = ") + (time_zone->useDaylightTime()?"true":"false")); |
73c04bcf A |
206 | if (time_zone->getRawOffset() == expZoneOffset) |
207 | logln(UnicodeString("PASS: getRawOffset() = ") + (expZoneOffset / ONE_HOUR)); | |
208 | else | |
729e4ab9 | 209 | dataerrln(UnicodeString("FAIL: getRawOffset() = ") + (time_zone->getRawOffset() / ONE_HOUR) + "; expected " + (expZoneOffset / ONE_HOUR)); |
73c04bcf | 210 | |
b75a7d8f A |
211 | GregorianCalendar *gc = new GregorianCalendar(time_zone->clone(), status); |
212 | gc->setTime(d, status); | |
213 | if (failure(status, "GregorianCalendar::setTime")) return; | |
214 | int32_t offset = time_zone->getOffset((uint8_t)gc->get(UCAL_ERA, status), | |
215 | gc->get(UCAL_YEAR, status), gc->get(UCAL_MONTH, status), | |
216 | gc->get(UCAL_DATE, status), (uint8_t)gc->get(UCAL_DAY_OF_WEEK, status), | |
217 | ((gc->get(UCAL_HOUR_OF_DAY, status) * 60 + gc->get(UCAL_MINUTE, status)) * 60 + gc->get(UCAL_SECOND, status)) * 1000 + gc->get(UCAL_MILLISECOND, status), | |
218 | status); | |
219 | if (failure(status, "GregorianCalendar::get")) return; | |
220 | if (offset == expDSTOffset) logln(UnicodeString("PASS: getOffset() = ") + (offset / ONE_HOUR)); | |
729e4ab9 | 221 | else dataerrln(UnicodeString("FAIL: getOffset() = ") + (offset / ONE_HOUR) + "; expected " + (expDSTOffset / ONE_HOUR)); |
b75a7d8f A |
222 | delete gc; |
223 | } | |
224 | ||
225 | // ------------------------------------- | |
73c04bcf A |
226 | /** |
227 | * Check that the given year/month/dom/hour maps to and from the | |
228 | * given epochHours. This verifies the functioning of the | |
229 | * calendar and time zone in conjunction with one another, | |
230 | * including the calendar time->fields and fields->time and | |
231 | * the time zone getOffset method. | |
232 | * | |
233 | * @param epochHours hours after Jan 1 1970 0:00 GMT. | |
234 | */ | |
235 | void TimeZoneBoundaryTest::verifyMapping(Calendar& cal, int year, int month, int dom, int hour, | |
236 | double epochHours) { | |
237 | double H = 3600000.0; | |
238 | UErrorCode status = U_ZERO_ERROR; | |
239 | cal.clear(); | |
240 | cal.set(year, month, dom, hour, 0, 0); | |
241 | UDate e = cal.getTime(status)/ H; | |
242 | UDate ed = (epochHours * H); | |
243 | if (e == epochHours) { | |
244 | logln(UnicodeString("Ok: ") + year + "/" + (month+1) + "/" + dom + " " + hour + ":00 => " + | |
245 | e + " (" + ed + ")"); | |
246 | } else { | |
729e4ab9 | 247 | dataerrln(UnicodeString("FAIL: ") + year + "/" + (month+1) + "/" + dom + " " + hour + ":00 => " + |
73c04bcf A |
248 | e + " (" + (e * H) + ")" + |
249 | ", expected " + epochHours + " (" + ed + ")"); | |
250 | } | |
251 | cal.setTime(ed, status); | |
252 | if (cal.get(UCAL_YEAR, status) == year && | |
253 | cal.get(UCAL_MONTH, status) == month && | |
254 | cal.get(UCAL_DATE, status) == dom && | |
255 | cal.get(UCAL_MILLISECONDS_IN_DAY, status) == hour * 3600000) { | |
256 | logln(UnicodeString("Ok: ") + epochHours + " (" + ed + ") => " + | |
257 | cal.get(UCAL_YEAR, status) + "/" + | |
258 | (cal.get(UCAL_MONTH, status)+1) + "/" + | |
259 | cal.get(UCAL_DATE, status) + " " + | |
260 | cal.get(UCAL_MILLISECOND, status)/H); | |
261 | } else { | |
729e4ab9 | 262 | dataerrln(UnicodeString("FAIL: ") + epochHours + " (" + ed + ") => " + |
73c04bcf A |
263 | cal.get(UCAL_YEAR, status) + "/" + |
264 | (cal.get(UCAL_MONTH, status)+1) + "/" + | |
265 | cal.get(UCAL_DATE, status) + " " + | |
266 | cal.get(UCAL_MILLISECOND, status)/H + | |
267 | ", expected " + year + "/" + (month+1) + "/" + dom + | |
268 | " " + hour); | |
269 | } | |
270 | } | |
271 | ||
b75a7d8f A |
272 | /** |
273 | * Test the behavior of SimpleTimeZone at the transition into and out of DST. | |
274 | * Use a binary search to find boundaries. | |
275 | */ | |
276 | void | |
277 | TimeZoneBoundaryTest::TestBoundaries() | |
278 | { | |
73c04bcf A |
279 | UErrorCode status = U_ZERO_ERROR; |
280 | TimeZone* pst = TimeZone::createTimeZone("PST"); | |
281 | Calendar* tempcal = Calendar::createInstance(pst, status); | |
282 | if(U_SUCCESS(status)){ | |
283 | verifyMapping(*tempcal, 1997, Calendar::APRIL, 3, 0, 238904.0); | |
284 | verifyMapping(*tempcal, 1997, Calendar::APRIL, 4, 0, 238928.0); | |
285 | verifyMapping(*tempcal, 1997, Calendar::APRIL, 5, 0, 238952.0); | |
286 | verifyMapping(*tempcal, 1997, Calendar::APRIL, 5, 23, 238975.0); | |
287 | verifyMapping(*tempcal, 1997, Calendar::APRIL, 6, 0, 238976.0); | |
288 | verifyMapping(*tempcal, 1997, Calendar::APRIL, 6, 1, 238977.0); | |
289 | verifyMapping(*tempcal, 1997, Calendar::APRIL, 6, 3, 238978.0); | |
290 | }else{ | |
729e4ab9 | 291 | dataerrln("Could not create calendar. Error: %s", u_errorName(status)); |
73c04bcf A |
292 | } |
293 | TimeZone* utc = TimeZone::createTimeZone("UTC"); | |
294 | Calendar* utccal = Calendar::createInstance(utc, status); | |
295 | if(U_SUCCESS(status)){ | |
296 | verifyMapping(*utccal, 1997, Calendar::APRIL, 6, 0, 238968.0); | |
297 | }else{ | |
729e4ab9 | 298 | dataerrln("Could not create calendar. Error: %s", u_errorName(status)); |
73c04bcf A |
299 | } |
300 | TimeZone* save = TimeZone::createDefault(); | |
301 | TimeZone::setDefault(*pst); | |
729e4ab9 A |
302 | |
303 | if (tempcal != NULL) { | |
304 | // DST changeover for PST is 4/6/1997 at 2 hours past midnight | |
305 | // at 238978.0 epoch hours. | |
306 | tempcal->clear(); | |
307 | tempcal->set(1997, Calendar::APRIL, 6); | |
308 | UDate d = tempcal->getTime(status); | |
73c04bcf | 309 | |
729e4ab9 A |
310 | // i is minutes past midnight standard time |
311 | for (int i=-120; i<=180; i+=60) | |
312 | { | |
313 | UBool inDST = (i >= 120); | |
314 | tempcal->setTime(d + i*60*1000, status); | |
315 | verifyDST(tempcal->getTime(status),pst, TRUE, inDST, -8*ONE_HOUR,inDST ? -7*ONE_HOUR : -8*ONE_HOUR); | |
316 | } | |
73c04bcf A |
317 | } |
318 | TimeZone::setDefault(*save); | |
319 | delete save; | |
320 | delete utccal; | |
321 | delete tempcal; | |
322 | ||
b75a7d8f A |
323 | #if 1 |
324 | { | |
325 | logln("--- Test a ---"); | |
326 | UDate d = date(97, UCAL_APRIL, 6); | |
327 | TimeZone *z = TimeZone::createTimeZone("PST"); | |
328 | for (int32_t i = 60; i <= 180; i += 15) { | |
329 | UBool inDST = (i >= 120); | |
330 | UDate e = d + i * 60 * 1000; | |
331 | verifyDST(e, z, TRUE, inDST, - 8 * ONE_HOUR, inDST ? - 7 * ONE_HOUR: - 8 * ONE_HOUR); | |
332 | } | |
333 | delete z; | |
334 | } | |
335 | #endif | |
336 | #if 1 | |
337 | { | |
338 | logln("--- Test b ---"); | |
339 | TimeZone *tz; | |
340 | TimeZone::setDefault(*(tz = TimeZone::createTimeZone("PST"))); | |
341 | delete tz; | |
342 | logln("========================================"); | |
343 | findDaylightBoundaryUsingDate(date(97, 0, 1), "PST", PST_1997_BEG); | |
344 | logln("========================================"); | |
345 | findDaylightBoundaryUsingDate(date(97, 6, 1), "PDT", PST_1997_END); | |
346 | } | |
347 | #endif | |
348 | #if 1 | |
349 | { | |
350 | logln("--- Test c ---"); | |
351 | logln("========================================"); | |
352 | TimeZone* z = TimeZone::createTimeZone("Australia/Adelaide"); | |
353 | findDaylightBoundaryUsingTimeZone(date(97, 0, 1), TRUE, 859653000000.0, z); | |
354 | logln("========================================"); | |
355 | findDaylightBoundaryUsingTimeZone(date(97, 6, 1), FALSE, 877797000000.0, z); | |
356 | delete z; | |
357 | } | |
358 | #endif | |
359 | #if 1 | |
360 | { | |
361 | logln("--- Test d ---"); | |
362 | logln("========================================"); | |
363 | findDaylightBoundaryUsingTimeZone(date(97, 0, 1), FALSE, PST_1997_BEG); | |
364 | logln("========================================"); | |
365 | findDaylightBoundaryUsingTimeZone(date(97, 6, 1), TRUE, PST_1997_END); | |
366 | } | |
367 | #endif | |
368 | #if 0 | |
369 | { | |
370 | logln("--- Test e ---"); | |
371 | TimeZone *z = TimeZone::createDefault(); | |
372 | logln(UnicodeString("") + z->getOffset(1, 97, 3, 4, 6, 0) + " " + date(97, 3, 4)); | |
373 | logln(UnicodeString("") + z->getOffset(1, 97, 3, 5, 7, 0) + " " + date(97, 3, 5)); | |
374 | logln(UnicodeString("") + z->getOffset(1, 97, 3, 6, 1, 0) + " " + date(97, 3, 6)); | |
375 | logln(UnicodeString("") + z->getOffset(1, 97, 3, 7, 2, 0) + " " + date(97, 3, 7)); | |
376 | delete z; | |
377 | } | |
378 | #endif | |
379 | } | |
380 | ||
381 | // ------------------------------------- | |
382 | ||
383 | void | |
384 | TimeZoneBoundaryTest::testUsingBinarySearch(SimpleTimeZone* tz, UDate d, UDate expectedBoundary) | |
385 | { | |
386 | UErrorCode status = U_ZERO_ERROR; | |
387 | UDate min = d; | |
388 | UDate max = min + SIX_MONTHS; | |
389 | UBool startsInDST = tz->inDaylightTime(d, status); | |
729e4ab9 | 390 | if (failure(status, "SimpleTimeZone::inDaylightTime", TRUE)) return; |
b75a7d8f | 391 | if (tz->inDaylightTime(max, status) == startsInDST) { |
73c04bcf | 392 | errln("Error: inDaylightTime(" + dateToString(max) + ") != " + ((!startsInDST)?"true":"false")); |
b75a7d8f A |
393 | } |
394 | if (failure(status, "SimpleTimeZone::inDaylightTime")) return; | |
395 | while ((max - min) > INTERVAL) { | |
396 | UDate mid = (min + max) / 2; | |
397 | if (tz->inDaylightTime(mid, status) == startsInDST) { | |
398 | min = mid; | |
399 | } | |
400 | else { | |
401 | max = mid; | |
402 | } | |
403 | if (failure(status, "SimpleTimeZone::inDaylightTime")) return; | |
404 | } | |
405 | logln("Binary Search Before: " + showDate(min)); | |
406 | logln("Binary Search After: " + showDate(max)); | |
407 | UDate mindelta = expectedBoundary - min; | |
408 | UDate maxdelta = max - expectedBoundary; | |
409 | if (mindelta >= 0 && | |
410 | mindelta <= INTERVAL && | |
411 | maxdelta >= 0 && | |
412 | maxdelta <= INTERVAL) logln(UnicodeString("PASS: Expected boundary at ") + expectedBoundary); | |
413 | else errln(UnicodeString("FAIL: Expected boundary at ") + expectedBoundary); | |
414 | } | |
415 | ||
416 | // ------------------------------------- | |
417 | ||
418 | /** | |
419 | * Test the handling of the "new" rules; that is, rules other than nth Day of week. | |
420 | */ | |
421 | void | |
422 | TimeZoneBoundaryTest::TestNewRules() | |
423 | { | |
424 | #if 1 | |
425 | { | |
426 | UErrorCode status = U_ZERO_ERROR; | |
427 | SimpleTimeZone *tz; | |
428 | logln("-----------------------------------------------------------------"); | |
429 | logln("Aug 2ndTues .. Mar 15"); | |
430 | tz = new SimpleTimeZone(- 8 * (int32_t)ONE_HOUR, "Test_1", UCAL_AUGUST, 2, UCAL_TUESDAY, 2 * (int32_t)ONE_HOUR, UCAL_MARCH, 15, 0, 2 * (int32_t)ONE_HOUR, status); | |
431 | logln("========================================"); | |
432 | testUsingBinarySearch(tz, date(97, 0, 1), 858416400000.0); | |
433 | logln("========================================"); | |
434 | testUsingBinarySearch(tz, date(97, 6, 1), 871380000000.0); | |
435 | delete tz; | |
436 | logln("-----------------------------------------------------------------"); | |
437 | logln("Apr Wed>=14 .. Sep Sun<=20"); | |
438 | tz = new SimpleTimeZone(- 8 * (int32_t)ONE_HOUR, "Test_2", UCAL_APRIL, 14, - UCAL_WEDNESDAY, 2 *(int32_t)ONE_HOUR, UCAL_SEPTEMBER, - 20, - UCAL_SUNDAY, 2 * (int32_t)ONE_HOUR, status); | |
439 | logln("========================================"); | |
440 | testUsingBinarySearch(tz, date(97, 0, 1), 861184800000.0); | |
441 | logln("========================================"); | |
442 | testUsingBinarySearch(tz, date(97, 6, 1), 874227600000.0); | |
443 | delete tz; | |
444 | } | |
445 | #endif | |
446 | } | |
447 | ||
448 | // ------------------------------------- | |
449 | ||
450 | void | |
451 | TimeZoneBoundaryTest::findBoundariesStepwise(int32_t year, UDate interval, TimeZone* z, int32_t expectedChanges) | |
452 | { | |
453 | UErrorCode status = U_ZERO_ERROR; | |
454 | UnicodeString str; | |
455 | UDate d = date(year - 1900, UCAL_JANUARY, 1); | |
456 | UDate time = d; | |
457 | UDate limit = time + ONE_YEAR + ONE_DAY; | |
458 | UBool lastState = z->inDaylightTime(d, status); | |
729e4ab9 | 459 | if (failure(status, "TimeZone::inDaylightTime", TRUE)) return; |
b75a7d8f A |
460 | int32_t changes = 0; |
461 | logln(UnicodeString("-- Zone ") + z->getID(str) + " starts in " + year + " with DST = " + (lastState?"true":"false")); | |
462 | logln(UnicodeString("useDaylightTime = ") + (z->useDaylightTime()?"true":"false")); | |
463 | while (time < limit) { | |
464 | d = time; | |
465 | UBool state = z->inDaylightTime(d, status); | |
466 | if (failure(status, "TimeZone::inDaylightTime")) return; | |
467 | if (state != lastState) { | |
468 | logln(UnicodeString(state ? "Entry ": "Exit ") + "at " + d); | |
469 | lastState = state;++changes; | |
470 | } | |
471 | time += interval; | |
472 | } | |
473 | if (changes == 0) { | |
474 | if (!lastState && | |
475 | !z->useDaylightTime()) logln("No DST"); | |
476 | else errln("FAIL: DST all year, or no DST with true useDaylightTime"); | |
477 | } | |
478 | else if (changes != 2) { | |
479 | errln(UnicodeString("FAIL: ") + changes + " changes seen; should see 0 or 2"); | |
480 | } | |
481 | else if (!z->useDaylightTime()) { | |
482 | errln("FAIL: useDaylightTime false but 2 changes seen"); | |
483 | } | |
484 | if (changes != expectedChanges) { | |
729e4ab9 | 485 | dataerrln(UnicodeString("FAIL: ") + changes + " changes seen; expected " + expectedChanges); |
b75a7d8f A |
486 | } |
487 | } | |
488 | ||
489 | // ------------------------------------- | |
490 | ||
491 | /** | |
492 | * This test is problematic. It makes assumptions about the behavior | |
493 | * of specific zones. Since ICU's zone table is based on the Olson | |
494 | * zones (the UNIX zones), and those change from time to time, this | |
495 | * test can fail after a zone table update. If that happens, the | |
496 | * selected zones need to be updated to have the behavior | |
497 | * expected. That is, they should have DST, not have DST, and have DST | |
498 | * -- other than that this test isn't picky. 12/3/99 aliu | |
499 | * | |
500 | * Test the behavior of SimpleTimeZone at the transition into and out of DST. | |
501 | * Use a stepwise march to find boundaries. | |
502 | */ | |
503 | void | |
504 | TimeZoneBoundaryTest::TestStepwise() | |
505 | { | |
374ca955 | 506 | TimeZone *zone = TimeZone::createTimeZone("America/New_York"); |
b75a7d8f A |
507 | findBoundariesStepwise(1997, ONE_DAY, zone, 2); |
508 | delete zone; | |
509 | zone = TimeZone::createTimeZone("UTC"); // updated 12/3/99 aliu | |
510 | findBoundariesStepwise(1997, ONE_DAY, zone, 0); | |
511 | delete zone; | |
512 | zone = TimeZone::createTimeZone("Australia/Adelaide"); | |
513 | findBoundariesStepwise(1997, ONE_DAY, zone, 2); | |
514 | delete zone; | |
515 | } | |
516 | ||
517 | #endif /* #if !UCONFIG_NO_FORMATTING */ |