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