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