]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/tzregts.cpp
ICU-6.2.6.tar.gz
[apple/icu.git] / icuSources / test / intltest / tzregts.cpp
1 /********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2003, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6
7 #include "unicode/utypes.h"
8
9 #if !UCONFIG_NO_FORMATTING
10
11 #include "unicode/simpletz.h"
12 #include "unicode/smpdtfmt.h"
13 #include "unicode/strenum.h"
14 #include "tzregts.h"
15 #include "calregts.h"
16 #include "cmemory.h"
17
18 // *****************************************************************************
19 // class TimeZoneRegressionTest
20 // *****************************************************************************
21
22 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
23
24 void
25 TimeZoneRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
26 {
27 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
28 switch (index) {
29
30 CASE(0, Test4052967);
31 CASE(1, Test4073209);
32 CASE(2, Test4073215);
33 CASE(3, Test4084933);
34 CASE(4, Test4096952);
35 CASE(5, Test4109314);
36 CASE(6, Test4126678);
37 CASE(7, Test4151406);
38 CASE(8, Test4151429);
39 CASE(9, Test4154537);
40 CASE(10, Test4154542);
41 CASE(11, Test4154650);
42 CASE(12, Test4154525);
43 CASE(13, Test4162593);
44 CASE(14, TestJ186);
45 CASE(15, TestJ449);
46 CASE(16, TestJDK12API);
47
48 default: name = ""; break;
49 }
50 }
51
52 UBool
53 TimeZoneRegressionTest::failure(UErrorCode status, const char* msg)
54 {
55 if(U_FAILURE(status)) {
56 errln(UnicodeString("FAIL: ") + msg + " failed, error " + u_errorName(status));
57 return TRUE;
58 }
59
60 return FALSE;
61 }
62
63 /**
64 * @bug 4052967
65 */
66 void TimeZoneRegressionTest:: Test4052967() {
67 // {sfb} not applicable in C++ ?
68 /*logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***");
69 logln("user.timezone:" + System.getProperty("user.timezone", "<not set>"));
70 logln(new Date().toString());
71 logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");*/
72 }
73
74 /**
75 * @bug 4073209
76 */
77 void TimeZoneRegressionTest:: Test4073209() {
78 TimeZone *z1 = TimeZone::createTimeZone("PST");
79 TimeZone *z2 = TimeZone::createTimeZone("PST");
80 if (z1 == z2)
81 errln("Fail: TimeZone should return clones");
82 delete z1;
83 delete z2;
84 }
85
86 UDate TimeZoneRegressionTest::findTransitionBinary(const SimpleTimeZone& tz, UDate min, UDate max) {
87 UErrorCode status = U_ZERO_ERROR;
88 UBool startsInDST = tz.inDaylightTime(min, status);
89 if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0;
90 if (tz.inDaylightTime(max, status) == startsInDST) {
91 logln((UnicodeString)"Error: inDaylightTime() != " + ((!startsInDST)?"TRUE":"FALSE"));
92 return 0;
93 }
94 if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0;
95 while ((max - min) > 100) { // Min accuracy in ms
96 UDate mid = (min + max) / 2;
97 if (tz.inDaylightTime(mid, status) == startsInDST) {
98 min = mid;
99 } else {
100 max = mid;
101 }
102 if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0;
103 }
104 return (min + max) / 2;
105 }
106
107 UDate TimeZoneRegressionTest::findTransitionStepwise(const SimpleTimeZone& tz, UDate min, UDate max) {
108 UErrorCode status = U_ZERO_ERROR;
109 UBool startsInDST = tz.inDaylightTime(min, status);
110 if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0;
111 while (min < max) {
112 if (tz.inDaylightTime(min, status) != startsInDST) {
113 return min;
114 }
115 if (failure(status, "SimpleTimeZone::inDaylightTime")) return 0;
116 min += (UDate)24*60*60*1000; // one day
117 }
118 return 0;
119 }
120
121 /**
122 * @bug 4073215
123 */
124 // {sfb} will this work using a Calendar?
125 void TimeZoneRegressionTest:: Test4073215()
126 {
127 UErrorCode status = U_ZERO_ERROR;
128 UnicodeString str, str2;
129 SimpleTimeZone *z = new SimpleTimeZone(0, "GMT");
130 if (z->useDaylightTime())
131 errln("Fail: Fix test to start with non-DST zone");
132 z->setStartRule(UCAL_FEBRUARY, 1, UCAL_SUNDAY, 0, status);
133 failure(status, "z->setStartRule()");
134 z->setEndRule(UCAL_MARCH, -1, UCAL_SUNDAY, 0, status);
135 failure(status, "z->setStartRule()");
136 if (!z->useDaylightTime())
137 errln("Fail: DST not active");
138
139 GregorianCalendar cal(1997, UCAL_JANUARY, 31, status);
140 if(U_FAILURE(status)) {
141 errln("Error creating calendar %s", u_errorName(status));
142 return;
143 }
144 failure(status, "new GregorianCalendar");
145 cal.adoptTimeZone(z);
146
147 SimpleDateFormat sdf((UnicodeString)"E d MMM yyyy G HH:mm", status);
148 if(U_FAILURE(status)) {
149 errln("Error creating date format %s", u_errorName(status));
150 return;
151 }
152 sdf.setCalendar(cal);
153 failure(status, "new SimpleDateFormat");
154
155 UDate jan31, mar1, mar31;
156
157 UBool indt = z->inDaylightTime(jan31=cal.getTime(status), status);
158 failure(status, "inDaylightTime or getTime call on Jan 31");
159 if (indt) {
160 errln("Fail: Jan 31 inDaylightTime=TRUE, exp FALSE");
161 }
162 cal.set(1997, UCAL_MARCH, 1);
163 indt = z->inDaylightTime(mar1=cal.getTime(status), status);
164 failure(status, "inDaylightTime or getTime call on Mar 1");
165 if (!indt) {
166 UnicodeString str;
167 sdf.format(cal.getTime(status), str);
168 failure(status, "getTime");
169 errln((UnicodeString)"Fail: " + str + " inDaylightTime=FALSE, exp TRUE");
170 }
171 cal.set(1997, UCAL_MARCH, 31);
172 indt = z->inDaylightTime(mar31=cal.getTime(status), status);
173 failure(status, "inDaylightTime or getTime call on Mar 31");
174 if (indt) {
175 errln("Fail: Mar 31 inDaylightTime=TRUE, exp FALSE");
176 }
177
178 /*
179 cal.set(1997, Calendar::DECEMBER, 31);
180 UDate dec31 = cal.getTime(status);
181 failure(status, "getTime");
182 UDate trans = findTransitionStepwise(*z, jan31, dec31);
183 logln((UnicodeString)"Stepwise from " +
184 sdf.format(jan31, str.remove()) + "; transition at " +
185 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE"));
186 trans = findTransitionStepwise(*z, mar1, dec31);
187 logln((UnicodeString)"Stepwise from " +
188 sdf.format(mar1, str.remove()) + "; transition at " +
189 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE"));
190 trans = findTransitionStepwise(*z, mar31, dec31);
191 logln((UnicodeString)"Stepwise from " +
192 sdf.format(mar31, str.remove()) + "; transition at " +
193 (trans?sdf.format(trans, str2.remove()):(UnicodeString)"NONE"));
194 */
195 }
196
197 /**
198 * @bug 4084933
199 * The expected behavior of TimeZone around the boundaries is:
200 * (Assume transition time of 2:00 AM)
201 * day of onset 1:59 AM STD = display name 1:59 AM ST
202 * 2:00 AM STD = display name 3:00 AM DT
203 * day of end 0:59 AM STD = display name 1:59 AM DT
204 * 1:00 AM STD = display name 1:00 AM ST
205 */
206 void TimeZoneRegressionTest:: Test4084933() {
207 UErrorCode status = U_ZERO_ERROR;
208 TimeZone *tz = TimeZone::createTimeZone("PST");
209
210 int32_t offset1 = tz->getOffset(1,
211 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000), status);
212 int32_t offset2 = tz->getOffset(1,
213 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000)-1, status);
214
215 int32_t offset3 = tz->getOffset(1,
216 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (1*60*60*1000), status);
217 int32_t offset4 = tz->getOffset(1,
218 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (1*60*60*1000)-1, status);
219
220 /*
221 * The following was added just for consistency. It shows that going *to* Daylight
222 * Savings Time (PDT) does work at 2am.
223 */
224
225 int32_t offset5 = tz->getOffset(1,
226 1997, UCAL_APRIL, 6, UCAL_SUNDAY, (2*60*60*1000), status);
227 int32_t offset6 = tz->getOffset(1,
228 1997, UCAL_APRIL, 6, UCAL_SUNDAY, (2*60*60*1000)-1, status);
229
230 int32_t offset7 = tz->getOffset(1,
231 1997, UCAL_APRIL, 6, UCAL_SUNDAY, (1*60*60*1000), status);
232 int32_t offset8 = tz->getOffset(1,
233 1997, UCAL_APRIL, 6, UCAL_SUNDAY, (1*60*60*1000)-1, status);
234
235 int32_t SToffset = (int32_t)(-8 * 60*60*1000L);
236 int32_t DToffset = (int32_t)(-7 * 60*60*1000L);
237 if (offset1 != SToffset || offset2 != SToffset ||
238 offset3 != SToffset || offset4 != DToffset ||
239 offset5 != DToffset || offset6 != SToffset ||
240 offset7 != SToffset || offset8 != SToffset
241 || U_FAILURE(status))
242 errln("Fail: TimeZone misbehaving");
243
244 delete tz;
245 }
246
247 /**
248 * @bug 4096952
249 */
250 void TimeZoneRegressionTest:: Test4096952() {
251 // {sfb} serialization not applicable
252 /*
253 UnicodeString ZONES [] = { UnicodeString("GMT"), UnicodeString("MET"), UnicodeString("IST") };
254 UBool pass = TRUE;
255 //try {
256 for (int32_t i=0; i < ZONES.length; ++i) {
257 TimeZone *zone = TimeZone::createTimeZone(ZONES[i]);
258 UnicodeString id;
259 if (zone->getID(id) != ZONES[i])
260 errln("Fail: Test broken; zones not instantiating");
261
262 ByteArrayOutputStream baos;
263 ObjectOutputStream ostream =
264 new ObjectOutputStream(baos = new
265 ByteArrayOutputStream());
266 ostream.writeObject(zone);
267 ostream.close();
268 baos.close();
269 ObjectInputStream istream =
270 new ObjectInputStream(new
271 ByteArrayInputStream(baos.toByteArray()));
272 TimeZone frankenZone = (TimeZone) istream.readObject();
273 //logln("Zone: " + zone);
274 //logln("FrankenZone: " + frankenZone);
275 if (!zone.equals(frankenZone)) {
276 logln("TimeZone " + zone.getID() +
277 " not equal to serialized/deserialized one");
278 pass = false;
279 }
280 }
281 if (!pass) errln("Fail: TimeZone serialization/equality bug");
282 }
283 catch (IOException e) {
284 errln("Fail: " + e);
285 e.print32_tStackTrace();
286 }
287 catch (ClassNotFoundException e) {
288 errln("Fail: " + e);
289 e.print32_tStackTrace();
290 }
291 */
292 }
293
294 /**
295 * @bug 4109314
296 */
297 void TimeZoneRegressionTest:: Test4109314() {
298 UErrorCode status = U_ZERO_ERROR;
299 GregorianCalendar *testCal = (GregorianCalendar*)Calendar::createInstance(status);
300 if(U_FAILURE(status)) {
301 errln("Error creating calendar %s", u_errorName(status));
302 delete testCal;
303 return;
304 }
305 failure(status, "Calendar::createInstance");
306 TimeZone *PST = TimeZone::createTimeZone("PST");
307 /*Object[] testData = {
308 PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0),
309 PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0),
310 };*/
311 UDate testData [] = {
312 CalendarRegressionTest::makeDate(98,UCAL_APRIL,4,22,0),
313 CalendarRegressionTest::makeDate(98, UCAL_APRIL,5,6,0),
314 CalendarRegressionTest::makeDate(98,UCAL_OCTOBER,24,22,0),
315 CalendarRegressionTest::makeDate(98,UCAL_OCTOBER,25,6,0)
316 };
317 UBool pass = TRUE;
318 for (int32_t i = 0; i < 4; i+=2) {
319 //testCal->setTimeZone((TimeZone) testData[i]);
320 testCal->setTimeZone(*PST);
321 UDate t = testData[i];
322 UDate end = testData[i+1];
323 while(testCal->getTime(status) < end) {
324 testCal->setTime(t, status);
325 if ( ! checkCalendar314(testCal, PST))
326 pass = FALSE;
327 t += 60*60*1000.0;
328 }
329 }
330 if ( ! pass)
331 errln("Fail: TZ API inconsistent");
332
333 delete testCal;
334 delete PST;
335 }
336
337 UBool
338 TimeZoneRegressionTest::checkCalendar314(GregorianCalendar *testCal, TimeZone *testTZ)
339 {
340 UErrorCode status = U_ZERO_ERROR;
341 // GregorianCalendar testCal = (GregorianCalendar)aCal.clone();
342
343 int32_t tzOffset, tzRawOffset;
344 float tzOffsetFloat,tzRawOffsetFloat;
345 // Here is where the user made an error. They were passing in the value of
346 // the MILLSECOND field; you need to pass in the millis in the day in STANDARD
347 // time.
348 UDate millis = testCal->get(UCAL_MILLISECOND, status) +
349 1000.0 * (testCal->get(UCAL_SECOND, status) +
350 60.0 * (testCal->get(UCAL_MINUTE, status) +
351 60.0 * (testCal->get(UCAL_HOUR_OF_DAY, status)))) -
352 testCal->get(UCAL_DST_OFFSET, status);
353
354 /* Fix up millis to be in range. ASSUME THAT WE ARE NOT AT THE
355 * BEGINNING OR END OF A MONTH. We must add this code because
356 * getOffset() has been changed to be more strict about the parameters
357 * it receives -- it turns out that this test was passing in illegal
358 * values. */
359 int32_t date = testCal->get(UCAL_DATE, status);
360 int32_t dow = testCal->get(UCAL_DAY_OF_WEEK, status);
361 while(millis < 0) {
362 millis += U_MILLIS_PER_DAY;
363 --date;
364 dow = UCAL_SUNDAY + ((dow - UCAL_SUNDAY + 6) % 7);
365 }
366 while (millis >= U_MILLIS_PER_DAY) {
367 millis -= U_MILLIS_PER_DAY;
368 ++date;
369 dow = UCAL_SUNDAY + ((dow - UCAL_SUNDAY + 1) % 7);
370 }
371
372 tzOffset = testTZ->getOffset((uint8_t)testCal->get(UCAL_ERA, status),
373 testCal->get(UCAL_YEAR, status),
374 testCal->get(UCAL_MONTH, status),
375 date,
376 (uint8_t)dow,
377 (int32_t)millis,
378 status);
379 tzRawOffset = testTZ->getRawOffset();
380 tzOffsetFloat = (float)tzOffset/(float)3600000;
381 tzRawOffsetFloat = (float)tzRawOffset/(float)3600000;
382
383 UDate testDate = testCal->getTime(status);
384
385 UBool inDaylightTime = testTZ->inDaylightTime(testDate, status);
386 SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)"MM/dd/yyyy HH:mm", status);
387 sdf->setCalendar(*testCal);
388 UnicodeString inDaylightTimeString;
389
390 UBool passed;
391
392 if(inDaylightTime)
393 {
394 inDaylightTimeString = " DST ";
395 passed = (tzOffset == (tzRawOffset + 3600000));
396 }
397 else
398 {
399 inDaylightTimeString = " ";
400 passed = (tzOffset == tzRawOffset);
401 }
402
403 UnicodeString output;
404 FieldPosition pos(0);
405 output = testTZ->getID(output) + " " + sdf->format(testDate, output, pos) +
406 " Offset(" + tzOffsetFloat + ")" +
407 " RawOffset(" + tzRawOffsetFloat + ")" +
408 " " + millis/(float)3600000 + " " +
409 inDaylightTimeString;
410
411 if (passed)
412 output += " ";
413 else
414 output += "ERROR";
415
416 if (passed)
417 logln(output);
418 else
419 errln(output);
420
421 delete sdf;
422 return passed;
423 }
424
425 /**
426 * @bug 4126678
427 * CANNOT REPRODUDE
428 *
429 * Yet another _alleged_ bug in TimeZone::getOffset(), a method that never
430 * should have been made public. It's simply too hard to use correctly.
431 *
432 * The original test code failed to do the following:
433 * (1) Call Calendar::setTime() before getting the fields!
434 * (2) Use the right millis (as usual) for getOffset(); they were passing
435 * in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
436 * When you fix these two problems, the test passes, as expected.
437 */
438 void TimeZoneRegressionTest:: Test4126678()
439 {
440 UErrorCode status = U_ZERO_ERROR;
441 Calendar *cal = Calendar::createInstance(status);
442 if(U_FAILURE(status)) {
443 errln("Error creating calendar %s", u_errorName(status));
444 delete cal;
445 return;
446 }
447 failure(status, "Calendar::createInstance");
448 TimeZone *tz = TimeZone::createTimeZone("PST");
449 cal->adoptTimeZone(tz);
450
451 cal->set(1998 - 1900, UCAL_APRIL, 5, 10, 0);
452 //Date dt = new Date(1998-1900, Calendar::APRIL, 5, 10, 0);
453
454 if (! tz->useDaylightTime() || U_FAILURE(status))
455 errln("We're not in Daylight Savings Time and we should be.\n");
456
457 //cal.setTime(dt);
458 int32_t era = cal->get(UCAL_ERA, status);
459 int32_t year = cal->get(UCAL_YEAR, status);
460 int32_t month = cal->get(UCAL_MONTH, status);
461 int32_t day = cal->get(UCAL_DATE, status);
462 int32_t dayOfWeek = cal->get(UCAL_DAY_OF_WEEK, status);
463 int32_t millis = cal->get(UCAL_MILLISECOND, status) +
464 (cal->get(UCAL_SECOND, status) +
465 (cal->get(UCAL_MINUTE, status) +
466 (cal->get(UCAL_HOUR, status) * 60) * 60) * 1000) -
467 cal->get(UCAL_DST_OFFSET, status);
468
469 failure(status, "cal->get");
470 int32_t offset = tz->getOffset((uint8_t)era, year, month, day, (uint8_t)dayOfWeek, millis, status);
471 int32_t raw_offset = tz->getRawOffset();
472 if (offset == raw_offset)
473 errln("Offsets should not match when in DST");
474
475 delete cal;
476 }
477
478 /**
479 * @bug 4151406
480 * TimeZone::getAvailableIDs(int32_t) throws exception for certain values,
481 * due to a faulty constant in TimeZone::java.
482 */
483 void TimeZoneRegressionTest:: Test4151406() {
484 int32_t max = 0;
485 for (int32_t h=-28; h<=30; ++h) {
486 // h is in half-hours from GMT; rawoffset is in millis
487 int32_t rawoffset = h * 1800000;
488 int32_t hh = (h<0) ? -h : h;
489 UnicodeString hname = UnicodeString((h<0) ? "GMT-" : "GMT+") +
490 ((hh/2 < 10) ? "0" : "") +
491 (hh/2) + ':' +
492 ((hh%2==0) ? "00" : "30");
493 //try {
494 UErrorCode ec = U_ZERO_ERROR;
495 int32_t count;
496 StringEnumeration* ids = TimeZone::createEnumeration(rawoffset);
497 count = ids->count(ec);
498 if (count> max)
499 max = count;
500 if (count > 0) {
501 logln(hname + ' ' + (UnicodeString)count + (UnicodeString)" e.g. " + *ids->snext(ec));
502 } else {
503 logln(hname + ' ' + count);
504 }
505 // weiv 11/27/2002: why uprv_free? This should be a delete
506 delete ids;
507 //delete [] ids;
508 //uprv_free(ids);
509 /*} catch (Exception e) {
510 errln(hname + ' ' + "Fail: " + e);
511 }*/
512 }
513 logln("Maximum zones per offset = %d", max);
514 }
515
516 /**
517 * @bug 4151429
518 */
519 void TimeZoneRegressionTest:: Test4151429() {
520 // {sfb} silly test in C++, since we are using an enum and not an int
521 //try {
522 /*TimeZone *tz = TimeZone::createTimeZone("GMT");
523 UnicodeString name;
524 tz->getDisplayName(TRUE, TimeZone::LONG,
525 Locale.getDefault(), name);
526 errln("IllegalArgumentException not thrown by TimeZone::getDisplayName()");*/
527 //} catch(IllegalArgumentException e) {}
528 }
529
530 /**
531 * @bug 4154537
532 * SimpleTimeZone::hasSameRules() doesn't work for zones with no DST
533 * and different DST parameters.
534 */
535 void TimeZoneRegressionTest:: Test4154537() {
536 UErrorCode status = U_ZERO_ERROR;
537 // tz1 and tz2 have no DST and different rule parameters
538 SimpleTimeZone *tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0, status);
539 SimpleTimeZone *tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0, status);
540 // tza and tzA have the same rule params
541 SimpleTimeZone *tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0, status);
542 SimpleTimeZone *tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0, status);
543 // tzb differs from tza
544 SimpleTimeZone *tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0, status);
545
546 if(U_FAILURE(status))
547 errln("Couldn't create TimeZones");
548
549 if (tz1->useDaylightTime() || tz2->useDaylightTime() ||
550 !tza->useDaylightTime() || !tzA->useDaylightTime() ||
551 !tzb->useDaylightTime()) {
552 errln("Test is broken -- rewrite it");
553 }
554 if (!tza->hasSameRules(*tzA) || tza->hasSameRules(*tzb)) {
555 errln("Fail: hasSameRules() broken for zones with rules");
556 }
557 if (!tz1->hasSameRules(*tz2)) {
558 errln("Fail: hasSameRules() returns false for zones without rules");
559 //errln("zone 1 = " + tz1);
560 //errln("zone 2 = " + tz2);
561 }
562
563 delete tz1;
564 delete tz2;
565 delete tza;
566 delete tzA;
567 delete tzb;
568 }
569
570 /**
571 * @bug 4154542
572 * SimpleTimeZOne constructors, setStartRule(), and setEndRule() don't
573 * check for out-of-range arguments.
574 */
575 void TimeZoneRegressionTest:: Test4154542()
576 {
577 const int32_t GOOD = 1;
578 const int32_t BAD = 0;
579
580 const int32_t GOOD_MONTH = UCAL_JANUARY;
581 const int32_t GOOD_DAY = 1;
582 const int32_t GOOD_DAY_OF_WEEK = UCAL_SUNDAY;
583 const int32_t GOOD_TIME = 0;
584
585 int32_t DATA [] = {
586 GOOD, INT32_MIN, 0, INT32_MAX, INT32_MIN,
587 GOOD, UCAL_JANUARY, -5, UCAL_SUNDAY, 0,
588 GOOD, UCAL_DECEMBER, 5, UCAL_SATURDAY, 24*60*60*1000,
589 BAD, UCAL_DECEMBER, 5, UCAL_SATURDAY, 24*60*60*1000+1,
590 BAD, UCAL_DECEMBER, 5, UCAL_SATURDAY, -1,
591 BAD, UCAL_JANUARY, -6, UCAL_SUNDAY, 0,
592 BAD, UCAL_DECEMBER, 6, UCAL_SATURDAY, 24*60*60*1000,
593 GOOD, UCAL_DECEMBER, 1, 0, 0,
594 GOOD, UCAL_DECEMBER, 31, 0, 0,
595 BAD, UCAL_APRIL, 31, 0, 0,
596 BAD, UCAL_DECEMBER, 32, 0, 0,
597 BAD, UCAL_JANUARY-1, 1, UCAL_SUNDAY, 0,
598 BAD, UCAL_DECEMBER+1, 1, UCAL_SUNDAY, 0,
599 GOOD, UCAL_DECEMBER, 31, -UCAL_SUNDAY, 0,
600 GOOD, UCAL_DECEMBER, 31, -UCAL_SATURDAY, 0,
601 BAD, UCAL_DECEMBER, 32, -UCAL_SATURDAY, 0,
602 BAD, UCAL_DECEMBER, -32, -UCAL_SATURDAY, 0,
603 BAD, UCAL_DECEMBER, 31, -UCAL_SATURDAY-1, 0,
604 };
605 SimpleTimeZone *zone = new SimpleTimeZone(0, "Z");
606 for (int32_t i=0; i < 18*5; i+=5) {
607 UBool shouldBeGood = (DATA[i] == GOOD);
608 int32_t month = DATA[i+1];
609 int32_t day = DATA[i+2];
610 int32_t dayOfWeek = DATA[i+3];
611 int32_t time = DATA[i+4];
612
613 UErrorCode status = U_ZERO_ERROR;
614
615 //Exception ex = null;
616 //try {
617 zone->setStartRule(month, day, dayOfWeek, time, status);
618 //} catch (IllegalArgumentException e) {
619 // ex = e;
620 //}
621 if (U_SUCCESS(status) != shouldBeGood) {
622 errln(UnicodeString("setStartRule(month=") + month + ", day=" + day +
623 ", dayOfWeek=" + dayOfWeek + ", time=" + time +
624 (shouldBeGood ? (") should work")
625 : ") should fail but doesn't"));
626 }
627
628 //ex = null;
629 //try {
630 status = U_ZERO_ERROR;
631 zone->setEndRule(month, day, dayOfWeek, time, status);
632 //} catch (IllegalArgumentException e) {
633 // ex = e;
634 //}
635 if (U_SUCCESS(status) != shouldBeGood) {
636 errln(UnicodeString("setEndRule(month=") + month + ", day=" + day +
637 ", dayOfWeek=" + dayOfWeek + ", time=" + time +
638 (shouldBeGood ? (") should work")
639 : ") should fail but doesn't"));
640 }
641
642 //ex = null;
643 //try {
644 // {sfb} need to look into ctor problems! (UErrorCode vs. dst signature confusion)
645 status = U_ZERO_ERROR;
646 SimpleTimeZone *temp = new SimpleTimeZone(0, "Z",
647 (int8_t)month, (int8_t)day, (int8_t)dayOfWeek, time,
648 (int8_t)GOOD_MONTH, (int8_t)GOOD_DAY, (int8_t)GOOD_DAY_OF_WEEK,
649 GOOD_TIME,status);
650 //} catch (IllegalArgumentException e) {
651 // ex = e;
652 //}
653 if (U_SUCCESS(status) != shouldBeGood) {
654 errln(UnicodeString("SimpleTimeZone(month=") + month + ", day=" + day +
655 ", dayOfWeek=" + dayOfWeek + ", time=" + time +
656 (shouldBeGood ? (", <end>) should work")// + ex)
657 : ", <end>) should fail but doesn't"));
658 }
659
660 delete temp;
661 //ex = null;
662 //try {
663 status = U_ZERO_ERROR;
664 temp = new SimpleTimeZone(0, "Z",
665 (int8_t)GOOD_MONTH, (int8_t)GOOD_DAY, (int8_t)GOOD_DAY_OF_WEEK,
666 GOOD_TIME,
667 (int8_t)month, (int8_t)day, (int8_t)dayOfWeek, time,status);
668 //} catch (IllegalArgumentException e) {
669 // ex = e;
670 //}
671 if (U_SUCCESS(status) != shouldBeGood) {
672 errln(UnicodeString("SimpleTimeZone(<start>, month=") + month + ", day=" + day +
673 ", dayOfWeek=" + dayOfWeek + ", time=" + time +
674 (shouldBeGood ? (") should work")// + ex)
675 : ") should fail but doesn't"));
676 }
677 delete temp;
678 }
679 delete zone;
680 }
681
682
683 /**
684 * @bug 4154525
685 * SimpleTimeZone accepts illegal DST savings values. These values
686 * must be non-zero. There is no upper limit at this time.
687 */
688 void
689 TimeZoneRegressionTest::Test4154525()
690 {
691 const int32_t GOOD = 1, BAD = 0;
692
693 int32_t DATA [] = {
694 1, GOOD,
695 0, BAD,
696 -1, BAD,
697 60*60*1000, GOOD,
698 INT32_MIN, BAD,
699 // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time
700 };
701
702 UErrorCode status = U_ZERO_ERROR;
703 for(int32_t i = 0; i < 10; i+=2) {
704 int32_t savings = DATA[i];
705 UBool valid = DATA[i+1] == GOOD;
706 UnicodeString method;
707 for(int32_t j=0; j < 2; ++j) {
708 SimpleTimeZone *z=NULL;
709 switch (j) {
710 case 0:
711 method = "constructor";
712 z = new SimpleTimeZone(0, "id",
713 UCAL_JANUARY, 1, 0, 0,
714 UCAL_MARCH, 1, 0, 0,
715 savings, status); // <- what we're interested in
716 break;
717 case 1:
718 method = "setDSTSavings()";
719 z = new SimpleTimeZone(0, "GMT");
720 z->setDSTSavings(savings, status);
721 break;
722 }
723
724 if(U_FAILURE(status)) {
725 if(valid) {
726 errln(UnicodeString("Fail: DST savings of ") + savings + " to " + method + " gave " + u_errorName(status));
727 }
728 else {
729 logln(UnicodeString("Pass: DST savings of ") + savings + " to " + method + " gave " + u_errorName(status));
730 }
731 }
732 else {
733 if(valid) {
734 logln(UnicodeString("Pass: DST savings of ") + savings + " accepted by " + method);
735 }
736 else {
737 errln(UnicodeString("Fail: DST savings of ") + savings + " accepted by " + method);
738 }
739 }
740 status = U_ZERO_ERROR;
741 delete z;
742 }
743 }
744 }
745
746 /**
747 * @bug 4154650
748 * SimpleTimeZone.getOffset accepts illegal arguments.
749 */
750 void
751 TimeZoneRegressionTest::Test4154650()
752 {
753 const int32_t GOOD = 1, BAD = 0;
754 const int32_t GOOD_ERA = GregorianCalendar::AD, GOOD_YEAR = 1998, GOOD_MONTH = UCAL_AUGUST;
755 const int32_t GOOD_DAY = 2, GOOD_DOW = UCAL_SUNDAY, GOOD_TIME = 16*3600000;
756
757 int32_t DATA []= {
758 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
759
760 GOOD, GregorianCalendar::BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
761 GOOD, GregorianCalendar::AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
762 BAD, GregorianCalendar::BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
763 BAD, GregorianCalendar::AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
764
765 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME,
766 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME,
767 BAD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
768 BAD, GOOD_ERA, GOOD_YEAR, UCAL_DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
769
770 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 1, GOOD_DOW, GOOD_TIME,
771 GOOD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 31, GOOD_DOW, GOOD_TIME,
772 BAD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 0, GOOD_DOW, GOOD_TIME,
773 BAD, GOOD_ERA, GOOD_YEAR, UCAL_JANUARY, 32, GOOD_DOW, GOOD_TIME,
774
775 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SUNDAY, GOOD_TIME,
776 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SATURDAY, GOOD_TIME,
777 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SUNDAY-1, GOOD_TIME,
778 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, UCAL_SATURDAY+1, GOOD_TIME,
779
780 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0,
781 GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1,
782 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1,
783 BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000,
784 };
785
786 int32_t dataLen = (int32_t)(sizeof(DATA) / sizeof(DATA[0]));
787
788 UErrorCode status = U_ZERO_ERROR;
789 TimeZone *tz = TimeZone::createDefault();
790 for(int32_t i = 0; i < dataLen; i += 7) {
791 UBool good = DATA[i] == GOOD;
792 //IllegalArgumentException e = null;
793 //try {
794 /*int32_t offset = */
795 tz->getOffset((uint8_t)DATA[i+1], DATA[i+2], DATA[i+3],
796 DATA[i+4], (uint8_t)DATA[i+5], DATA[i+6], status);
797 //} catch (IllegalArgumentException ex) {
798 // e = ex;
799 //}
800 if(good != U_SUCCESS(status)) {
801 UnicodeString errMsg;
802 if (good) {
803 errMsg = (UnicodeString(") threw ") + u_errorName(status));
804 }
805 else {
806 errMsg = UnicodeString(") accepts invalid args", "");
807 }
808 errln(UnicodeString("Fail: getOffset(") +
809 DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " +
810 DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] +
811 errMsg);
812 }
813 status = U_ZERO_ERROR; // reset
814 }
815 delete tz;
816 }
817
818 /**
819 * @bug 4162593
820 * TimeZone broken at midnight. The TimeZone code fails to handle
821 * transitions at midnight correctly.
822 */
823 void
824 TimeZoneRegressionTest::Test4162593()
825 {
826 UErrorCode status = U_ZERO_ERROR;
827 SimpleDateFormat *fmt = new SimpleDateFormat("z", Locale::getUS(), status);
828 if(U_FAILURE(status)) {
829 errln("Error creating calendar %s", u_errorName(status));
830 delete fmt;
831 return;
832 }
833 const int32_t ONE_HOUR = 60*60*1000;
834
835 SimpleTimeZone *asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/,
836 UCAL_OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR,
837 UCAL_MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR, status);
838
839 /* Zone
840 * Starting time
841 * Transition expected between start+1H and start+2H
842 */
843 TimeZone *DATA_TZ [] = {
844 0, 0, 0 };
845
846 int32_t DATA_INT [] [5] = {
847 // These years must be AFTER the Gregorian cutover
848 {1998, UCAL_SEPTEMBER, 30, 22, 0},
849 {2000, UCAL_FEBRUARY, 28, 22, 0},
850 {2000, UCAL_FEBRUARY, 29, 22, 0},
851 };
852
853 UBool DATA_BOOL [] = {
854 TRUE,
855 FALSE,
856 TRUE,
857 };
858
859 UnicodeString zone [4];// = new String[4];
860 DATA_TZ[0] =
861 new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/,
862 UCAL_APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR,
863 UCAL_OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR, status);
864 DATA_TZ[1] = asuncion; DATA_TZ[2] = asuncion;
865
866 for(int32_t j = 0; j < 3; j++) {
867 TimeZone *tz = (TimeZone*)DATA_TZ[j];
868 TimeZone::setDefault(*tz);
869 fmt->setTimeZone(*tz);
870
871 // Must construct the Date object AFTER setting the default zone
872 int32_t *p = (int32_t*)DATA_INT[j];
873 UDate d = CalendarRegressionTest::makeDate(p[0], p[1], p[2], p[3], p[4]);
874 UBool transitionExpected = DATA_BOOL[j];
875
876 UnicodeString temp;
877 logln(tz->getID(temp) + ":");
878 for (int32_t i = 0; i < 4; ++i) {
879 FieldPosition pos(0);
880 zone[i].remove();
881 zone[i] = fmt->format(d, zone[i], pos);
882 logln(UnicodeString("") + i + ": " + d + " / " + zone[i]);
883 d += (double) ONE_HOUR;
884 }
885 if(zone[0] == zone[1] &&
886 (zone[1] == zone[2]) != transitionExpected &&
887 zone[2] == zone[3]) {
888 logln(UnicodeString("Ok: transition ") + transitionExpected);
889 }
890 else {
891 errln("Fail: boundary transition incorrect");
892 }
893 }
894 delete fmt;
895 delete asuncion;
896 delete DATA_TZ[0];
897 }
898
899 /**
900 * Make sure setStartRule and setEndRule set the DST savings to nonzero
901 * if it was zero.
902 */
903 void TimeZoneRegressionTest::TestJ186() {
904 UErrorCode status = U_ZERO_ERROR;
905 // NOTE: Setting the DST savings to zero is illegal, so we
906 // are limited in the testing we can do here. This is why
907 // lines marked //~ are commented out.
908 SimpleTimeZone z(0, "ID");
909 //~z.setDSTSavings(0, status); // Must do this!
910 z.setStartRule(UCAL_FEBRUARY, 1, UCAL_SUNDAY, 0, status);
911 failure(status, "setStartRule()");
912 if (z.useDaylightTime()) {
913 errln("Fail: useDaylightTime true with start rule only");
914 }
915 //~if (z.getDSTSavings() != 0) {
916 //~ errln("Fail: dst savings != 0 with start rule only");
917 //~}
918 z.setEndRule(UCAL_MARCH, -1, UCAL_SUNDAY, 0, status);
919 failure(status, "setStartRule()");
920 if (!z.useDaylightTime()) {
921 errln("Fail: useDaylightTime false with rules set");
922 }
923 if (z.getDSTSavings() == 0) {
924 errln("Fail: dst savings == 0 with rules set");
925 }
926 }
927
928 /**
929 * Test to see if DateFormat understands zone equivalency groups. It
930 * might seem that this should be a DateFormat test, but it's really a
931 * TimeZone test -- the changes to DateFormat are minor.
932 *
933 * We use two known, stable zones that shouldn't change much over time
934 * -- America/Vancouver and America/Los_Angeles. However, they MAY
935 * change at some point -- if that happens, replace them with any two
936 * zones in an equivalency group where one zone has localized name
937 * data, and the other doesn't, in some locale.
938 */
939 void TimeZoneRegressionTest::TestJ449() {
940 UErrorCode status = U_ZERO_ERROR;
941 UnicodeString str;
942
943 // Modify the following three as necessary. The two IDs must
944 // specify two zones in the same equivalency group. One must have
945 // locale data in 'loc'; the other must not.
946 const char* idWithLocaleData = "America/Los_Angeles";
947 const char* idWithoutLocaleData = "US/Pacific";
948 const Locale loc("en", "", "");
949
950 TimeZone *zoneWith = TimeZone::createTimeZone(idWithLocaleData);
951 TimeZone *zoneWithout = TimeZone::createTimeZone(idWithoutLocaleData);
952 // Make sure we got valid zones
953 if (zoneWith->getID(str) != UnicodeString(idWithLocaleData) ||
954 zoneWithout->getID(str) != UnicodeString(idWithoutLocaleData)) {
955 errln(UnicodeString("Fail: Unable to create zones - wanted ") + idWithLocaleData + ", got " + zoneWith->getID(str) + ", and wanted " + idWithoutLocaleData + " but got " + zoneWithout->getID(str));
956 } else {
957 GregorianCalendar calWith(*zoneWith, status);
958 GregorianCalendar calWithout(*zoneWithout, status);
959 SimpleDateFormat fmt("MMM d yyyy hh:mm a zzz", loc, status);
960 if (U_FAILURE(status)) {
961 errln("Fail: Unable to create GregorianCalendar/SimpleDateFormat");
962 } else {
963 UDate date = 0;
964 UnicodeString strWith, strWithout;
965 fmt.setCalendar(calWith);
966 fmt.format(date, strWith);
967 fmt.setCalendar(calWithout);
968 fmt.format(date, strWithout);
969 if (strWith == strWithout) {
970 logln((UnicodeString)"Ok: " + idWithLocaleData + " -> " +
971 strWith + "; " + idWithoutLocaleData + " -> " +
972 strWithout);
973 } else {
974 errln((UnicodeString)"FAIL: " + idWithLocaleData + " -> " +
975 strWith + "; " + idWithoutLocaleData + " -> " +
976 strWithout);
977 }
978 }
979 }
980
981 delete zoneWith;
982 delete zoneWithout;
983 }
984
985 // test new API for JDK 1.2 8/31 putback
986 void
987 TimeZoneRegressionTest::TestJDK12API()
988 {
989 // TimeZone *pst = TimeZone::createTimeZone("PST");
990 // TimeZone *cst1 = TimeZone::createTimeZone("CST");
991 UErrorCode ec = U_ZERO_ERROR;
992 //d,-28800,3,1,-1,120,w,9,-1,1,120,w,60
993 TimeZone *pst = new SimpleTimeZone(-28800*U_MILLIS_PER_SECOND,
994 "PST",
995 3,1,-1,120*U_MILLIS_PER_MINUTE,
996 SimpleTimeZone::WALL_TIME,
997 9,-1,1,120*U_MILLIS_PER_MINUTE,
998 SimpleTimeZone::WALL_TIME,
999 60*U_MILLIS_PER_MINUTE,ec);
1000 //d,-21600,3,1,-1,120,w,9,-1,1,120,w,60
1001 TimeZone *cst1 = new SimpleTimeZone(-21600*U_MILLIS_PER_SECOND,
1002 "CST",
1003 3,1,-1,120*U_MILLIS_PER_MINUTE,
1004 SimpleTimeZone::WALL_TIME,
1005 9,-1,1,120*U_MILLIS_PER_MINUTE,
1006 SimpleTimeZone::WALL_TIME,
1007 60*U_MILLIS_PER_MINUTE,ec);
1008 if (U_FAILURE(ec)) {
1009 errln("FAIL: SimpleTimeZone constructor");
1010 return;
1011 }
1012
1013 SimpleTimeZone *cst = 0;
1014
1015 if(cst1->getDynamicClassID() == SimpleTimeZone::getStaticClassID())
1016 cst = (SimpleTimeZone*) cst1;
1017
1018 if(pst->hasSameRules(*cst)) {
1019 errln("FAILURE: PST and CST have same rules");
1020 }
1021
1022 UErrorCode status = U_ZERO_ERROR;
1023 int32_t offset1 = pst->getOffset(1,
1024 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000), status);
1025 failure(status, "getOffset() failed");
1026
1027
1028 int32_t offset2 = cst->getOffset(1,
1029 1997, UCAL_OCTOBER, 26, UCAL_SUNDAY, (2*60*60*1000), 31, status);
1030 failure(status, "getOffset() failed");
1031
1032 if(offset1 == offset2)
1033 errln("FAILURE: Sunday Oct. 26 1997 2:00 has same offset for PST and CST");
1034
1035 // verify error checking
1036 pst->getOffset(1,
1037 1997, (UCalendarDateFields)-1, 26, UCAL_SUNDAY, (2*60*60*1000), status);
1038 if(U_SUCCESS(status))
1039 errln("FAILURE: getOffset() succeeded with -1 for month");
1040
1041 status = U_ZERO_ERROR;
1042 cst->setDSTSavings(60*60*1000, status);
1043 failure(status, "setDSTSavings() failed");
1044
1045 int32_t savings = cst->getDSTSavings();
1046 if(savings != 60*60*1000) {
1047 errln("setDSTSavings() failed");
1048 }
1049
1050 delete pst;
1051 delete cst;
1052 }
1053
1054 #endif /* #if !UCONFIG_NO_FORMATTING */