1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation
6 * and others. All Rights Reserved.
7 ********************************************************************/
8
9 #include "unicode/utypes.h"
10
11 #if !UCONFIG_NO_FORMATTING
12
13 #include "calregts.h"
14
15 #include "unicode/calendar.h"
16 #include "unicode/gregocal.h"
17 #include "unicode/simpletz.h"
18 #include "unicode/smpdtfmt.h"
19 #include "unicode/strenum.h"
20 #include "unicode/localpointer.h"
21 #include "cmemory.h"
22 #include "caltest.h"
23 #include "unicode/localpointer.h"
24
25 #include <float.h>
26
27 // *****************************************************************************
28 // class CalendarRegressionTest
29 // *****************************************************************************
30
31 // these numbers correspond to using LONG_MIN and LONG_MAX in Java
32 // this is 2^52 - 1, the largest allowable mantissa with a 0 exponent in a 64-bit double
33 const UDate CalendarRegressionTest::EARLIEST_SUPPORTED_MILLIS = - 4503599627370495.0;
34 const UDate CalendarRegressionTest::LATEST_SUPPORTED_MILLIS = 4503599627370495.0;
35
36 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
37
38 void
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)39 CalendarRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
40 {
41 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
42 switch (index) {
43 CASE(0,test4100311);
44 CASE(1,test4074758);
45 CASE(2,test4028518);
46 CASE(3,test4031502);
47 CASE(4,test4035301);
48 CASE(5,test4040996);
49 CASE(6,test4051765);
50 CASE(7,test4061476);
51 CASE(8,test4070502);
52 CASE(9,test4071197);
53 CASE(10,test4071385);
54 CASE(11,test4073929);
55 CASE(12,test4083167);
56 CASE(13,test4086724);
57 CASE(14,test4095407);
58 CASE(15,test4096231);
59 CASE(16,test4096539);
60 CASE(17,test41003112);
61 CASE(18,test4103271);
62 CASE(19,test4106136);
63 CASE(20,test4108764);
64 CASE(21,test4114578);
65 CASE(22,test4118384);
66 CASE(23,test4125881);
67 CASE(24,test4125892);
68 CASE(25,test4141665);
69 CASE(26,test4142933);
70 CASE(27,test4145158);
71 CASE(28,test4145983);
72 CASE(29,test4147269);
73
74 CASE(30,Test4149677);
75 CASE(31,Test4162587);
76 CASE(32,Test4165343);
77 CASE(33,Test4166109);
78 CASE(34,Test4167060);
79 CASE(35,Test4197699);
80 CASE(36,TestJ81);
81 CASE(37,TestJ438);
82 CASE(38,TestLeapFieldDifference);
83 CASE(39,TestMalaysianInstance);
84 CASE(40,test4059654);
85 CASE(41,test4092362);
86 CASE(42,TestWeekShift);
87 CASE(43,TestTimeZoneTransitionAdd);
88 CASE(44,TestDeprecates);
89 CASE(45,TestT5555);
90 CASE(46,TestT6745);
91 CASE(47,TestT8057);
92 CASE(48,TestT8596);
93 CASE(49,Test9019);
94 CASE(50,TestT9452);
95 CASE(51,TestT11632);
96 CASE(52,TestPersianCalOverflow);
97 CASE(53,TestIslamicCalOverflow);
98 CASE(54,TestWeekOfYear13548);
99 CASE(55,Test13745);
100 CASE(56,TestUTCWrongAMPM22023);
101 CASE(57,TestAsiaManilaAfterSetGregorianChange22043);
102 default: name = ""; break;
103 }
104 }
105
106 const char* CalendarRegressionTest::FIELD_NAME [] = {
107 "ERA",
108 "YEAR",
109 "MONTH",
110 "WEEK_OF_YEAR",
111 "WEEK_OF_MONTH",
112 "DAY_OF_MONTH",
113 "DAY_OF_YEAR",
114 "DAY_OF_WEEK",
115 "DAY_OF_WEEK_IN_MONTH",
116 "AM_PM",
117 "HOUR",
118 "HOUR_OF_DAY",
119 "MINUTE",
120 "SECOND",
121 "MILLISECOND",
122 "ZONE_OFFSET",
123 "DST_OFFSET",
124 "YEAR_WOY",
125 "DOW_LOCAL"
126 };
127
128 UBool
failure(UErrorCode status,const char * msg)129 CalendarRegressionTest::failure(UErrorCode status, const char* msg)
130 {
131 if(U_FAILURE(status)) {
132 errcheckln(status, UnicodeString("FAIL: ") + msg + " failed, error " + u_errorName(status));
133 return true;
134 }
135
136 return false;
137 }
138
139 /*
140 * bug 4100311
141 */
142 void
test4100311()143 CalendarRegressionTest::test4100311()
144 {
145 UErrorCode status = U_ZERO_ERROR;
146 GregorianCalendar *cal = (GregorianCalendar*)Calendar::createInstance(status);
147 if(U_FAILURE(status)) {
148 dataerrln("Error creating Calendar: %s", u_errorName(status));
149 delete cal;
150 return;
151 }
152 failure(status, "Calendar::createInstance(status)");
153 cal->set(UCAL_YEAR, 1997);
154 cal->set(UCAL_DAY_OF_YEAR, 1);
155 UDate d = cal->getTime(status); // Should be Jan 1
156 failure(status, "cal->getTime");
157 logln(UnicodeString("") + d);
158 delete cal;
159 }
160
161
162 /**
163 * @bug 4074758
164 */
165 void
test4074758()166 CalendarRegressionTest::test4074758()
167 { //Set system time to between 12-1 (am or pm) and then run
168 UErrorCode status = U_ZERO_ERROR;
169 GregorianCalendar *cal = new GregorianCalendar(status);
170 if(U_FAILURE(status)) {
171 dataerrln("Error creating Calendar: %s", u_errorName(status));
172 delete cal;
173 return;
174 }
175 failure(status, "new GregorianCalendar");
176 for (int32_t h=0; h<25; ++h) {
177 cal->set(97, UCAL_JANUARY, 1, h, 34);
178 //System.out.print(d);
179 logln(UnicodeString("HOUR=") + cal->get(UCAL_HOUR, status)); //prints 0
180 failure(status, "cal->get");
181 logln(UnicodeString("HOUR_OF_DAY=") + cal->get(UCAL_HOUR_OF_DAY, status));
182 failure(status, "cal->get");
183 }
184
185 delete cal;
186 }
187
188 void
test4028518()189 CalendarRegressionTest::test4028518()
190 {
191 UErrorCode status = U_ZERO_ERROR;
192 GregorianCalendar *cal1 = new GregorianCalendar(status) ;
193 if(U_FAILURE(status)) {
194 dataerrln("Error creating Calendar: %s", u_errorName(status));
195 delete cal1;
196 return;
197 }
198 failure(status, "new GregorianCalendar");
199 GregorianCalendar *cal2 = cal1->clone() ;
200
201 printdate(cal1, "cal1: ") ;
202 printdate(cal2, "cal2 - cloned(): ") ;
203 cal1->add(UCAL_DATE, 1, status) ;
204 failure(status, "cal1->add");
205 printdate(cal1, "cal1 after adding 1 day:") ;
206 printdate(cal2, "cal2 should be unmodified:") ;
207 delete cal1;
208 delete cal2;
209 }
210
211
212 void
Test9019()213 CalendarRegressionTest::Test9019()
214 {
215 UErrorCode status = U_ZERO_ERROR;
216 LocalPointer<GregorianCalendar> cal1(new GregorianCalendar(status), status);
217 LocalPointer<GregorianCalendar> cal2(new GregorianCalendar(status), status);
218 if(U_FAILURE(status)) {
219 dataerrln("Error creating Calendar: %s", u_errorName(status));
220 return;
221 }
222 cal1->set(UCAL_HOUR, 1);
223 cal2->set(UCAL_HOUR,2);
224 cal1->clear();
225 cal2->clear();
226 failure(status, "new GregorianCalendar");
227 cal1->set(2011,UCAL_MAY,06);
228 cal2->set(2012,UCAL_JANUARY,06);
229 printdate(cal1.getAlias(), "cal1: ") ;
230 cal1->setLenient(false);
231 cal1->add(UCAL_MONTH,8,status);
232 failure(status, "->add(UCAL_MONTH,8)");
233 printdate(cal1.getAlias(), "cal1 (lenient) after adding 8 months:") ;
234 printdate(cal2.getAlias(), "cal2 (expected date):") ;
235
236 if(!cal1->equals(*cal2,status)) {
237 errln("Error: cal1 != cal2.\n");
238 }
239 failure(status, "equals");
240 }
241
242 void
printdate(GregorianCalendar * cal,const char * string)243 CalendarRegressionTest::printdate(GregorianCalendar *cal, const char *string)
244 {
245 UErrorCode status = U_ZERO_ERROR;
246 logln(UnicodeString(string, ""));
247 log(UnicodeString("") + cal->get(UCAL_MONTH, status)) ;
248 failure(status, "cal->get");
249 int32_t date = cal->get(UCAL_DATE, status) + 1 ;
250 failure(status, "cal->get");
251 log(UnicodeString("/") + date) ;
252 logln(UnicodeString("/") + cal->get(UCAL_YEAR, status)) ;
253 failure(status, "cal->get");
254 }
255
256 /**
257 * @bug 4031502
258 */
259 void
test4031502()260 CalendarRegressionTest::test4031502()
261 {
262 // This bug actually occurs on Windows NT as well, and doesn't
263 // require the host zone to be set; it can be set in Java.
264 UErrorCode status = U_ZERO_ERROR;
265 StringEnumeration* ids = TimeZone::createEnumeration(status);
266 if (U_FAILURE(status)) {
267 dataerrln("Unable to create TimeZone Enumeration.");
268 return;
269 }
270 UBool bad = false;
271 TimeZone* tz =TimeZone::createTimeZone("Asia/Riyadh87");
272 failure(status, "new TimeZone");
273 GregorianCalendar *cl = new GregorianCalendar(tz, status);
274 if (U_FAILURE(status)) {
275 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
276 delete tz;
277 return;
278 }
279 cl->clear();
280 cl->set(1900, 15, 5, 5, 8, 13);
281 cl->get(UCAL_HOUR, status);
282 failure(status, "cl->get(UCAL_HOUR, status)");
283 status = U_ZERO_ERROR;
284 delete cl;
285 for (int32_t i=0; i<ids->count(status); ++i) {
286 TimeZone *zone = TimeZone::createTimeZone(*ids->snext(status));
287 GregorianCalendar *cal = new GregorianCalendar(zone, status);
288 failure(status, "new GregorianCalendar");
289 cal->clear();
290 cal->set(1900, 15, 5, 5, 8, 13);
291 if (cal->get(UCAL_HOUR, status) != 5 || U_FAILURE(status)) {
292 UnicodeString temp;
293 logln(zone->getID(temp) + " " +
294 //zone.useDaylightTime() + " " +
295 cal->get(UCAL_DST_OFFSET,status) / (60*60*1000) + " " +
296 zone->getRawOffset() / (60*60*1000) +
297 ": HOUR = " + cal->get(UCAL_HOUR,status));
298 bad = true;
299 }
300 delete cal;
301 }
302 if (bad)
303 errln("TimeZone problems with GC");
304 // delete [] ids; // TODO: bad APIs
305 delete ids;
306 }
307
308 /**
309 * @bug 4035301
310 */
test4035301()311 void CalendarRegressionTest::test4035301()
312 {
313 UErrorCode status = U_ZERO_ERROR;
314 GregorianCalendar *c = new GregorianCalendar(98, 8, 7,status);
315 GregorianCalendar *d = new GregorianCalendar(98, 8, 7,status);
316 if (c->after(*d,status) ||
317 c->after(*c,status) ||
318 c->before(*d,status) ||
319 c->before(*c,status) ||
320 *c != *c ||
321 *c != *d)
322 dataerrln("Fail");
323 delete c;
324 delete d;
325 }
326
327 /**
328 * @bug 4040996
329 */
test4040996()330 void CalendarRegressionTest::test4040996()
331 {
332 int32_t count = 0;
333 UErrorCode status = U_ZERO_ERROR;
334 StringEnumeration* ids = TimeZone::createEnumerationForRawOffset(-8 * 60 * 60 * 1000, status);
335 if (U_FAILURE(status)) {
336 dataerrln("Unable to create TimeZone enumeration.");
337 return;
338 }
339 count = ids->count(status);
340 (void)count; // Suppress set but not used warning.
341 SimpleTimeZone *pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, *ids->snext(status));
342 pdt->setStartRule(UCAL_APRIL, 1, UCAL_SUNDAY, 2 * 60 * 60 * 1000, status);
343 pdt->setEndRule(UCAL_OCTOBER, -1, UCAL_SUNDAY, 2 * 60 * 60 * 1000, status);
344 Calendar *calendar = new GregorianCalendar(pdt, status);
345 if (U_FAILURE(status)) {
346 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
347 return;
348 }
349 calendar->set(UCAL_MONTH,3);
350 calendar->set(UCAL_DATE,18);
351 calendar->set(UCAL_SECOND, 30);
352
353 logln(UnicodeString("MONTH: ") + calendar->get(UCAL_MONTH, status));
354 logln(UnicodeString("DAY_OF_MONTH: ") +
355 calendar->get(UCAL_DATE, status));
356 logln(UnicodeString("MINUTE: ") + calendar->get(UCAL_MINUTE, status));
357 logln(UnicodeString("SECOND: ") + calendar->get(UCAL_SECOND, status));
358
359 calendar->add(UCAL_SECOND,6, status);
360 //This will print out todays date for MONTH and DAY_OF_MONTH
361 //instead of the date it was set to.
362 //This happens when adding MILLISECOND or MINUTE also
363 logln(UnicodeString("MONTH: ") + calendar->get(UCAL_MONTH, status));
364 logln(UnicodeString("DAY_OF_MONTH: ") +
365 calendar->get(UCAL_DATE, status));
366 logln(UnicodeString("MINUTE: ") + calendar->get(UCAL_MINUTE, status));
367 logln(UnicodeString("SECOND: ") + calendar->get(UCAL_SECOND, status));
368 if (calendar->get(UCAL_MONTH, status) != 3 ||
369 calendar->get(UCAL_DATE, status) != 18 ||
370 calendar->get(UCAL_SECOND, status) != 36)
371 errln(UnicodeString("Fail: Calendar::add misbehaves"));
372
373 delete calendar;
374 delete ids;
375 // delete ids; // TODO: BAD API
376 }
377
378 /**
379 * @bug 4051765
380 */
test4051765()381 void CalendarRegressionTest::test4051765()
382 {
383 UErrorCode status = U_ZERO_ERROR;
384 Calendar *cal = Calendar::createInstance(status);
385 if(U_FAILURE(status)) {
386 dataerrln("Error creating Calendar: %s", u_errorName(status));
387 delete cal;
388 return;
389 }
390 cal->setLenient(false);
391 cal->set(UCAL_DAY_OF_WEEK, 0);
392 //try {
393 cal->getTime(status);
394 if( ! U_FAILURE(status))
395 errln("Fail: DAY_OF_WEEK 0 should be disallowed");
396 /*}
397 catch (IllegalArgumentException e) {
398 return;
399 }*/
400
401 delete cal;
402 }
403
404 /* User error - no bug here
405 void CalendarRegressionTest::test4059524() {
406 // Create calendar for April 10, 1997
407 GregorianCalendar calendar = new GregorianCalendar(status);
408 // print out a bunch of interesting things
409 logln("ERA: " + Calendar::get(Calendar::ERA));
410 logln("YEAR: " + Calendar::get(Calendar::YEAR));
411 logln("MONTH: " + Calendar::get(Calendar::MONTH));
412 logln("WEEK_OF_YEAR: " +
413 Calendar::get(Calendar::WEEK_OF_YEAR));
414 logln("WEEK_OF_MONTH: " +
415 Calendar::get(Calendar::WEEK_OF_MONTH));
416 logln("DATE: " + Calendar::get(Calendar::DATE));
417 logln("DAY_OF_MONTH: " +
418 Calendar::get(Calendar::DAY_OF_MONTH));
419 logln("DAY_OF_YEAR: " + Calendar::get(Calendar::DAY_OF_YEAR));
420 logln("DAY_OF_WEEK: " + Calendar::get(Calendar::DAY_OF_WEEK));
421 logln("DAY_OF_WEEK_IN_MONTH: " +
422 Calendar::get(Calendar::DAY_OF_WEEK_IN_MONTH));
423 logln("AM_PM: " + Calendar::get(Calendar::AM_PM));
424 logln("HOUR: " + Calendar::get(Calendar::HOUR));
425 logln("HOUR_OF_DAY: " + Calendar::get(Calendar::HOUR_OF_DAY));
426 logln("MINUTE: " + Calendar::get(Calendar::MINUTE));
427 logln("SECOND: " + Calendar::get(Calendar::SECOND));
428 logln("MILLISECOND: " + Calendar::get(Calendar::MILLISECOND));
429 logln("ZONE_OFFSET: "
430 + (Calendar::get(Calendar::ZONE_OFFSET)/(60*60*1000)));
431 logln("DST_OFFSET: "
432 + (Calendar::get(Calendar::DST_OFFSET)/(60*60*1000)));
433 calendar = new GregorianCalendar(1997,3,10);
434 Calendar::getTime();
435 logln("April 10, 1997");
436 logln("ERA: " + Calendar::get(Calendar::ERA));
437 logln("YEAR: " + Calendar::get(Calendar::YEAR));
438 logln("MONTH: " + Calendar::get(Calendar::MONTH));
439 logln("WEEK_OF_YEAR: " +
440 Calendar::get(Calendar::WEEK_OF_YEAR));
441 logln("WEEK_OF_MONTH: " +
442 Calendar::get(Calendar::WEEK_OF_MONTH));
443 logln("DATE: " + Calendar::get(Calendar::DATE));
444 logln("DAY_OF_MONTH: " +
445 Calendar::get(Calendar::DAY_OF_MONTH));
446 logln("DAY_OF_YEAR: " + Calendar::get(Calendar::DAY_OF_YEAR));
447 logln("DAY_OF_WEEK: " + Calendar::get(Calendar::DAY_OF_WEEK));
448 logln("DAY_OF_WEEK_IN_MONTH: " + Calendar::get(Calendar::DAY_OF_WEEK_IN_MONTH));
449 logln("AM_PM: " + Calendar::get(Calendar::AM_PM));
450 logln("HOUR: " + Calendar::get(Calendar::HOUR));
451 logln("HOUR_OF_DAY: " + Calendar::get(Calendar::HOUR_OF_DAY));
452 logln("MINUTE: " + Calendar::get(Calendar::MINUTE));
453 logln("SECOND: " + Calendar::get(Calendar::SECOND));
454 logln("MILLISECOND: " + Calendar::get(Calendar::MILLISECOND));
455 logln("ZONE_OFFSET: "
456 + (Calendar::get(Calendar::ZONE_OFFSET)/(60*60*1000))); // in hours
457 logln("DST_OFFSET: "
458 + (Calendar::get(Calendar::DST_OFFSET)/(60*60*1000))); // in hours
459 }
460 */
461
462 /**
463 * @bug 4059654
464 */
test4059654()465 void CalendarRegressionTest::test4059654() {
466 UErrorCode status = U_ZERO_ERROR;
467 GregorianCalendar *gc = new GregorianCalendar(status);
468 if(U_FAILURE(status)) {
469 dataerrln("Error creating Calendar: %s", u_errorName(status));
470 delete gc;
471 return;
472 }
473
474 gc->set(1997, 3, 1, 15, 16, 17); // April 1, 1997
475
476 gc->set(UCAL_HOUR, 0);
477 gc->set(UCAL_AM_PM, UCAL_AM);
478 gc->set(UCAL_MINUTE, 0);
479 gc->set(UCAL_SECOND, 0);
480 gc->set(UCAL_MILLISECOND, 0);
481
482 UDate cd = gc->getTime(status);
483 GregorianCalendar *exp = new GregorianCalendar(1997, 3, 1, 0, 0, 0, status);
484 if (cd != exp->getTime(status))
485 errln(UnicodeString("Fail: Calendar::set broken. Got ") + cd + " Want " + exp->getTime(status));
486
487 delete gc;
488 delete exp;
489 }
490
491 /**
492 * @bug 4061476
493 */
test4061476()494 void CalendarRegressionTest::test4061476()
495 {
496 UErrorCode status = U_ZERO_ERROR;
497 SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("ddMMMyy"), Locale::getUK(),status);
498 Calendar *cal = Calendar::createInstance(TimeZone::createTimeZone("GMT"),
499 Locale::getUK(),status);
500 if(U_FAILURE(status)) {
501 dataerrln("Error creating Calendar: %s", u_errorName(status));
502 delete cal;
503 delete fmt;
504 return;
505 }
506 fmt->adoptCalendar(cal);
507 // try {
508 UDate date = fmt->parse("29MAY97", status);
509 failure(status, "fmt->parse");
510 cal->setTime(date, status);
511 failure(status, "cal->setTime");
512 // }
513 //catch (Exception e) {;}
514 cal->set(UCAL_HOUR_OF_DAY, 13);
515 logln(UnicodeString("Hour: ")+cal->get(UCAL_HOUR_OF_DAY, status));
516 cal->add(UCAL_HOUR_OF_DAY, 6,status);
517 logln(UnicodeString("Hour: ")+cal->get(UCAL_HOUR_OF_DAY, status));
518 if (cal->get(UCAL_HOUR_OF_DAY, status) != 19)
519 errln(UnicodeString("Fail: Want 19 Got ") + cal->get(UCAL_HOUR_OF_DAY, status));
520
521 delete fmt;
522 }
523
524 /**
525 * @bug 4070502
526 */
test4070502()527 void CalendarRegressionTest::test4070502()
528 {
529 UErrorCode status = U_ZERO_ERROR;
530 Calendar *cal = new GregorianCalendar(status);
531 if(status == U_USING_FALLBACK_WARNING || U_FAILURE(status)) {
532 dataerrln("Error creating Calendar: %s", u_errorName(status));
533 delete cal;
534 return;
535 }
536 UDate d = getAssociatedDate(makeDate(1998,0,30), status);
537 cal->setTime(d,status);
538 if (cal->get(UCAL_DAY_OF_WEEK,status) == UCAL_SATURDAY ||
539 cal->get(UCAL_DAY_OF_WEEK,status) == UCAL_SUNDAY)
540 errln(UnicodeString("Fail: Want weekday Got ") + d);
541
542 delete cal;
543 }
544
545 /**
546 * Get the associated date starting from a specified date
547 * NOTE: the unnecessary "getTime()'s" below are a work-around for a
548 * bug in jdk 1.1.3 (and probably earlier versions also)
549 * <p>
550 * @param date The date to start from
551 */
552 UDate
getAssociatedDate(UDate d,UErrorCode & status)553 CalendarRegressionTest::getAssociatedDate(UDate d, UErrorCode& status)
554 {
555 GregorianCalendar *cal = new GregorianCalendar(status);
556 cal->setTime(d,status);
557 //cal.add(field, amount); //<-- PROBLEM SEEN WITH field = DATE,MONTH
558 // cal.getTime(); // <--- REMOVE THIS TO SEE BUG
559 for (;;) {
560 int32_t wd = cal->get(UCAL_DAY_OF_WEEK, status);
561 if (wd == UCAL_SATURDAY || wd == UCAL_SUNDAY) {
562 cal->add(UCAL_DATE, 1, status);
563 // cal.getTime();
564 }
565 else
566 break;
567 }
568
569 UDate dd = cal->getTime(status);
570 delete cal;
571 return dd;
572 }
573
574 /**
575 * @bug 4071197
576 */
test4071197()577 void CalendarRegressionTest::test4071197()
578 {
579 dowTest(false);
580 dowTest(true);
581 }
582
dowTest(UBool lenient)583 void CalendarRegressionTest::dowTest(UBool lenient)
584 {
585 UErrorCode status = U_ZERO_ERROR;
586 GregorianCalendar *cal = new GregorianCalendar(status);
587 if(U_FAILURE(status)) {
588 dataerrln("Error creating Calendar: %s", u_errorName(status));
589 delete cal;
590 return;
591 }
592 cal->set(1997, UCAL_AUGUST, 12); // Wednesday
593 // cal.getTime(); // Force update
594 cal->setLenient(lenient);
595 cal->set(1996, UCAL_DECEMBER, 1); // Set the date to be December 1, 1996
596 int32_t dow = cal->get(UCAL_DAY_OF_WEEK, status);
597 int32_t min = cal->getMinimum(UCAL_DAY_OF_WEEK);
598 int32_t max = cal->getMaximum(UCAL_DAY_OF_WEEK);
599 //logln(cal.getTime().toString());
600 if (min != UCAL_SUNDAY || max != UCAL_SATURDAY)
601 errln("FAIL: Min/max bad");
602 if (dow < min || dow > max)
603 errln("FAIL: Day of week %d out of range [%d,%d]\n", dow, min, max);
604 if (dow != UCAL_SUNDAY)
605 errln(UnicodeString("FAIL: Day of week should be SUNDAY Got ") + dow);
606
607 if(U_FAILURE(status)) {
608 errln("Error checking Calendar: %s", u_errorName(status));
609 delete cal;
610 return;
611 }
612
613 if(cal->getActualMinimum(UCAL_DAY_OF_WEEK, status) != min) {
614 errln("FAIL: actual minimum differs from minimum");
615 }
616 if(cal->getActualMinimum(Calendar::DAY_OF_WEEK, status) != min) {
617 errln("FAIL: actual minimum (Calendar::DAY_OF_WEEK, status) differs from minimum");
618 }
619 if(cal->getActualMinimum(Calendar::DAY_OF_WEEK) != min) {
620 errln("FAIL: actual minimum (Calendar::DAY_OF_WEEK) differs from minimum");
621 }
622 if(((Calendar*)cal)->getActualMinimum(UCAL_DAY_OF_WEEK, status) != min) {
623 errln("FAIL: actual minimum (UCAL_DAY_OF_WEEK, status) differs from minimum");
624 }
625 // NOTE: This function does not exist! jitterbug #3016
626 // if(((Calendar*)cal)->getActualMinimum(Calendar::DAY_OF_WEEK, status) != min) {
627 // errln("FAIL: actual minimum (Calendar::DAY_OF_WEEK, status) differs from minimum");
628 // }
629 if(U_FAILURE(status)) {
630 errln("Error getting actual minimum: %s", u_errorName(status));
631 return;
632 }
633
634 delete cal;
635 }
636
637 /**
638 * @bug 4071385
639 */
test4071385()640 void CalendarRegressionTest::test4071385()
641 {
642 UErrorCode status = U_ZERO_ERROR;
643 Calendar *cal = Calendar::createInstance(status);
644 if(U_FAILURE(status)) {
645 dataerrln("Error creating Calendar: %s", u_errorName(status));
646 delete cal;
647 return;
648 }
649 cal->setTime(makeDate(1998, UCAL_JUNE, 24),status);
650 cal->set(UCAL_MONTH, UCAL_NOVEMBER); // change a field
651 //logln(cal.getTime().toString());
652 if (cal->getTime(status) != makeDate(1998, UCAL_NOVEMBER, 24))
653 errln("Fail");
654
655 delete cal;
656 }
657
658 /**
659 * @bug 4073929
660 */
test4073929()661 void CalendarRegressionTest::test4073929()
662 {
663 UErrorCode status = U_ZERO_ERROR;
664 GregorianCalendar *foo1 = new GregorianCalendar(1997, 8, 27,status);
665 if(U_FAILURE(status)) {
666 dataerrln("Error creating Calendar: %s", u_errorName(status));
667 delete foo1;
668 return;
669 }
670 logln("foo1@%.0f - %d-%d-%d %d:%d:%d.%ds\n", foo1->getTime(status),
671 foo1->get(UCAL_YEAR, status),
672 foo1->get(UCAL_MONTH, status),
673 foo1->get(UCAL_DATE, status),
674 foo1->get(UCAL_HOUR, status),
675 foo1->get(UCAL_MINUTE, status),
676 foo1->get(UCAL_SECOND, status),
677 foo1->get(UCAL_MILLISECOND,status));
678 foo1->add(UCAL_DATE, + 1, status);
679 logln("foo1@%.0f - %d-%d-%d %d:%d:%d.%ds after +\n", foo1->getTime(status),
680 foo1->get(UCAL_YEAR, status),
681 foo1->get(UCAL_MONTH, status),
682 foo1->get(UCAL_DATE, status),
683 foo1->get(UCAL_HOUR, status),
684 foo1->get(UCAL_MINUTE, status),
685 foo1->get(UCAL_SECOND, status),
686 foo1->get(UCAL_MILLISECOND ,status));
687 foo1->add(UCAL_DATE, - 1, status);
688 logln("foo1@%.0f - %d-%d-%d %d:%d:%d.%ds after -\n", foo1->getTime(status),
689 foo1->get(UCAL_YEAR, status),
690 foo1->get(UCAL_MONTH, status),
691 foo1->get(UCAL_DATE, status),
692 foo1->get(UCAL_HOUR, status),
693 foo1->get(UCAL_MINUTE, status),
694 foo1->get(UCAL_SECOND, status),
695 foo1->get(UCAL_MILLISECOND, status));
696
697 foo1->add(UCAL_DATE, + 1, status);
698 int32_t testyear = foo1->get(UCAL_YEAR, status);
699 int32_t testmonth = foo1->get(UCAL_MONTH, status);
700 int32_t testday = foo1->get(UCAL_DATE, status);
701 if (testyear != 1997 ||
702 testmonth != 8 ||
703 testday != 28)
704 errln("Fail: Calendar not initialized");
705
706 delete foo1;
707 }
708
709 /**
710 * @bug 4083167
711 */
test4083167()712 void CalendarRegressionTest::test4083167()
713 {
714 UErrorCode status = U_ZERO_ERROR;
715 TimeZone *saveZone = TimeZone::createDefault();
716 //try {
717 TimeZone *newZone = TimeZone::createTimeZone("UTC");
718 TimeZone::setDefault(*newZone);
719 UDate firstDate = Calendar::getNow();
720 Calendar *cal = new GregorianCalendar(status);
721 if(U_FAILURE(status)) {
722 dataerrln("Error creating Calendar: %s", u_errorName(status));
723 delete cal;
724 return;
725 }
726 cal->setTime(firstDate,status);
727 int32_t hr = cal->get(UCAL_HOUR_OF_DAY, status);
728 int32_t min = cal->get(UCAL_MINUTE, status);
729 int32_t sec = cal->get(UCAL_SECOND, status);
730 int32_t msec = cal->get(UCAL_MILLISECOND, status);
731 double firstMillisInDay = hr * 3600000 + min * 60000 + sec * 1000 + msec;
732
733 //logln("Current time: " + firstDate.toString());
734
735 for (int32_t validity=0; validity<30; validity++) {
736 UDate lastDate = firstDate + validity*1000*24*60*60.0;
737 cal->setTime(lastDate, status);
738 hr = cal->get(UCAL_HOUR_OF_DAY, status);
739 min = cal->get(UCAL_MINUTE, status);
740 sec = cal->get(UCAL_SECOND, status);
741 msec = cal->get(UCAL_MILLISECOND, status);
742 double millisInDay = hr * 3600000.0 + min * 60000.0 + sec * 1000.0 + msec;
743 if (firstMillisInDay != millisInDay)
744 errln(UnicodeString("Day has shifted ") + lastDate);
745 }
746 //}
747 //finally {
748 TimeZone::setDefault(*saveZone);
749 //}
750
751 delete saveZone;
752 delete newZone;
753 delete cal;
754 }
755
756 /**
757 * @bug 4086724
758 */
test4086724()759 void CalendarRegressionTest::test4086724()
760 {
761 UErrorCode status = U_ZERO_ERROR;
762 SimpleDateFormat *date;
763 TimeZone *saveZone = TimeZone::createDefault();
764 Locale saveLocale = Locale::getDefault();
765 //try {
766 Locale::setDefault(Locale::getUK(),status);
767 TimeZone *newZone = TimeZone::createTimeZone("GMT");
768 TimeZone::setDefault(*newZone);
769 date = new SimpleDateFormat(UnicodeString("dd MMM yyy (zzzz) 'is in week' ww"),status);
770 Calendar *cal = Calendar::createInstance(status);
771 if(U_FAILURE(status)) {
772 dataerrln("Error creating Calendar: %s", u_errorName(status));
773 delete cal;
774 delete newZone;
775 delete date;
776 return;
777 }
778 cal->set(1997,UCAL_SEPTEMBER,30);
779 UDate now = cal->getTime(status);
780 UnicodeString temp;
781 FieldPosition pos(FieldPosition::DONT_CARE);
782 logln(date->format(now, temp, pos));
783 cal->set(1997,UCAL_JANUARY,1);
784 now=cal->getTime(status);
785 logln(date->format(now,temp, pos));
786 cal->set(1997,UCAL_JANUARY,8);
787 now=cal->getTime(status);
788 logln(date->format(now,temp, pos));
789 cal->set(1996,UCAL_DECEMBER,31);
790 now=cal->getTime(status);
791 logln(date->format(now,temp, pos));
792 //}
793 //finally {
794 Locale::setDefault(saveLocale,status);
795 TimeZone::setDefault(*saveZone);
796 //}
797 logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
798
799 delete newZone;
800 delete cal;
801 delete date;
802 delete saveZone;
803 }
804
805 /**
806 * @bug 4092362
807 */
test4092362()808 void CalendarRegressionTest::test4092362() {
809 UErrorCode status = U_ZERO_ERROR;
810 GregorianCalendar *cal1 = new GregorianCalendar(1997, 10, 11, 10, 20, 40,status);
811 if (U_FAILURE(status)) {
812 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
813 delete cal1;
814 return;
815 }
816 /*cal1.set( Calendar::YEAR, 1997 );
817 cal1.set( Calendar::MONTH, 10 );
818 cal1.set( Calendar::DATE, 11 );
819 cal1.set( Calendar::HOUR, 10 );
820 cal1.set( Calendar::MINUTE, 20 );
821 cal1.set( Calendar::SECOND, 40 ); */
822
823 logln( UnicodeString(" Cal1 = ") + cal1->getTime(status) );
824 logln( UnicodeString(" Cal1 time in ms = ") + cal1->get(UCAL_MILLISECOND,status) );
825 for (int32_t k = 0; k < 100 ; k++)
826 ;
827
828 GregorianCalendar *cal2 = new GregorianCalendar(1997, 10, 11, 10, 20, 40,status);
829 /*cal2.set( Calendar::YEAR, 1997 );
830 cal2.set( Calendar::MONTH, 10 );
831 cal2.set( Calendar::DATE, 11 );
832 cal2.set( Calendar::HOUR, 10 );
833 cal2.set( Calendar::MINUTE, 20 );
834 cal2.set( Calendar::SECOND, 40 ); */
835
836 logln( UnicodeString(" Cal2 = ") + cal2->getTime(status) );
837 logln( UnicodeString(" Cal2 time in ms = ") + cal2->get(UCAL_MILLISECOND,status) );
838 if( *cal1 != *cal2 )
839 errln("Fail: Milliseconds randomized");
840
841 delete cal1;
842 delete cal2;
843 }
844
845 /**
846 * @bug 4095407
847 */
test4095407()848 void CalendarRegressionTest::test4095407()
849 {
850 UErrorCode status = U_ZERO_ERROR;
851 GregorianCalendar *a = new GregorianCalendar(1997,UCAL_NOVEMBER, 13,status);
852 if (U_FAILURE(status)) {
853 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
854 delete a;
855 return;
856 }
857 int32_t dow = a->get(UCAL_DAY_OF_WEEK, status);
858 if (dow != UCAL_THURSDAY)
859 errln(UnicodeString("Fail: Want THURSDAY Got ") + dow);
860
861 delete a;
862 }
863
864 /**
865 * @bug 4096231
866 */
test4096231()867 void CalendarRegressionTest::test4096231()
868 {
869 UErrorCode status = U_ZERO_ERROR;
870 TimeZone *GMT = TimeZone::createTimeZone("GMT");
871 TimeZone *PST = TimeZone::createTimeZone("PST");
872 int32_t sec = 0, min = 0, hr = 0, day = 1, month = 10, year = 1997;
873
874 Calendar *cal1 = new GregorianCalendar(*PST,status);
875 if (U_FAILURE(status)) {
876 dataerrln("Failure new GregorianCalendar: %s", u_errorName(status));
877 delete GMT;
878 delete PST;
879 delete cal1;
880 return;
881 }
882 cal1->setTime(880698639000.0,status);
883 // Issue 1: Changing the timezone doesn't change the
884 // represented time. The old API, pre 1.2.2a requires
885 // setTime to be called in order to update the time fields after the time
886 // zone has been set.
887 int32_t h1,h2;
888 logln(UnicodeString("PST 1 is: ") + (h1=cal1->get(UCAL_HOUR_OF_DAY, status)));
889 cal1->setTimeZone(*GMT);
890 logln(UnicodeString("GMT 2 is: ") + (h2=cal1->get(UCAL_HOUR_OF_DAY, status)));
891 if ((*GMT != *PST) && (h1 == h2))
892 errln("Fail: Hour same in different zones");
893
894 Calendar *cal2 = new GregorianCalendar(*GMT,status);
895 Calendar *cal3 = new GregorianCalendar(*PST,status);
896 cal2->set(UCAL_MILLISECOND, 0);
897 cal3->set(UCAL_MILLISECOND, 0);
898
899 cal2->set(cal1->get(UCAL_YEAR,status),
900 cal1->get(UCAL_MONTH,status),
901 cal1->get(UCAL_DATE,status),
902 cal1->get(UCAL_HOUR_OF_DAY,status),
903 cal1->get(UCAL_MINUTE,status),
904 cal1->get(UCAL_SECOND,status));
905
906 double t1,t2,t3,t4;
907 logln(UnicodeString("RGMT 1 is: ") + (t1=cal2->getTime(status)));
908 cal3->set(year, month, day, hr, min, sec);
909 logln(UnicodeString("RPST 1 is: ") + (t2=cal3->getTime(status)));
910 cal3->setTimeZone(*GMT);
911 logln(UnicodeString("RGMT 2 is: ") + (t3=cal3->getTime(status)));
912 cal3->set(cal1->get(UCAL_YEAR,status),
913 cal1->get(UCAL_MONTH,status),
914 cal1->get(UCAL_DATE,status),
915 cal1->get(UCAL_HOUR_OF_DAY,status),
916 cal1->get(UCAL_MINUTE,status),
917 cal1->get(UCAL_SECOND,status));
918 // Issue 2: Calendar continues to use the timezone in its
919 // constructor for set() conversions, regardless
920 // of calls to setTimeZone()
921 logln(UnicodeString("RGMT 3 is: ") + (t4=cal3->getTime(status)));
922 if (t1 == t2 ||
923 t1 != t4 ||
924 t2 != t3)
925 errln("Fail: Calendar zone behavior faulty");
926
927 delete cal1;
928 delete cal2;
929 delete cal3;
930 delete GMT;
931 delete PST;
932 }
933
934 /**
935 * @bug 4096539
936 */
test4096539()937 void CalendarRegressionTest::test4096539()
938 {
939 UErrorCode status = U_ZERO_ERROR;
940 int32_t y [] = {31,28,31,30,31,30,31,31,30,31,30,31};
941
942 for (int32_t x=0;x<12;x++) {
943 GregorianCalendar *gc = new
944 GregorianCalendar(1997,x,y[x], status);
945 if (U_FAILURE(status)) {
946 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
947 delete gc;
948 return;
949 }
950 int32_t m1,m2;
951 log(UnicodeString("") + (m1=gc->get(UCAL_MONTH,status)+1)+UnicodeString("/")+
952 gc->get(UCAL_DATE,status)+"/"+gc->get(UCAL_YEAR,status)+
953 " + 1mo = ");
954
955 gc->add(UCAL_MONTH, 1,status);
956 logln(UnicodeString("") + (m2=gc->get(UCAL_MONTH,status)+1)+UnicodeString("/")+
957 gc->get(UCAL_DATE,status)+"/"+gc->get(UCAL_YEAR,status)
958 );
959 int32_t m = (m1 % 12) + 1;
960 if (m2 != m)
961 errln(UnicodeString("Fail: Want ") + m + " Got " + m2);
962 delete gc;
963 }
964
965 }
966
967 /**
968 * @bug 4100311
969 */
test41003112()970 void CalendarRegressionTest::test41003112()
971 {
972 UErrorCode status = U_ZERO_ERROR;
973 GregorianCalendar *cal = (GregorianCalendar*)Calendar::createInstance(status);
974 if(U_FAILURE(status)) {
975 dataerrln("Error creating calendar: %s", u_errorName(status));
976 delete cal;
977 return;
978 }
979 cal->set(UCAL_YEAR, 1997);
980 cal->set(UCAL_DAY_OF_YEAR, 1);
981 //UDate d = cal->getTime(status); // Should be Jan 1
982 //logln(d.toString());
983 if (cal->get(UCAL_DAY_OF_YEAR, status) != 1)
984 errln("Fail: DAY_OF_YEAR not set");
985 delete cal;
986 }
987
988 /**
989 * @bug 4103271
990 */
test4103271()991 void CalendarRegressionTest::test4103271()
992 {
993 UErrorCode status = U_ZERO_ERROR;
994 SimpleDateFormat sdf(status);
995 int32_t numYears=40, startYear=1997, numDays=15;
996 UnicodeString output, testDesc, str, str2;
997 GregorianCalendar *testCal = (GregorianCalendar*)Calendar::createInstance(status);
998 if(U_FAILURE(status)) {
999 dataerrln("Error creating calendar: %s", u_errorName(status));
1000 delete testCal;
1001 return;
1002 }
1003 testCal->clear();
1004 sdf.adoptCalendar(testCal);
1005 sdf.applyPattern("EEE dd MMM yyyy 'WOY'ww'-'YYYY 'DOY'DDD");
1006 UBool fail = false;
1007 for (int32_t firstDay=1; firstDay<=2; firstDay++) {
1008 for (int32_t minDays=1; minDays<=7; minDays++) {
1009 testCal->setMinimalDaysInFirstWeek((uint8_t)minDays);
1010 testCal->setFirstDayOfWeek((UCalendarDaysOfWeek)firstDay);
1011 testDesc = (UnicodeString("Test") + firstDay + minDays);
1012 logln(testDesc + " => 1st day of week=" +
1013 firstDay +
1014 ", minimum days in first week=" +
1015 minDays);
1016 for (int32_t j=startYear; j<=startYear+numYears; j++) {
1017 testCal->set(j,11,25);
1018 for(int32_t i=0; i<numDays; i++) {
1019 testCal->add(UCAL_DATE,1,status);
1020 UnicodeString calWOY;
1021 int32_t actWOY = testCal->get(UCAL_WEEK_OF_YEAR,status);
1022 if (actWOY < 1 || actWOY > 53) {
1023 UDate d = testCal->getTime(status);
1024 //calWOY = String.valueOf(actWOY);
1025 UnicodeString temp;
1026 FieldPosition pos(FieldPosition::DONT_CARE);
1027 output = testDesc + " - " + sdf.format(d,temp,pos) + "\t";
1028 output = output + "\t" + actWOY;
1029 logln(output);
1030 fail = true;
1031 }
1032 }
1033 }
1034 }
1035 }
1036
1037 int32_t DATA [] = {
1038 3, 52, 52, 52, 52, 52, 52, 52,
1039 1, 1, 1, 1, 1, 1, 1,
1040 2, 2, 2, 2, 2, 2, 2,
1041 4, 52, 52, 52, 52, 52, 52, 52,
1042 53, 53, 53, 53, 53, 53, 53,
1043 1, 1, 1, 1, 1, 1, 1,
1044 };
1045 testCal->setFirstDayOfWeek(UCAL_SUNDAY);
1046 for (int32_t j=0; j<44; j+=22) {
1047 logln(UnicodeString("Minimal days in first week = ") + DATA[j] +
1048 " Week starts on Sunday");
1049 testCal->setMinimalDaysInFirstWeek((uint8_t)DATA[j]);
1050 testCal->set(1997, UCAL_DECEMBER, 21);
1051 for (int32_t i=0; i<21; ++i) {
1052 int32_t woy = testCal->get(UCAL_WEEK_OF_YEAR,status);
1053 str.remove();
1054 log(UnicodeString("") + sdf.format(testCal->getTime(status), str) +
1055 UnicodeString(" ") + woy);
1056 if (woy != DATA[j + 1 + i]) {
1057 log(" ERROR");
1058 fail = true;
1059 }
1060 logln("");
1061
1062 // Now compute the time from the fields, and make sure we
1063 // get the same answer back. This is a round-trip test.
1064 UDate save = testCal->getTime(status);
1065 testCal->clear();
1066 testCal->set(UCAL_YEAR_WOY, DATA[j+1+i] < 25 ? 1998 : 1997);
1067 testCal->set(UCAL_WEEK_OF_YEAR, DATA[j+1+i]);
1068 testCal->set(UCAL_DAY_OF_WEEK, (i%7) + UCAL_SUNDAY);
1069 if (testCal->getTime(status) != save) {
1070 str.remove();
1071 logln(UnicodeString(" Parse failed: ") +
1072 sdf.format(testCal->getTime(status), str));
1073 fail= true;
1074 }
1075
1076 testCal->setTime(save,status);
1077 testCal->add(UCAL_DATE, 1,status);
1078 }
1079 }
1080 // Test field disambiguation with a few special hard-coded cases.
1081 // This shouldn't fail if the above cases aren't failing.
1082 int32_t DISAM_int [] = {
1083 // y y_woy woy dow
1084 1997, 1998, 1, UCAL_SUNDAY,
1085 (1998), (1998), (2), (UCAL_SATURDAY),
1086 (1998), (1998), (53), (UCAL_THURSDAY),
1087 (1999), (1998), (53), (UCAL_FRIDAY)
1088 };
1089
1090 UDate DISAM_date [] = {
1091 makeDate(1997, UCAL_DECEMBER, 28),
1092 makeDate(1998, UCAL_JANUARY, 10),
1093 makeDate(1998, UCAL_DECEMBER, 31),
1094 makeDate(1999, UCAL_JANUARY, 1)
1095 };
1096
1097 testCal->setMinimalDaysInFirstWeek(3);
1098 testCal->setFirstDayOfWeek(UCAL_SUNDAY);
1099 int32_t i = 0;
1100
1101 /* Enable this code to display various WOY values
1102 testCal->clear();
1103 for (i=25; i<38; ++i) {
1104 testCal->set(1996, Calendar::DECEMBER, i);
1105 UDate got = testCal->getTime(status);
1106 str.remove();
1107 logln(UnicodeString("") + sdf.format(got, str));
1108 }
1109 for (i=25; i<38; ++i) {
1110 testCal->set(1997, Calendar::DECEMBER, i);
1111 UDate got = testCal->getTime(status);
1112 str.remove();
1113 logln(UnicodeString("") + sdf.format(got, str));
1114 }
1115 for (i=25; i<38; ++i) {
1116 testCal->set(1998, UCAL_DECEMBER, i);
1117 UDate got = testCal->getTime(status);
1118 str.remove();
1119 logln(UnicodeString("") + sdf.format(got, str));
1120 }
1121 */
1122
1123 for (i=0; i < 16; i += 4) {
1124 int32_t y = DISAM_int[i];
1125 int32_t ywoy = DISAM_int[i+1];
1126 int32_t woy = DISAM_int[i+2];
1127 int32_t dow = DISAM_int[i+3];
1128 UDate exp = DISAM_date[i/4];
1129 testCal->clear();
1130 testCal->set(UCAL_YEAR, y);
1131 testCal->set(UCAL_WEEK_OF_YEAR, woy);
1132 testCal->set(UCAL_DAY_OF_WEEK, dow);
1133 UDate got = testCal->getTime(status);
1134 str.remove();
1135 str2.remove();
1136 log(UnicodeString("Y") + y + "-W" + woy +
1137 "-DOW" + dow + " expect:" + sdf.format(exp, str) +
1138 " got:" + sdf.format(got, str2));
1139 if (got != exp) {
1140 log(" FAIL (%s:%d, i=%d)", __FILE__, __LINE__, i);
1141 logln(CalendarTest::calToStr(*testCal));
1142 testCal->setTime(exp, status);
1143 logln(CalendarTest::calToStr(*testCal) + UnicodeString( " <<< expected "));
1144 fail = true;
1145 }
1146 logln("");
1147
1148 testCal->clear();
1149 testCal->set(UCAL_YEAR_WOY, ywoy);
1150 testCal->set(UCAL_WEEK_OF_YEAR, woy);
1151 testCal->set(UCAL_DAY_OF_WEEK, dow);
1152 got = testCal->getTime(status);
1153 str.remove();
1154 str2.remove();
1155 log(UnicodeString("YWOY") + ywoy + "-W" + woy +
1156 "-DOW" + dow + " expect:" + sdf.format(exp, str) +
1157 " got:" + sdf.format(got, str2));
1158 if (got != exp) {
1159 log(" FAIL");
1160 fail = true;
1161 }
1162 logln("");
1163 }
1164 // Now try adding and rolling
1165 UDate ADDROLL_date [] = {
1166 makeDate(1998, UCAL_DECEMBER, 25), makeDate(1999, UCAL_JANUARY, 1),
1167 makeDate(1997, UCAL_DECEMBER, 28), makeDate(1998, UCAL_JANUARY, 4),
1168 makeDate(1998, UCAL_DECEMBER, 27), makeDate(1997, UCAL_DECEMBER, 28),
1169 makeDate(1999, UCAL_JANUARY, 2), makeDate(1998, UCAL_JANUARY, 3),
1170 };
1171
1172 int32_t ADDROLL_int []= {
1173 (1),
1174 (1),
1175 (1),
1176 (1)
1177 };
1178
1179
1180 UBool ADDROLL_bool [] = {
1181 true,//ADD,
1182 true,
1183 false,
1184 false
1185 };
1186
1187 testCal->setMinimalDaysInFirstWeek(3);
1188 testCal->setFirstDayOfWeek(UCAL_SUNDAY);
1189 for (i=0; i<8; i += 2) {
1190 int32_t amount = ADDROLL_int[i/2];
1191 UDate before = ADDROLL_date[i];
1192 UDate after = ADDROLL_date[i+1];
1193
1194 testCal->setTime(before,status);
1195 if (ADDROLL_bool[i/2])
1196 testCal->add(UCAL_WEEK_OF_YEAR, amount,status);
1197 else
1198 testCal->roll(UCAL_WEEK_OF_YEAR, amount,status);
1199 UDate got = testCal->getTime(status);
1200 str.remove();
1201 str2.remove();
1202 UnicodeString opTypeStr;
1203 if (ADDROLL_bool[i/2]) {
1204 opTypeStr = UnicodeString("add(WOY,", "");
1205 } else {
1206 opTypeStr = UnicodeString("roll(WOY,", "");
1207 }
1208 log(opTypeStr + amount + ") " + sdf.format(before, str) + " => " +
1209 sdf.format(got, str2));
1210 if (after != got) {
1211 str.remove();
1212 logln(UnicodeString(" exp:") + sdf.format(after, str) + " FAIL");
1213 fail = true;
1214 }
1215 else logln(" ok");
1216
1217 testCal->setTime(after,status);
1218 if (ADDROLL_bool[i/2])
1219 testCal->add(UCAL_WEEK_OF_YEAR, -amount,status);
1220 else
1221 testCal->roll(UCAL_WEEK_OF_YEAR, -amount,status);
1222 got = testCal->getTime(status);
1223 str.remove();
1224 str2.remove();
1225 log(opTypeStr + (-amount) + ") " + sdf.format(after, str) + " => " +
1226 sdf.format(got, str2));
1227 if (before != got) {
1228 str.remove();
1229 logln(UnicodeString(" exp:") + sdf.format(before, str) + " FAIL");
1230 fail = true;
1231 }
1232 else logln(" ok");
1233 }
1234 if (fail)
1235 errln("Fail: Week of year misbehaving");
1236 }
1237
1238 /**
1239 * @bug 4106136
1240 */
test4106136()1241 void CalendarRegressionTest::test4106136()
1242 {
1243 UErrorCode status = U_ZERO_ERROR;
1244 Locale saveLocale = Locale::getDefault();
1245 //try {
1246 Locale locales [] = { Locale::getChinese(), Locale::getChina() };
1247 for (int32_t i=0; i<2; ++i) {
1248 Locale::setDefault(locales[i], status);
1249 failure(status, "Locale::setDefault");
1250 int32_t count1, count2, count3;
1251 Calendar::getAvailableLocales(count1);
1252 DateFormat::getAvailableLocales(count2);
1253 NumberFormat::getAvailableLocales(count3);
1254 int32_t n [] = {
1255 count1, count2, count3
1256 };
1257 for (int32_t j=0; j<3; ++j) {
1258 UnicodeString temp;
1259 if (n[j] == 0)
1260 dataerrln(UnicodeString("Fail: No locales for ") + locales[i].getName());
1261 }
1262 }
1263 //}
1264 //finally {
1265 Locale::setDefault(saveLocale,status);
1266 //}
1267 }
1268
1269 /**
1270 * @bug 4108764
1271 */
test4108764()1272 void CalendarRegressionTest::test4108764()
1273 {
1274 UErrorCode status = U_ZERO_ERROR;
1275 Calendar *cal = Calendar::createInstance(status);
1276 if(U_FAILURE(status)) {
1277 dataerrln("Error creating calendar %s", u_errorName(status));
1278 delete cal;
1279 return;
1280 }
1281 UDate d00 = makeDate(1997, UCAL_MARCH, 15, 12, 00, 00);
1282 UDate d01 = makeDate(1997, UCAL_MARCH, 15, 12, 00, 56);
1283 UDate d10 = makeDate(1997, UCAL_MARCH, 15, 12, 34, 00);
1284 UDate d11 = makeDate(1997, UCAL_MARCH, 15, 12, 34, 56);
1285 UDate epoch = makeDate(1970, UCAL_JANUARY, 1);
1286
1287 cal->setTime(d11,status);
1288
1289 cal->clear( UCAL_MINUTE );
1290 logln(UnicodeString("") + cal->getTime(status));
1291 if (cal->getTime(status) != d01)
1292 errln("Fail: clear(MINUTE) broken");
1293
1294 cal->set( UCAL_SECOND, 0 );
1295 logln(UnicodeString("") + cal->getTime(status));
1296 if (cal->getTime(status) != d00)
1297 errln("Fail: set(SECOND, 0) broken");
1298
1299 cal->setTime(d11,status);
1300 cal->set( UCAL_SECOND, 0 );
1301 logln(UnicodeString("") + cal->getTime(status));
1302 if (cal->getTime(status) != d10)
1303 errln("Fail: set(SECOND, 0) broken #2");
1304
1305 cal->clear( UCAL_MINUTE );
1306 logln(UnicodeString("") + cal->getTime(status));
1307 if (cal->getTime(status) != d00)
1308 errln("Fail: clear(MINUTE) broken #2");
1309
1310 cal->clear();
1311 logln(UnicodeString("") + cal->getTime(status));
1312 if (cal->getTime(status) != epoch)
1313 errln(UnicodeString("Fail: clear() broken Want ") + epoch);
1314
1315 delete cal;
1316 }
1317
1318 /**
1319 * @bug 4114578
1320 */
test4114578()1321 void CalendarRegressionTest::test4114578()
1322 {
1323 UErrorCode status = U_ZERO_ERROR;
1324 double ONE_HOUR = 60*60*1000;
1325 Calendar *cal = Calendar::createInstance(status);
1326 if(U_FAILURE(status)) {
1327 dataerrln("Error creating calendar %s", u_errorName(status));
1328 delete cal;
1329 return;
1330 }
1331 cal->adoptTimeZone(TimeZone::createTimeZone("PST"));
1332 UDate onset = makeDate(1998, UCAL_APRIL, 5, 1, 0) + ONE_HOUR;
1333 UDate cease = makeDate(1998, UCAL_OCTOBER, 25, 0, 0) + 2*ONE_HOUR;
1334
1335 UBool fail = false;
1336
1337 const int32_t ADD = 1;
1338 const int32_t ROLL = 2;
1339
1340 double DATA []= {
1341 // Start Action Amt Expected_change
1342 onset - ONE_HOUR, ADD, 1, ONE_HOUR,
1343 onset, ADD, -1, -ONE_HOUR,
1344 onset - ONE_HOUR, ROLL, 1, ONE_HOUR,
1345 onset, ROLL, -1, -ONE_HOUR,
1346 cease - ONE_HOUR, ADD, 1, ONE_HOUR,
1347 cease, ADD, -1, -ONE_HOUR,
1348 cease - ONE_HOUR, ROLL, 1, ONE_HOUR,
1349 cease, ROLL, -1, -ONE_HOUR,
1350 };
1351
1352 for (int32_t i=0; i<32; i+=4) {
1353 UDate date = DATA[i];
1354 int32_t amt = (int32_t) DATA[i+2];
1355 double expectedChange = DATA[i+3];
1356
1357 log(UnicodeString("") + date);
1358 cal->setTime(date,status);
1359
1360 switch ((int32_t) DATA[i+1]) {
1361 case ADD:
1362 log(UnicodeString(" add (HOUR,") + (amt<0?"":"+")+amt + ")= ");
1363 cal->add(UCAL_HOUR, amt,status);
1364 break;
1365 case ROLL:
1366 log(UnicodeString(" roll(HOUR,") + (amt<0?"":"+")+amt + ")= ");
1367 cal->roll(UCAL_HOUR, amt,status);
1368 break;
1369 }
1370
1371 log(UnicodeString("") + cal->getTime(status));
1372
1373 double change = cal->getTime(status) - date;
1374 if (change != expectedChange) {
1375 fail = true;
1376 logln(" FAIL");
1377 }
1378 else logln(" OK");
1379 }
1380
1381 if (fail) errln("Fail: roll/add misbehaves around DST onset/cease");
1382
1383 delete cal;
1384 }
1385
1386 /**
1387 * @bug 4118384
1388 * Make sure maximum for HOUR field is 11, not 12.
1389 */
test4118384()1390 void CalendarRegressionTest::test4118384()
1391 {
1392 UErrorCode status = U_ZERO_ERROR;
1393 Calendar *cal = Calendar::createInstance(status);
1394 if(U_FAILURE(status)) {
1395 dataerrln("Error creating calendar %s", u_errorName(status));
1396 delete cal;
1397 return;
1398 }
1399 if (cal->getMaximum(UCAL_HOUR) != 11 ||
1400 cal->getLeastMaximum(UCAL_HOUR) != 11 ||
1401 cal->getActualMaximum(UCAL_HOUR,status) != 11)
1402 errln("Fail: maximum of HOUR field should be 11");
1403
1404 // test deprecated functions
1405 if (cal->getLeastMaximum(Calendar::HOUR) != 11 ||
1406 cal->getMaximum(Calendar::HOUR) != 11) {
1407 errln("Fail: [deprecated functions] maximum of HOUR field should be 11\n");
1408 }
1409
1410 if (cal->getGreatestMinimum(Calendar::HOUR) != 0 ||
1411 cal->getMinimum(Calendar::HOUR) != 0) {
1412 errln("Fail: [deprecated functions] minimum of HOUR field should be 1\n");
1413 }
1414
1415 delete cal;
1416 cal = Calendar::createInstance(Locale("th_TH@calendar=buddhist"),status);
1417 if(U_FAILURE(status)) {
1418 dataerrln("Error creating calendar %s", u_errorName(status));
1419 delete cal;
1420 return;
1421 }
1422 // test deprecated functions
1423 if (cal->getLeastMaximum(Calendar::HOUR) != 11 ||
1424 cal->getMaximum(Calendar::HOUR) != 11) {
1425 errln("Fail: Buddhist:[deprecated functions] maximum of HOUR field should be 11\n");
1426 }
1427
1428 if (cal->getGreatestMinimum(Calendar::HOUR) != 0 ||
1429 cal->getMinimum(Calendar::HOUR) != 0) {
1430 errln("Fail: Buddhist:[deprecated functions] minimum of HOUR field should be 1\n");
1431 }
1432
1433 delete cal;
1434 // test deprecated functions
1435 cal = Calendar::createInstance(Locale("ja_JP@calendar=japanese"),status);
1436 if(U_FAILURE(status)) {
1437 dataerrln("Error creating calendar %s", u_errorName(status));
1438 delete cal;
1439 return;
1440 }
1441 if (cal->getLeastMaximum(Calendar::HOUR) != 11 ||
1442 cal->getMaximum(Calendar::HOUR) != 11) {
1443 errln("Fail: Japanese:[deprecated functions] maximum of HOUR field should be 11\n");
1444 }
1445
1446 if (cal->getGreatestMinimum(Calendar::HOUR) != 0 ||
1447 cal->getMinimum(Calendar::HOUR) != 0) {
1448 errln("Fail: Japanese:[deprecated functions] minimum of HOUR field should be 1\n");
1449 }
1450
1451 delete cal;
1452 }
1453
1454 /**
1455 * @bug 4125881
1456 * Check isLeapYear for BC years.
1457 */
test4125881()1458 void CalendarRegressionTest::test4125881()
1459 {
1460 UErrorCode status = U_ZERO_ERROR;
1461 LocalPointer<GregorianCalendar> cal((GregorianCalendar*) Calendar::createInstance(status), status);
1462 if(U_FAILURE(status)) {
1463 dataerrln("Error creating calendar %s", u_errorName(status));
1464 return;
1465 }
1466 SimpleDateFormat fmt(UnicodeString("MMMM d, yyyy G"),status);
1467 if(U_FAILURE(status)) {
1468 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(status));
1469 return;
1470 }
1471 cal->clear();
1472 for (int32_t y=-20; y<=10; ++y) {
1473 cal->set(UCAL_ERA, y < 1 ? GregorianCalendar::BC : GregorianCalendar::AD);
1474 cal->set(UCAL_YEAR, y < 1 ? 1 - y : y);
1475 UnicodeString temp;
1476 logln(UnicodeString("") + y + UnicodeString(" = ") + fmt.format(cal->getTime(status), temp) + " " +
1477 cal->isLeapYear(y));
1478 if (cal->isLeapYear(y) != ((y+40)%4 == 0))
1479 errln("Leap years broken");
1480 }
1481 }
1482
1483 /**
1484 * @bug 4125892
1485 * Prove that GregorianCalendar is proleptic (it used to cut off
1486 * at 45 BC, and not have leap years before then).
1487 */
test4125892()1488 void CalendarRegressionTest::test4125892() {
1489 UErrorCode status = U_ZERO_ERROR;
1490 LocalPointer<GregorianCalendar> cal((GregorianCalendar*) Calendar::createInstance(status), status);
1491 if(U_FAILURE(status)) {
1492 dataerrln("Error creating calendar %s", u_errorName(status));
1493 return;
1494 }
1495 SimpleDateFormat fmt(UnicodeString("MMMM d, yyyy G"),status);
1496 if(U_FAILURE(status)) {
1497 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(status));
1498 return;
1499 }
1500 cal->clear();
1501 cal->set(UCAL_ERA, GregorianCalendar::BC);
1502 cal->set(UCAL_YEAR, 81); // 81 BC is a leap year (proleptically)
1503 cal->set(UCAL_MONTH, UCAL_FEBRUARY);
1504 cal->set(UCAL_DATE, 28);
1505 cal->add(UCAL_DATE, 1,status);
1506 if(U_FAILURE(status))
1507 errln("add(DATE,1) failed");
1508 if (cal->get(UCAL_DATE,status) != 29 ||
1509 !cal->isLeapYear(-80)) // -80 == 81 BC
1510 errln("Calendar not proleptic");
1511
1512 }
1513
1514 /**
1515 * @bug 4141665
1516 * GregorianCalendar::equals() ignores cutover date
1517 */
test4141665()1518 void CalendarRegressionTest::test4141665()
1519 {
1520 UErrorCode status = U_ZERO_ERROR;
1521 GregorianCalendar *cal = new GregorianCalendar(status);
1522 if(U_FAILURE(status)) {
1523 dataerrln("Error creating calendar %s", u_errorName(status));
1524 delete cal;
1525 return;
1526 }
1527 GregorianCalendar *cal2 = cal->clone();
1528 UDate cut = cal->getGregorianChange();
1529 UDate cut2 = cut + 100*24*60*60*1000.0; // 100 days later
1530 if (*cal != *cal2) {
1531 errln("Cloned GregorianCalendars not equal");
1532 }
1533 cal2->setGregorianChange(cut2,status);
1534 if ( *cal == *cal2) {
1535 errln("GregorianCalendar::equals() ignores cutover");
1536 }
1537
1538 delete cal;
1539 delete cal2;
1540 }
1541
1542 const UDate MILLIS_IN_DAY = 86400000.0;
1543 /**
1544 * ICU-13745
1545 * GregorianCalendar::setGregorianChange() overflow
1546 */
Test13745()1547 void CalendarRegressionTest::Test13745()
1548 {
1549 UErrorCode status = U_ZERO_ERROR;
1550 GregorianCalendar *cal = new GregorianCalendar(status);
1551 if(U_FAILURE(status)) {
1552 dataerrln("Error creating calendar %s", u_errorName(status));
1553 delete cal;
1554 return;
1555 }
1556
1557 // this line would overflow before fix 13745
1558 cal->setGregorianChange(((double)INT32_MAX+1.0) * MILLIS_IN_DAY, status);
1559 if(U_FAILURE(status)) {
1560 errln("%s:%d Failure setting INT32_MAX+1 change on calendar: %s\n", __FILE__, __LINE__, u_errorName(status));
1561 return;
1562 }
1563 assertEquals("getGregorianChange()", (double)INT32_MAX * MILLIS_IN_DAY, cal->getGregorianChange());
1564
1565 // test underflow
1566 cal->setGregorianChange(((double)INT32_MIN-1.0) * MILLIS_IN_DAY, status);
1567 if(U_FAILURE(status)) {
1568 errln("%s:%d Failure setting INT32_MAX-1 change on calendar: %s\n", __FILE__, __LINE__, u_errorName(status));
1569 return;
1570 }
1571 assertEquals("getGregorianChange()", (double)INT32_MIN * MILLIS_IN_DAY, cal->getGregorianChange());
1572
1573 delete cal;
1574 }
1575
1576
1577 /**
1578 * @bug 4142933
1579 * Bug states that ArrayIndexOutOfBoundsException is thrown by GregorianCalendar::roll()
1580 * when IllegalArgumentException should be.
1581 */
test4142933()1582 void CalendarRegressionTest::test4142933()
1583 {
1584 UErrorCode status = U_ZERO_ERROR;
1585 GregorianCalendar *calendar = new GregorianCalendar(status);
1586 if(U_FAILURE(status)) {
1587 dataerrln("Error creating calendar %s", u_errorName(status));
1588 delete calendar;
1589 return;
1590 }
1591 //try {
1592 calendar->roll((UCalendarDateFields)-1, true, status);
1593 if(U_SUCCESS(status))
1594 errln("Test failed, no exception thrown");
1595 //}
1596 //catch (IllegalArgumentException e) {
1597 // OK: Do nothing
1598 // logln("Test passed");
1599 //}
1600 //catch (Exception e) {
1601 //errln("Test failed. Unexpected exception is thrown: " + e);
1602 //e.printStackTrace();
1603 //}
1604
1605 delete calendar;
1606 }
1607
1608 /**
1609 * @bug 4145158
1610 * GregorianCalendar handling of Dates Long.MIN_VALUE and Long.MAX_VALUE is
1611 * confusing; unless the time zone has a raw offset of zero, one or the
1612 * other of these will wrap. We've modified the test given in the bug
1613 * report to therefore only check the behavior of a calendar with a zero raw
1614 * offset zone.
1615 */
test4145158()1616 void CalendarRegressionTest::test4145158()
1617 {
1618 UErrorCode status = U_ZERO_ERROR;
1619 GregorianCalendar *calendar = new GregorianCalendar(status);
1620 if(status == U_USING_FALLBACK_WARNING || U_FAILURE(status)) {
1621 dataerrln("Error creating calendar %s", u_errorName(status));
1622 delete calendar;
1623 return;
1624 }
1625
1626 calendar->adoptTimeZone(TimeZone::createTimeZone("GMT"));
1627
1628 calendar->setTime(makeDate(INT32_MIN),status);
1629 int32_t year1 = calendar->get(UCAL_YEAR,status);
1630 int32_t era1 = calendar->get(UCAL_ERA,status);
1631
1632 calendar->setTime(makeDate(INT32_MAX),status);
1633 int32_t year2 = calendar->get(UCAL_YEAR,status);
1634 int32_t era2 = calendar->get(UCAL_ERA,status);
1635
1636 if (year1 == year2 && era1 == era2) {
1637 errln("Fail: Long.MIN_VALUE or Long.MAX_VALUE wrapping around");
1638 }
1639
1640 delete calendar;
1641 }
1642
1643 /**
1644 * @bug 4145983
1645 * Maximum value for YEAR field wrong.
1646 */
1647 // {sfb} this is not directly applicable in C++, since all
1648 // possible doubles are not representable by our Calendar.
1649 // In Java, all longs are representable.
1650 // We can determine limits programmatically
1651 // Using DBL_MAX is a bit of a hack, since for large doubles
1652 // Calendar gets squirrely and doesn't behave in any sort
1653 // of linear fashion (ie years jump around, up/down, etc) for a
1654 // small change in millis.
test4145983()1655 void CalendarRegressionTest::test4145983()
1656 {
1657 UErrorCode status = U_ZERO_ERROR;
1658 GregorianCalendar *calendar = new GregorianCalendar(status);
1659 if(U_FAILURE(status)) {
1660 dataerrln("Error creating calendar %s", u_errorName(status));
1661 delete calendar;
1662 return;
1663 }
1664 calendar->adoptTimeZone(TimeZone::createTimeZone("GMT"));
1665 UDate DATES [] = { LATEST_SUPPORTED_MILLIS, EARLIEST_SUPPORTED_MILLIS };
1666 for (int32_t i=0; i<2; ++i) {
1667 calendar->setTime(DATES[i], status);
1668 int32_t year = calendar->get(UCAL_YEAR,status);
1669 int32_t maxYear = calendar->getMaximum(UCAL_YEAR);
1670 if (year > maxYear) {
1671 errln(UnicodeString("Failed for ")+DATES[i]+" ms: year=" +
1672 year + ", maxYear=" + maxYear);
1673 }
1674 }
1675
1676 delete calendar;
1677 }
1678
1679 /**
1680 * @bug 4147269
1681 * This is a bug in the validation code of GregorianCalendar:: As reported,
1682 * the bug seems worse than it really is, due to a bug in the way the bug
1683 * report test was written. In reality the bug is restricted to the DAY_OF_YEAR
1684 * field. - liu 6/29/98
1685 */
test4147269()1686 void CalendarRegressionTest::test4147269()
1687 {
1688 UErrorCode status = U_ZERO_ERROR;
1689 GregorianCalendar *calendar = new GregorianCalendar(status);
1690 if(status == U_USING_FALLBACK_WARNING || U_FAILURE(status)) {
1691 dataerrln("Error creating calendar %s", u_errorName(status));
1692 delete calendar;
1693 return;
1694 }
1695 calendar->setLenient(false);
1696 UDate date = makeDate(1996, UCAL_JANUARY, 3); // Arbitrary date
1697 for (int32_t field = 0; field < UCAL_FIELD_COUNT; field++) {
1698 calendar->setTime(date,status);
1699 // Note: In the bug report, getActualMaximum() was called instead
1700 // of getMaximum() -- this was an error. The validation code doesn't
1701 // use getActualMaximum(), since that's too costly.
1702 int32_t max = calendar->getMaximum((UCalendarDateFields)field);
1703 int32_t value = max+1;
1704 calendar->set((UCalendarDateFields)field, value);
1705 //try {
1706 calendar->getTime(status); // Force time computation
1707 // We expect an exception to be thrown. If we fall through
1708 // to the next line, then we have a bug.
1709 if(U_SUCCESS(status))
1710 errln(UnicodeString("Test failed with field ") + FIELD_NAME[field] +
1711 ", date before: " + date +
1712 ", date after: " + calendar->getTime(status) +
1713 ", value: " + value + " (max = " + max +")");
1714 //} catch (IllegalArgumentException e) {}
1715 }
1716
1717 delete calendar;
1718 }
1719
1720 /**
1721 * @bug 4149677
1722 * Reported bug is that a GregorianCalendar with a cutover of Date(Long.MAX_VALUE)
1723 * doesn't behave as a pure Julian calendar.
1724 * CANNOT REPRODUCE THIS BUG
1725 */
1726 void
Test4149677()1727 CalendarRegressionTest::Test4149677()
1728 {
1729 UErrorCode status = U_ZERO_ERROR;
1730
1731 TimeZone *zones [] = {
1732 TimeZone::createTimeZone("GMT"),
1733 TimeZone::createTimeZone("PST"),
1734 TimeZone::createTimeZone("EAT")
1735 };
1736 if(U_FAILURE(status)) {
1737 errln("Couldn't create zones");
1738 return;
1739 // could leak memory
1740 }
1741
1742 for (int32_t i=0; i < 3; ++i) {
1743 GregorianCalendar *calendar = new GregorianCalendar(zones[i], status);
1744 if(U_FAILURE(status)) {
1745 dataerrln("Couldn't create calendar.: %s", u_errorName(status));
1746 return;
1747 }
1748
1749 // Make sure extreme values don't wrap around
1750 calendar->setTime(EARLIEST_SUPPORTED_MILLIS, status);
1751 if(U_FAILURE(status))
1752 errln("setTime failed");
1753 if (calendar->get(UCAL_ERA, status) != GregorianCalendar::BC || U_FAILURE(status)) {
1754 errln("Fail: Date(EARLIEST_SUPPORTED_MILLIS) has an AD year");
1755 }
1756 calendar->setTime(LATEST_SUPPORTED_MILLIS, status);
1757 if(U_FAILURE(status))
1758 errln("setTime failed");
1759 if (calendar->get(UCAL_ERA, status) != GregorianCalendar::AD || U_FAILURE(status)) {
1760 errln("Fail: Date(LATEST_SUPPORTED_MILLIS) has a BC year");
1761 }
1762
1763 calendar->setGregorianChange(LATEST_SUPPORTED_MILLIS, status);
1764 if(U_FAILURE(status))
1765 errln("setGregorianChange failed");
1766 // to obtain a pure Julian calendar
1767
1768 UBool is100Leap = calendar->isLeapYear(100);
1769 if (!is100Leap) {
1770 UnicodeString temp;
1771 errln("test failed with zone " + zones[i]->getID(temp));
1772 errln(" cutover date is Date(Long.MAX_VALUE)");
1773 errln(UnicodeString(" isLeapYear(100) returns: ") + is100Leap);
1774 }
1775 delete calendar;
1776 }
1777
1778 // no need for cleanup- zones were adopted
1779 }
1780
1781 /**
1782 * @bug 4162587
1783 * Calendar and Date HOUR broken. If HOUR is out-of-range, Calendar
1784 * and Date classes will misbehave.
1785 */
1786 void
Test4162587()1787 CalendarRegressionTest::Test4162587()
1788 {
1789 UErrorCode status = U_ZERO_ERROR;
1790 TimeZone *savedef = TimeZone::createDefault();
1791 TimeZone *tz = TimeZone::createTimeZone("PST");
1792 //TimeZone::adoptDefault(tz);
1793 TimeZone::setDefault(*tz);
1794
1795 GregorianCalendar *cal = new GregorianCalendar(tz, status);
1796 if(U_FAILURE(status)) {
1797 dataerrln("Couldn't create calendar.: %s", u_errorName(status));
1798 return;
1799 }
1800 UDate d0, dPlus, dMinus;
1801
1802 for(int32_t i=0; i<5; ++i) {
1803 if (i>0) logln("---");
1804
1805 cal->clear();
1806 cal->set(1998, UCAL_APRIL, 5, i, 0);
1807 d0 = cal->getTime(status);
1808 if(U_FAILURE(status))
1809 errln("Coudln't get time (1)");
1810 //String s0 = d.toString();
1811 logln(UnicodeString("0 ") + i + ": " + d0/*s0*/);
1812
1813 cal->clear();
1814 cal->set(1998, UCAL_APRIL, 4, i+24, 0);
1815 dPlus = cal->getTime(status);
1816 if(U_FAILURE(status))
1817 errln("Coudln't get time (2)");
1818 //String sPlus = d.toString();
1819 logln(UnicodeString("+ ") + i + ": " + dPlus/*sPlus*/);
1820
1821 cal->clear();
1822 cal->set(1998, UCAL_APRIL, 6, i-24, 0);
1823 dMinus = cal->getTime(status);
1824 if(U_FAILURE(status))
1825 errln("Coudln't get time (3)");
1826 //String sMinus = d.toString();
1827 logln(UnicodeString("- ") + i + ": " + dMinus/*sMinus*/);
1828
1829 if (d0 != dPlus || d0 != dMinus) {
1830 errln("Fail: All three lines must match");
1831 }
1832 }
1833 TimeZone::setDefault(*savedef);
1834 //delete tz;
1835 delete cal;
1836 delete savedef;
1837 }
1838
1839 /**
1840 * @bug 4165343
1841 * Adding 12 months behaves differently from adding 1 year
1842 */
1843 void
Test4165343()1844 CalendarRegressionTest::Test4165343()
1845 {
1846 UErrorCode status = U_ZERO_ERROR;
1847 GregorianCalendar *calendar = new GregorianCalendar(1996, UCAL_FEBRUARY, 29, status);
1848 if(U_FAILURE(status)) {
1849 dataerrln("Couldn't create calendar.: %s", u_errorName(status));
1850 return;
1851 }
1852 UDate start = calendar->getTime(status);
1853 if(U_FAILURE(status))
1854 errln("Couldn't getTime (1)");
1855 logln(UnicodeString("init date: ") + start);
1856 calendar->add(UCAL_MONTH, 12, status);
1857 if(U_FAILURE(status))
1858 errln("Couldn't add(MONTH, 12)");
1859 UDate date1 = calendar->getTime(status);
1860 if(U_FAILURE(status))
1861 errln("Couldn't getTime (2)");
1862 logln(UnicodeString("after adding 12 months: ") + date1);
1863 calendar->setTime(start, status);
1864 if(U_FAILURE(status))
1865 errln("Couldn't setTime");
1866 calendar->add(UCAL_YEAR, 1, status);
1867 if(U_FAILURE(status))
1868 errln("Couldn't add(YEAR, 1)");
1869 UDate date2 = calendar->getTime(status);
1870 if(U_FAILURE(status))
1871 errln("Couldn't getTime (3)");
1872 logln(UnicodeString("after adding one year : ") + date2);
1873 if (date1 == date2) {
1874 logln("Test passed");
1875 } else {
1876 errln("Test failed");
1877 }
1878 delete calendar;
1879 }
1880
1881 /**
1882 * @bug 4166109
1883 * GregorianCalendar.getActualMaximum() does not account for first day of week.
1884 */
1885 void
Test4166109()1886 CalendarRegressionTest::Test4166109()
1887 {
1888 /* Test month:
1889 *
1890 * March 1998
1891 * Su Mo Tu We Th Fr Sa
1892 * 1 2 3 4 5 6 7
1893 * 8 9 10 11 12 13 14
1894 * 15 16 17 18 19 20 21
1895 * 22 23 24 25 26 27 28
1896 * 29 30 31
1897 */
1898 UBool passed = true;
1899 UErrorCode status = U_ZERO_ERROR;
1900 UCalendarDateFields field = UCAL_WEEK_OF_MONTH;
1901
1902 GregorianCalendar *calendar = new GregorianCalendar(Locale::getUS(), status);
1903 if(U_FAILURE(status)) {
1904 dataerrln("Couldn't create calendar.: %s", u_errorName(status));
1905 return;
1906 }
1907 calendar->set(1998, UCAL_MARCH, 1);
1908 calendar->setMinimalDaysInFirstWeek(1);
1909 logln(UnicodeString("Date: ") + calendar->getTime(status)); // 888817448000
1910
1911 int32_t firstInMonth = calendar->get(UCAL_DATE, status);
1912 if(U_FAILURE(status))
1913 errln("get(D_O_M) failed");
1914
1915 for(int32_t firstInWeek = UCAL_SUNDAY; firstInWeek <= UCAL_SATURDAY; firstInWeek++) {
1916 calendar->setFirstDayOfWeek((UCalendarDaysOfWeek)firstInWeek);
1917 int32_t returned = calendar->getActualMaximum(field, status);
1918 int32_t expected = (31 + ((firstInMonth - firstInWeek + 7)% 7) + 6) / 7;
1919
1920 logln(UnicodeString("First day of week = ") + firstInWeek +
1921 " getActualMaximum(WEEK_OF_MONTH, status) = " + returned +
1922 " expected = " + expected +
1923 ((returned == expected) ? " ok" : " FAIL"));
1924
1925 if (returned != expected) {
1926 passed = false;
1927 }
1928 }
1929 if (!passed) {
1930 errln("Test failed");
1931 }
1932
1933 delete calendar;
1934 }
1935
1936 /**
1937 * @bug 4167060
1938 * Calendar.getActualMaximum(YEAR) works wrong.
1939 */
1940 void
Test4167060()1941 CalendarRegressionTest::Test4167060()
1942 {
1943 UErrorCode status = U_ZERO_ERROR;
1944 UCalendarDateFields field = UCAL_YEAR;
1945 LocalPointer<DateFormat> format (new SimpleDateFormat(UnicodeString("EEE MMM dd HH:mm:ss zzz yyyy G"),
1946 Locale::getUS(), status));
1947 if(U_FAILURE(status)) {
1948 dataerrln("Couldn't create SimpleDateFormat - %s", u_errorName(status));
1949 return;
1950 }
1951
1952 GregorianCalendar calendars [] = {
1953 {100, UCAL_NOVEMBER, 1, status},
1954 {-99 /*100BC*/, UCAL_JANUARY, 1, status},
1955 {1996, UCAL_FEBRUARY, 29, status}
1956 };
1957 if(U_FAILURE(status)) {
1958 errln("Couldn't create GregorianCalendars");
1959 return;
1960 }
1961
1962 UnicodeString id [] = { "Hybrid", "Gregorian", "Julian" };
1963
1964 for (int32_t k=0; k<3; ++k) {
1965 logln("--- " + id[k] + " ---");
1966
1967 for (int32_t j=0; j < 3; ++j) {
1968 GregorianCalendar *calendar = &calendars[j];
1969 if (k == 1) {
1970 calendar->setGregorianChange(EARLIEST_SUPPORTED_MILLIS, status);
1971 }
1972 else if (k == 2) {
1973 calendar->setGregorianChange(LATEST_SUPPORTED_MILLIS, status);
1974 }
1975
1976 if(U_FAILURE(status))
1977 errln("setGregorianChange() failed");
1978 format->adoptCalendar(calendar->clone());
1979
1980 UDate dateBefore = calendar->getTime(status);
1981 if(U_FAILURE(status))
1982 errln("getTime() failed");
1983
1984 int32_t maxYear = calendar->getActualMaximum(field, status);
1985 UnicodeString temp;
1986 logln(UnicodeString("maxYear: ") + maxYear + " for " + format->format(calendar->getTime(status), temp));
1987 temp.remove();
1988 logln("date before: " + format->format(dateBefore, temp));
1989
1990 int32_t years[] = {2000, maxYear-1, maxYear, maxYear+1};
1991
1992 for (int32_t i = 0; i < 4; i++) {
1993 UBool valid = years[i] <= maxYear;
1994 calendar->set(field, years[i]);
1995 UDate dateAfter = calendar->getTime(status);
1996 if(U_FAILURE(status))
1997 errln("getTime() failed");
1998 int32_t newYear = calendar->get(field, status);
1999 if(U_FAILURE(status))
2000 errln(UnicodeString("get(") + (int32_t)field + ") failed");
2001 calendar->setTime(dateBefore, status); // restore calendar for next use
2002 if(U_FAILURE(status))
2003 errln("setTime() failed");
2004
2005 temp.remove();
2006 logln(UnicodeString(" Year ") + years[i] + (valid? " ok " : " bad") +
2007 " => " + format->format(dateAfter, temp));
2008 if (valid && newYear != years[i]) {
2009 errln(UnicodeString(" FAIL: ") + newYear + " should be valid; date, month and time shouldn't change");
2010 }
2011 // {sfb} this next line is a hack, but it should work since if a
2012 // double has an exponent, adding 1 should not yield the same double
2013 else if (!valid && /*newYear == years[i]*/ dateAfter + 1.0 == dateAfter) {
2014 errln(UnicodeString(" FAIL: ") + newYear + " should be invalid");
2015 }
2016 }
2017 }
2018 }
2019 }
2020
2021 /**
2022 * Week of year is wrong at the start and end of the year.
2023 */
Test4197699()2024 void CalendarRegressionTest::Test4197699() {
2025 UErrorCode status = U_ZERO_ERROR;
2026 GregorianCalendar cal(status);
2027 cal.setFirstDayOfWeek(UCAL_MONDAY);
2028 cal.setMinimalDaysInFirstWeek(4);
2029 SimpleDateFormat fmt("E dd MMM yyyy 'DOY='D 'WOY='w",
2030 Locale::getUS(), status);
2031 fmt.setCalendar(cal);
2032 if (U_FAILURE(status)) {
2033 dataerrln("Couldn't initialize test - %s", u_errorName(status));
2034 return;
2035 }
2036
2037 int32_t DATA[] = {
2038 2000, UCAL_JANUARY, 1, 52,
2039 2001, UCAL_DECEMBER, 31, 1,
2040 };
2041 int32_t DATA_length = UPRV_LENGTHOF(DATA);
2042
2043 UnicodeString str;
2044 DateFormat& dfmt = *(DateFormat*)&fmt;
2045 for (int32_t i=0; i<DATA_length; ) {
2046 cal.clear();
2047 cal.set(DATA[i], DATA[i+1], DATA[i+2]);
2048 i += 3;
2049 int32_t expWOY = DATA[i++];
2050 int32_t actWOY = cal.get(UCAL_WEEK_OF_YEAR, status);
2051 if (expWOY == actWOY) {
2052 logln(UnicodeString("Ok: ") + dfmt.format(cal.getTime(status), str.remove()));
2053 } else {
2054 errln(UnicodeString("FAIL: ") + dfmt.format(cal.getTime(status), str.remove())
2055 + ", expected WOY=" + expWOY);
2056 cal.add(UCAL_DATE, -8, status);
2057 for (int j=0; j<14; ++j) {
2058 cal.add(UCAL_DATE, 1, status);
2059 logln(dfmt.format(cal.getTime(status), str.remove()));
2060 }
2061 }
2062 if (U_FAILURE(status)) {
2063 errln("FAIL: Unexpected error from Calendar");
2064 return;
2065 }
2066 }
2067 }
2068
2069 enum Action { ADD=1, ROLL=2 };
2070 enum Sign { PLUS=1, MINUS=2 };
2071
2072 #define ONE_HOUR (60*60*1000)
2073 #define ONE_DAY (24*ONE_HOUR)
2074
2075 typedef struct {
2076 UCalendarDateFields field;
2077 int8_t actionMask; // ADD or ROLL or both
2078 int8_t signMask; // PLUS or MINUS or both
2079 int32_t amount;
2080 int32_t before; // ms before cutover
2081 int32_t after; // ms after cutover
2082 } J81_DATA;
2083
2084 /**
2085 * Rolling and adding across the Gregorian cutover should work as expected.
2086 * Jitterbug 81.
2087 */
TestJ81()2088 void CalendarRegressionTest::TestJ81() {
2089 UErrorCode status = U_ZERO_ERROR;
2090 UnicodeString temp, temp2, temp3;
2091 int32_t i;
2092 GregorianCalendar cal(TimeZone::createTimeZone("GMT"), Locale::getUS(), status);
2093 SimpleDateFormat fmt("HH:mm 'w'w 'd'D E d MMM yyyy", Locale::getUS(), status);
2094 if (U_FAILURE(status)) {
2095 dataerrln("Error: Cannot create calendar or format - %s", u_errorName(status));
2096 return;
2097 }
2098 fmt.setCalendar(cal);
2099 // Get the Gregorian cutover
2100 UDate cutover = cal.getGregorianChange();
2101 UDate days = ONE_DAY;
2102 days = cutover/days;
2103 logln(UnicodeString("Cutover: {") +
2104 fmt.format(cutover, temp) + "}(epoch days-" + (int)days + ", jd" + (2440588 + days) +")");
2105
2106 // Check woy and doy handling. Reference data:
2107 /* w40 d274 Mon 1 Oct 1582
2108 w40 d275 Tue 2 Oct 1582
2109 w40 d276 Wed 3 Oct 1582
2110 w40 d277 Thu 4 Oct 1582
2111 w40 d278 Fri 15 Oct 1582
2112 w40 d279 Sat 16 Oct 1582
2113 w41 d280 Sun 17 Oct 1582
2114 w41 d281 Mon 18 Oct 1582
2115 w41 d282 Tue 19 Oct 1582
2116 w41 d283 Wed 20 Oct 1582
2117 w41 d284 Thu 21 Oct 1582
2118 w41 d285 Fri 22 Oct 1582
2119 w41 d286 Sat 23 Oct 1582
2120 w42 d287 Sun 24 Oct 1582
2121 w42 d288 Mon 25 Oct 1582
2122 w42 d289 Tue 26 Oct 1582
2123 w42 d290 Wed 27 Oct 1582
2124 w42 d291 Thu 28 Oct 1582
2125 w42 d292 Fri 29 Oct 1582
2126 w42 d293 Sat 30 Oct 1582
2127 w43 d294 Sun 31 Oct 1582
2128 w43 d295 Mon 1 Nov 1582 */
2129 int32_t DOY_DATA[] = {
2130 // dom, woy, doy
2131 1, 40, 274, UCAL_MONDAY,
2132 4, 40, 277, UCAL_THURSDAY,
2133 15, 40, 278, UCAL_FRIDAY,
2134 17, 41, 280, UCAL_SUNDAY,
2135 24, 42, 287, UCAL_SUNDAY,
2136 25, 42, 288, UCAL_MONDAY,
2137 26, 42, 289, UCAL_TUESDAY,
2138 27, 42, 290, UCAL_WEDNESDAY,
2139 28, 42, 291, UCAL_THURSDAY,
2140 29, 42, 292, UCAL_FRIDAY,
2141 30, 42, 293, UCAL_SATURDAY,
2142 31, 43, 294, UCAL_SUNDAY
2143 };
2144 int32_t DOY_DATA_length = UPRV_LENGTHOF(DOY_DATA);
2145
2146 for (i=0; i<DOY_DATA_length; i+=4) {
2147 // Test time->fields
2148 cal.set(1582, UCAL_OCTOBER, DOY_DATA[i]);
2149 int32_t woy = cal.get(UCAL_WEEK_OF_YEAR, status);
2150 int32_t doy = cal.get(UCAL_DAY_OF_YEAR, status);
2151 int32_t dow = cal.get(UCAL_DAY_OF_WEEK, status);
2152 if (U_FAILURE(status)) {
2153 errln("Error: get() failed");
2154 break;
2155 }
2156 if (woy != DOY_DATA[i+1] || doy != DOY_DATA[i+2] || dow != DOY_DATA[i+3]) {
2157 errln((UnicodeString)"Fail: expect woy=" + DOY_DATA[i+1] +
2158 ", doy=" + DOY_DATA[i+2] + ", dow=" + DOY_DATA[i+3] + " on " +
2159 fmt.format(cal.getTime(status), temp.remove()) +
2160 " set(1582,OCTOBER, " + DOY_DATA[i] + ")");
2161 logln(CalendarTest::calToStr(cal));
2162 status = U_ZERO_ERROR;
2163 } else {
2164 logln((UnicodeString)"PASS: expect woy=" + DOY_DATA[i+1] +
2165 ", doy=" + DOY_DATA[i+2] + ", dow=" + DOY_DATA[i+3] + " on " +
2166 fmt.format(cal.getTime(status), temp.remove()));
2167 logln(CalendarTest::calToStr(cal));
2168 status = U_ZERO_ERROR;
2169 }
2170 // Test fields->time for WOY
2171 cal.clear();
2172 cal.set(UCAL_YEAR, 1582);
2173 cal.set(UCAL_WEEK_OF_YEAR, DOY_DATA[i+1]);
2174 cal.set(UCAL_DAY_OF_WEEK, DOY_DATA[i+3]);
2175 int32_t dom = cal.get(UCAL_DATE, status);
2176 if (U_FAILURE(status)) {
2177 errln("Error: get() failed");
2178 break;
2179 }
2180 if (dom != DOY_DATA[i]) {
2181 errln((UnicodeString)"Fail: set woy=" + DOY_DATA[i+1] +
2182 " dow=" + DOY_DATA[i+3] + " => " +
2183 fmt.format(cal.getTime(status), temp.remove()) +
2184 ", expected 1582 Oct " + DOY_DATA[i]);
2185 logln(CalendarTest::calToStr(cal));
2186 status = U_ZERO_ERROR;
2187 }
2188
2189 // Test fields->time for DOY
2190 cal.clear();
2191 cal.set(UCAL_YEAR, 1582);
2192 cal.set(UCAL_DAY_OF_YEAR, DOY_DATA[i+2]);
2193 dom = cal.get(UCAL_DATE, status);
2194 if (U_FAILURE(status)) {
2195 errln("Error: get() failed");
2196 break;
2197 }
2198 if (dom != DOY_DATA[i]) {
2199 errln((UnicodeString)"Fail: set doy=" + DOY_DATA[i+2] +
2200 " => " +
2201 fmt.format(cal.getTime(status), temp.remove()) +
2202 ", expected 1582 Oct " + DOY_DATA[i]);
2203 status = U_ZERO_ERROR;
2204 }
2205 }
2206 status = U_ZERO_ERROR;
2207
2208 #define ADD_ROLL ADD|ROLL
2209 #define PLUS_MINUS PLUS|MINUS
2210 // Test cases
2211 J81_DATA DATA[] = {
2212 { UCAL_WEEK_OF_YEAR, ADD_ROLL, PLUS_MINUS, 1, -ONE_DAY, +6*ONE_DAY },
2213 { UCAL_WEEK_OF_YEAR, ADD_ROLL, PLUS_MINUS, 1, -ONE_DAY, +6*ONE_DAY },
2214 { UCAL_WEEK_OF_MONTH, ADD|ROLL, PLUS|MINUS, 1, -ONE_DAY, +6*ONE_DAY },
2215 { UCAL_DATE, ADD|ROLL, PLUS|MINUS, 2, -ONE_DAY, +1*ONE_DAY },
2216 { UCAL_DATE, ROLL, PLUS, -6, -ONE_DAY, +14*ONE_DAY },
2217 { UCAL_DATE, ROLL, PLUS, -7, 0, +14*ONE_DAY },
2218 { UCAL_DATE, ROLL, PLUS, -7, +ONE_DAY, +15*ONE_DAY },
2219 { UCAL_DATE, ROLL, PLUS, +18, -ONE_DAY, -4*ONE_DAY },
2220 { UCAL_DAY_OF_YEAR, ADD|ROLL, PLUS|MINUS, 2, -ONE_DAY, +1*ONE_DAY },
2221 { UCAL_DAY_OF_WEEK, ADD|ROLL, PLUS|MINUS, 2, -ONE_DAY, +1*ONE_DAY },
2222 { UCAL_DAY_OF_WEEK_IN_MONTH, ADD|ROLL, PLUS|MINUS, 1, -ONE_DAY, +6*ONE_DAY },
2223 { UCAL_AM_PM, ADD, PLUS|MINUS, 4, -12*ONE_HOUR, +36*ONE_HOUR },
2224 { UCAL_HOUR, ADD, PLUS|MINUS, 48, -12*ONE_HOUR, +36*ONE_HOUR },
2225 { UCAL_HOUR_OF_DAY, ADD, PLUS|MINUS, 48, -12*ONE_HOUR, +36*ONE_HOUR },
2226 { UCAL_MINUTE, ADD, PLUS|MINUS, 48*60, -12*ONE_HOUR, +36*ONE_HOUR },
2227 { UCAL_SECOND, ADD, PLUS|MINUS, 48*60*60, -12*ONE_HOUR, +36*ONE_HOUR },
2228 { UCAL_MILLISECOND, ADD, PLUS|MINUS, 48*ONE_HOUR, -12*ONE_HOUR, +36*ONE_HOUR },
2229 // NOTE: These are not supported yet. See jitterbug 180.
2230 // Uncomment these lines when add/roll supported on these fields.
2231 // { Calendar::YEAR_WOY, ADD|ROLL, 1, -ONE_DAY, +6*ONE_DAY },
2232 // { Calendar::DOW_LOCAL, ADD|ROLL, 2, -ONE_DAY, +1*ONE_DAY }
2233 };
2234 int32_t DATA_length = UPRV_LENGTHOF(DATA);
2235
2236 // Now run the tests
2237 for (i=0; i<DATA_length; ++i) {
2238 for (Action action=ADD; action<=ROLL; action=(Action)(action+1)) {
2239 if (!(DATA[i].actionMask & action)) {
2240 continue;
2241 }
2242 for (Sign sign=PLUS; sign<=MINUS; sign=(Sign)(sign+1)) {
2243 if (!(DATA[i].signMask & sign)) {
2244 continue;
2245 }
2246 status = U_ZERO_ERROR;
2247 int32_t amount = DATA[i].amount * (sign==MINUS?-1:1);
2248 UDate date = cutover +
2249 (sign==PLUS ? DATA[i].before : DATA[i].after);
2250 UDate expected = cutover +
2251 (sign==PLUS ? DATA[i].after : DATA[i].before);
2252 cal.setTime(date, status);
2253 if (U_FAILURE(status)) {
2254 errln((UnicodeString)"FAIL: setTime returned error code " + u_errorName(status));
2255 continue;
2256 }
2257 if (action == ADD) {
2258 cal.add(DATA[i].field, amount, status);
2259 } else {
2260 cal.roll(DATA[i].field, amount, status);
2261 }
2262 if (U_FAILURE(status)) {
2263 errln((UnicodeString)"FAIL: " +
2264 (action==ADD?"add ":"roll ") + FIELD_NAME[DATA[i].field] +
2265 " returned error code " + u_errorName(status));
2266 continue;
2267 }
2268 UDate result = cal.getTime(status);
2269 if (U_FAILURE(status)) {
2270 errln((UnicodeString)"FAIL: getTime returned error code " + u_errorName(status));
2271 continue;
2272 }
2273 if (result == expected) {
2274 logln((UnicodeString)"Ok: {" +
2275 fmt.format(date, temp.remove()) +
2276 "}(" + date/ONE_DAY +
2277 (action==ADD?") add ":") roll ") +
2278 amount + " " + FIELD_NAME[DATA[i].field] + " -> {" +
2279 fmt.format(result, temp2.remove()) +
2280 "}(" + result/ONE_DAY + ")");
2281 } else {
2282 errln((UnicodeString)"FAIL: {" +
2283 fmt.format(date, temp.remove()) +
2284 "}(" + date/ONE_DAY +
2285 (action==ADD?") add ":") roll ") +
2286 amount + " " + FIELD_NAME[DATA[i].field] + " -> {" +
2287 fmt.format(result, temp2.remove()) +
2288 "}(" + result/ONE_DAY + "), expect {" +
2289 fmt.format(expected, temp3.remove()) +
2290 "}(" + expected/ONE_DAY + ")");
2291 }
2292 }
2293 }
2294 }
2295 }
2296
2297 /**
2298 * Test fieldDifference().
2299 */
TestJ438(void)2300 void CalendarRegressionTest::TestJ438(void) {
2301 UErrorCode ec = U_ZERO_ERROR;
2302 int32_t DATA[] = {
2303 2000, UCAL_JANUARY, 20, 2010, UCAL_JUNE, 15,
2304 2010, UCAL_JUNE, 15, 2000, UCAL_JANUARY, 20,
2305 1964, UCAL_SEPTEMBER, 7, 1999, UCAL_JUNE, 4,
2306 1999, UCAL_JUNE, 4, 1964, UCAL_SEPTEMBER, 7,
2307 };
2308 int32_t DATA_length = UPRV_LENGTHOF(DATA);
2309 LocalPointer<Calendar> pcal(Calendar::createInstance(Locale::getUS(), ec));
2310 if(U_FAILURE(ec)) {
2311 dataerrln("Error creating calendar %s", u_errorName(ec));
2312 return;
2313 }
2314 Calendar& cal = *pcal;
2315 int32_t i;
2316 SimpleDateFormat fmt(UnicodeString("MMM dd yyyy",""), ec);
2317 if (U_FAILURE(ec)) {
2318 dataerrln("Error creating calendar %s", u_errorName(ec));
2319 return;
2320 }
2321 fmt.setCalendar(cal);
2322 UnicodeString s, t, u;
2323 if (U_SUCCESS(ec)) {
2324 for (i=0; i<DATA_length; i+=6) {
2325 int32_t y1 = DATA[i];
2326 int32_t m1 = DATA[i+1];
2327 int32_t d1 = DATA[i+2];
2328 int32_t y2 = DATA[i+3];
2329 int32_t m2 = DATA[i+4];
2330 int32_t d2 = DATA[i+5];
2331
2332 cal.clear();
2333 cal.set(y1, m1, d1);
2334 UDate date1 = cal.getTime(ec);
2335 if (failure(ec, "getTime"))
2336 break;
2337 cal.set(y2, m2, d2);
2338 UDate date2 = cal.getTime(ec);
2339 if (failure(ec, "getTime"))
2340 break;
2341
2342 cal.setTime(date1, ec);
2343 if (failure(ec, "setTime"))
2344 break;
2345 int32_t dy = cal.fieldDifference(date2, UCAL_YEAR, ec);
2346 int32_t dm = cal.fieldDifference(date2, UCAL_MONTH, ec);
2347 int32_t dd = cal.fieldDifference(date2, UCAL_DATE, ec);
2348 if (failure(ec, "fieldDifference"))
2349 break;
2350
2351 {
2352 LocalPointer<Calendar> cal2(cal.clone());
2353 UErrorCode ec2 = U_ZERO_ERROR;
2354
2355 cal2->setTime(date1, ec2);
2356
2357 int32_t dy2 = cal2->fieldDifference(date2, Calendar::YEAR, ec2);
2358 int32_t dm2 = cal2->fieldDifference(date2, Calendar::MONTH, ec2);
2359 int32_t dd2 = cal2->fieldDifference(date2, Calendar::DATE, ec2);
2360 if (failure(ec2, "fieldDifference(date, Calendar::DATE, ec)"))
2361 break;
2362 if( (dd2 != dd) ||
2363 (dm2 != dm) ||
2364 (dy2 != dy)){
2365 errln("fieldDifference(UCAL_...) and fieldDifference(Calendar::...) give different results!\n");
2366 }
2367 }
2368
2369
2370 logln(UnicodeString("") +
2371 fmt.format(date2, s.remove()) + " - " +
2372 fmt.format(date1, t.remove()) + " = " +
2373 dy + "y " + dm + "m " + dd + "d");
2374
2375 cal.setTime(date1, ec);
2376 if (failure(ec, "setTime"))
2377 break;
2378 cal.add(UCAL_YEAR, dy, ec);
2379 cal.add(UCAL_MONTH, dm, ec);
2380 cal.add(UCAL_DATE, dd, ec);
2381 if (failure(ec, "add"))
2382 break;
2383 UDate date22 = cal.getTime(ec);
2384 if (failure(ec, "getTime"))
2385 break;
2386 if (date2 != date22) {
2387 errln(UnicodeString("FAIL: ") +
2388 fmt.format(date1, s.remove()) + " + " +
2389 dy + "y " + dm + "m " + dd + "d = " +
2390 fmt.format(date22, t.remove()) + ", exp " +
2391 fmt.format(date2, u.remove()));
2392 } else {
2393 logln(UnicodeString("Ok: ") +
2394 fmt.format(date1, s.remove()) + " + " +
2395 dy + "y " + dm + "m " + dd + "d = " +
2396 fmt.format(date22, t.remove()));
2397 }
2398 }
2399 } else {
2400 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(ec));
2401 }
2402 }
2403
TestT5555()2404 void CalendarRegressionTest::TestT5555()
2405 {
2406 UErrorCode ec = U_ZERO_ERROR;
2407 Calendar *cal = Calendar::createInstance(ec);
2408
2409 if (cal == NULL || U_FAILURE(ec)) {
2410 dataerrln("FAIL: Calendar::createInstance(): %s", u_errorName(ec));
2411 delete cal;
2412 return;
2413 }
2414
2415 // Set to Wednesday, February 21, 2007
2416 cal->set(2007, UCAL_FEBRUARY, 21);
2417
2418 // Advance three years
2419 cal->add(UCAL_MONTH, 36, ec);
2420
2421 // Set to last Wednesday of the month
2422 cal->set(UCAL_DAY_OF_WEEK_IN_MONTH, -1);
2423
2424 cal->getTime(ec);
2425
2426 int32_t yy, mm, dd, ee;
2427
2428 yy = cal->get(UCAL_YEAR, ec);
2429 mm = cal->get(UCAL_MONTH, ec);
2430 dd = cal->get(UCAL_DATE, ec);
2431 ee = cal->get(UCAL_DAY_OF_WEEK, ec);
2432
2433 // Should be set to Wednesday, February 24, 2010
2434 if (U_FAILURE(ec) || yy != 2010 || mm != UCAL_FEBRUARY || dd != 24 || ee != UCAL_WEDNESDAY) {
2435 errln("FAIL: got date %4d/%02d/%02d, expected 210/02/24: ", yy, mm + 1, dd);
2436 }
2437 delete cal;
2438 }
2439
2440 typedef struct {
2441 int32_t startYear;
2442 int32_t startMonth; // 0-based
2443 int32_t startDay; // 1-based
2444 UCalendarDateFields fieldToChange;
2445 int32_t fieldDelta;
2446 int32_t endYear;
2447 int32_t endMonth; // 0-based
2448 int32_t endDay; // 1-based
2449 } CoptEthCalTestItem;
2450
2451 // year 1724 in coptic calendar =
2452 // year 2000 in ethiopic calendar (276 more than coptic) =
2453 // year 7500 in ethiopic-amete-alem calendar (5776 more than coptic)
2454 // (2007-2008 in gregorian calendar depending on month)
2455 static const CoptEthCalTestItem coptEthCalTestItems[] = {
2456 { 1724, 12, 1, UCAL_MONTH, +1, 1725, 0, 1 },
2457 { 1724, 12, 1, UCAL_MONTH, +9, 1725, 8, 1 },
2458 { 1723, 12, 2, UCAL_MONTH, +1, 1724, 0, 2 }, // 1723 is a leap year
2459 { 1723, 12, 2, UCAL_MONTH, +9, 1724, 8, 2 },
2460 { 1725, 0, 1, UCAL_MONTH, -1, 1724, 12, 1 },
2461 { 1725, 0, 1, UCAL_MONTH, -6, 1724, 7, 1 },
2462 { 1724, 12, 1, UCAL_DATE, +8, 1725, 0, 4 },
2463 { 1723, 12, 1, UCAL_DATE, +8, 1724, 0, 3 }, // 1723 is a leap year
2464 { 1724, 0, 1, UCAL_DATE, -1, 1723, 12, 6 }, // 1723 is a leap year
2465 { 0, 0, 0, (UCalendarDateFields)0, 0, 0, 0, 0 } // terminator
2466 };
2467
2468 typedef struct {
2469 const char * locale;
2470 int32_t yearOffset;
2471 } CoptEthCalLocale;
2472
2473 static const CoptEthCalLocale copEthCalLocales[] = {
2474 { "en@calendar=coptic", 0 },
2475 { "en@calendar=ethiopic", 276 },
2476 { NULL, 0 } // terminator
2477 };
2478
TestT6745()2479 void CalendarRegressionTest::TestT6745()
2480 {
2481 const CoptEthCalLocale * testLocalePtr;
2482 for ( testLocalePtr = copEthCalLocales; testLocalePtr->locale != NULL; ++testLocalePtr) {
2483 UErrorCode status = U_ZERO_ERROR;
2484 Calendar *cal = Calendar::createInstance(Locale(testLocalePtr->locale), status);
2485 if ( U_FAILURE(status) ) {
2486 dataerrln((UnicodeString)"FAIL: Calendar::createInstance, locale " + testLocalePtr->locale + ", status " + u_errorName(status));
2487 continue;
2488 }
2489 const CoptEthCalTestItem * testItemPtr;
2490 for (testItemPtr = coptEthCalTestItems; testItemPtr->fieldDelta != 0; ++testItemPtr) {
2491 status = U_ZERO_ERROR;
2492 cal->set( testItemPtr->startYear + testLocalePtr->yearOffset, testItemPtr->startMonth, testItemPtr->startDay, 9, 0 );
2493 cal->add( testItemPtr->fieldToChange, testItemPtr->fieldDelta, status );
2494 if ( U_FAILURE(status) ) {
2495 errln((UnicodeString)"FAIL: Calendar::add, locale " + testLocalePtr->locale + ", field/delta " +
2496 testItemPtr->fieldToChange + "/" + testItemPtr->fieldDelta + ", status " + u_errorName(status));
2497 continue;
2498 }
2499 int32_t endYear = testItemPtr->endYear + testLocalePtr->yearOffset;
2500 int32_t year = cal->get(UCAL_YEAR, status);
2501 int32_t month = cal->get(UCAL_MONTH, status);
2502 int32_t day = cal->get(UCAL_DATE, status);
2503 if ( U_FAILURE(status) || year != endYear || month != testItemPtr->endMonth || day != testItemPtr->endDay ) {
2504 errln((UnicodeString)"ERROR: Calendar::add, locale " + testLocalePtr->locale + ", field/delta " +
2505 testItemPtr->fieldToChange + "/" + testItemPtr->fieldDelta + ", status " + u_errorName(status) +
2506 ", expected " + endYear + "/" + testItemPtr->endMonth + "/" + testItemPtr->endDay +
2507 ", got " + year + "/" + month + "/" + day );
2508 }
2509 }
2510 delete cal;
2511 }
2512 }
2513
2514 /**
2515 * Test behavior of fieldDifference around leap years. Also test a large
2516 * field difference to check binary search.
2517 */
TestLeapFieldDifference()2518 void CalendarRegressionTest::TestLeapFieldDifference() {
2519 UErrorCode ec = U_ZERO_ERROR;
2520 Calendar* cal = Calendar::createInstance(ec);
2521 if (cal == NULL || U_FAILURE(ec)) {
2522 dataerrln("FAIL: Calendar::createInstance(): %s", u_errorName(ec));
2523 delete cal;
2524 return;
2525 }
2526 cal->set(2004, UCAL_FEBRUARY, 29);
2527 UDate date2004 = cal->getTime(ec);
2528 cal->set(2000, UCAL_FEBRUARY, 29);
2529 UDate date2000 = cal->getTime(ec);
2530 if (U_FAILURE(ec)) {
2531 errln("FAIL: getTime()");
2532 delete cal;
2533 return;
2534 }
2535 int32_t y = cal->fieldDifference(date2004, UCAL_YEAR, ec);
2536 int32_t d = cal->fieldDifference(date2004, UCAL_DAY_OF_YEAR, ec);
2537 if (U_FAILURE(ec)) {
2538 errln("FAIL: fieldDifference()");
2539 delete cal;
2540 return;
2541 }
2542 if (d == 0) {
2543 logln((UnicodeString)"Ok: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, " + d + " days");
2544 } else {
2545 errln((UnicodeString)"FAIL: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, " + d + " days");
2546 }
2547 cal->setTime(date2004, ec);
2548 y = cal->fieldDifference(date2000, UCAL_YEAR, ec);
2549 d = cal->fieldDifference(date2000, UCAL_DAY_OF_YEAR, ec);
2550 if (U_FAILURE(ec)) {
2551 errln("FAIL: setTime() / fieldDifference()");
2552 delete cal;
2553 return;
2554 }
2555 if (d == 0) {
2556 logln((UnicodeString)"Ok: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, " + d + " days");
2557 } else {
2558 errln((UnicodeString)"FAIL: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, " + d + " days");
2559 }
2560 // Test large difference
2561 cal->set(2001, UCAL_APRIL, 5); // 2452005
2562 UDate ayl = cal->getTime(ec);
2563 cal->set(1964, UCAL_SEPTEMBER, 7); // 2438646
2564 UDate asl = cal->getTime(ec);
2565 if (U_FAILURE(ec)) {
2566 errln("FAIL: getTime()");
2567 delete cal;
2568 return;
2569 }
2570 d = cal->fieldDifference(ayl, UCAL_DATE, ec);
2571 cal->setTime(ayl, ec);
2572 int32_t d2 = cal->fieldDifference(asl, UCAL_DATE, ec);
2573 if (U_FAILURE(ec)) {
2574 errln("FAIL: setTime() / fieldDifference()");
2575 delete cal;
2576 return;
2577 }
2578 if (d == -d2 && d == 13359) {
2579 logln((UnicodeString)"Ok: large field difference symmetrical " + d);
2580 } else {
2581 logln((UnicodeString)"FAIL: large field difference incorrect " + d + ", " + d2 +
2582 ", expect +/- 13359");
2583 }
2584 delete cal;
2585 }
2586
2587 /**
2588 * Test ms_MY "Malay (Malaysia)" locale. Bug 1543.
2589 */
TestMalaysianInstance()2590 void CalendarRegressionTest::TestMalaysianInstance() {
2591 Locale loc("ms", "MY"); // Malay (Malaysia)
2592 UErrorCode ec = U_ZERO_ERROR;
2593 Calendar* cal = Calendar::createInstance(loc, ec);
2594 if (U_FAILURE(ec)) {
2595 dataerrln("FAIL: Can't construct calendar for ms_MY: %s", u_errorName(ec));
2596 }
2597 delete cal;
2598 }
2599
2600 /**
2601 * setFirstDayOfWeek and setMinimalDaysInFirstWeek may change the
2602 * field <=> time mapping, since they affect the interpretation of
2603 * the WEEK_OF_MONTH or WEEK_OF_YEAR fields.
2604 */
TestWeekShift()2605 void CalendarRegressionTest::TestWeekShift() {
2606 UErrorCode ec = U_ZERO_ERROR;
2607 GregorianCalendar cal(TimeZone::createTimeZone("America/Los_Angeles"),
2608 Locale("en", "US"), ec);
2609 if (U_FAILURE(ec)) {
2610 dataerrln("Fail GregorianCalendar: %s", u_errorName(ec));
2611 return;
2612 }
2613 cal.setTime(UDate(997257600000.0), ec); // Wed Aug 08 01:00:00 PDT 2001
2614 // In pass one, change the first day of week so that the weeks
2615 // shift in August 2001. In pass two, change the minimal days
2616 // in the first week so that the weeks shift in August 2001.
2617 // August 2001
2618 // Su Mo Tu We Th Fr Sa
2619 // 1 2 3 4
2620 // 5 6 7 8 9 10 11
2621 // 12 13 14 15 16 17 18
2622 // 19 20 21 22 23 24 25
2623 // 26 27 28 29 30 31
2624 for (int32_t pass=0; pass<2; ++pass) {
2625 if (pass==0) {
2626 cal.setFirstDayOfWeek(UCAL_WEDNESDAY);
2627 cal.setMinimalDaysInFirstWeek(4);
2628 } else {
2629 cal.setFirstDayOfWeek(UCAL_SUNDAY);
2630 cal.setMinimalDaysInFirstWeek(4);
2631 }
2632 cal.add(UCAL_DATE, 1, ec); // Force recalc
2633 cal.add(UCAL_DATE, -1, ec);
2634
2635 UDate time1 = cal.getTime(ec); // Get time -- should not change
2636
2637 // Now change a week parameter and then force a recalc.
2638 // The bug is that the recalc should not be necessary --
2639 // calendar should do so automatically.
2640 if (pass==0) {
2641 cal.setFirstDayOfWeek(UCAL_THURSDAY);
2642 } else {
2643 cal.setMinimalDaysInFirstWeek(5);
2644 }
2645
2646 int32_t woy1 = cal.get(UCAL_WEEK_OF_YEAR, ec);
2647 int32_t wom1 = cal.get(UCAL_WEEK_OF_MONTH, ec);
2648
2649 cal.add(UCAL_DATE, 1, ec); // Force recalc
2650 cal.add(UCAL_DATE, -1, ec);
2651
2652 int32_t woy2 = cal.get(UCAL_WEEK_OF_YEAR, ec);
2653 int32_t wom2 = cal.get(UCAL_WEEK_OF_MONTH, ec);
2654
2655 UDate time2 = cal.getTime(ec);
2656
2657 if (U_FAILURE(ec)) {
2658 errln("FAIL: internal test error");
2659 return;
2660 }
2661
2662 if (time1 != time2) {
2663 errln("FAIL: shifting week should not alter time");
2664 } else {
2665 // logln(time1);
2666 }
2667 if (woy1 == woy2 && wom1 == wom2) {
2668 logln((UnicodeString)"Ok: WEEK_OF_YEAR: " + woy1 +
2669 ", WEEK_OF_MONTH: " + wom1);
2670 } else {
2671 errln((UnicodeString)"FAIL: WEEK_OF_YEAR: " + woy1 + " => " + woy2 +
2672 ", WEEK_OF_MONTH: " + wom1 + " => " + wom2 +
2673 " after week shift");
2674 }
2675 }
2676 }
2677
2678 /**
2679 * Make sure that when adding a day, we actually wind up in a
2680 * different day. The DST adjustments we use to keep the hour
2681 * constant across DST changes can backfire and change the day.
2682 */
TestTimeZoneTransitionAdd()2683 void CalendarRegressionTest::TestTimeZoneTransitionAdd() {
2684 UErrorCode ec = U_ZERO_ERROR;
2685 Locale locale(Locale::getUS()); // could also be CHINA
2686 SimpleDateFormat dateFormat("MM/dd/yyyy HH:mm z", locale, ec);
2687 if (U_FAILURE(ec)) {
2688 dataerrln("FAIL: Constructing SimpleDateFormat");
2689 return;
2690 }
2691
2692 StringEnumeration *tz = TimeZone::createEnumeration(ec);
2693 if (U_FAILURE(ec)) {
2694 dataerrln("FAIL: TimeZone::createEnumeration");
2695 return;
2696 }
2697
2698 UnicodeString buf1, buf2;
2699
2700 const UChar* id;
2701 while ((id = tz->unext(NULL, ec)) != NULL && U_SUCCESS(ec)) {
2702 if (U_FAILURE(ec)) {
2703 errln("FAIL: StringEnumeration::unext");
2704 break;
2705 }
2706
2707 TimeZone *t = TimeZone::createTimeZone(id);
2708 if (t == NULL) {
2709 errln("FAIL: TimeZone::createTimeZone");
2710 break;
2711 }
2712 dateFormat.setTimeZone(*t);
2713
2714 Calendar *cal = Calendar::createInstance(t, locale, ec);
2715 if (cal == NULL || U_FAILURE(ec)) {
2716 errln("FAIL: Calendar::createTimeZone");
2717 delete cal;
2718 break;
2719 }
2720
2721 cal->clear();
2722 // Scan the year 2003, overlapping the edges of the year
2723 cal->set(UCAL_YEAR, 2002);
2724 cal->set(UCAL_MONTH, UCAL_DECEMBER);
2725 cal->set(UCAL_DATE, 25);
2726
2727 for (int32_t i=0; i<365+10 && U_SUCCESS(ec); ++i) {
2728 UDate yesterday = cal->getTime(ec);
2729 int32_t yesterday_day = cal->get(UCAL_DATE, ec);
2730 cal->add(UCAL_DATE, 1, ec);
2731 if (yesterday_day == cal->get(UCAL_DATE, ec)) {
2732 errln(UnicodeString(id) + " " +
2733 dateFormat.format(yesterday, buf1) + " +1d= " +
2734 dateFormat.format(cal->getTime(ec), buf2));
2735 buf1.truncate(0);
2736 buf2.truncate(0);
2737 }
2738 }
2739 delete cal;
2740 }
2741
2742 if (U_FAILURE(ec)) {
2743 dataerrln("FAIL: %s", u_errorName(ec));
2744 }
2745
2746 delete tz;
2747 }
2748
2749 UDate
makeDate(int32_t y,int32_t m,int32_t d,int32_t hr,int32_t min,int32_t sec)2750 CalendarRegressionTest::makeDate(int32_t y, int32_t m, int32_t d,
2751 int32_t hr, int32_t min, int32_t sec)
2752 {
2753 UDate result;
2754
2755 UErrorCode status = U_ZERO_ERROR;
2756 Calendar *cal = Calendar::createInstance(status);
2757 cal->clear();
2758
2759 cal->set(UCAL_YEAR, y);
2760
2761 if(m != 0) cal->set(UCAL_MONTH, m);
2762 if(d != 0) cal->set(UCAL_DATE, d);
2763 if(hr != 0) cal->set(UCAL_HOUR, hr);
2764 if(min != 0) cal->set(UCAL_MINUTE, min);
2765 if(sec != 0) cal->set(UCAL_SECOND, sec);
2766
2767 result = cal->getTime(status);
2768
2769 delete cal;
2770
2771 return result;
2772 }
2773
TestDeprecates(void)2774 void CalendarRegressionTest::TestDeprecates(void)
2775 {
2776 UErrorCode status = U_ZERO_ERROR;
2777 Calendar *c1 = Calendar::createInstance("ja_JP@calendar=japanese",status);
2778 Calendar *c2 = Calendar::createInstance("ja_JP@calendar=japanese",status);
2779
2780 if(!c1 || !c2 || U_FAILURE(status)) {
2781 dataerrln("Couldn't create calendars for roll of HOUR: %s", u_errorName(status));
2782 return;
2783 }
2784
2785 c2->set(UCAL_HOUR,2);
2786 c1->setTime(c2->getTime(status),status);
2787 // *c1 = *c2;
2788
2789 c1->roll(Calendar::HOUR,(int32_t)3,status);
2790 c2->roll(UCAL_HOUR,(int32_t)3,status);
2791
2792 if(U_FAILURE(status)) {
2793 errln("Error code when trying to roll");
2794 } else if(*c1 != *c2) {
2795 errln("roll(EDateField, int32_t) had different effect than roll(UCalendarField, int32_t)");
2796 }
2797
2798 c1->setTime(c2->getTime(status),status);
2799 c1->roll(Calendar::HOUR,(UBool)false,status);
2800 c2->roll(UCAL_HOUR,(UBool)false,status);
2801
2802 if(U_FAILURE(status)) {
2803 errln("Error code when trying to roll(UBool)");
2804 } else if(*c1 != *c2) {
2805 errln("roll(EDateField, UBool) had different effect than roll(UCalendarField, UBool)");
2806 }
2807
2808 delete c1;
2809 delete c2;
2810
2811 status = U_ZERO_ERROR;
2812
2813 c1 = Calendar::createInstance("th_TH@calendar=buddhist",status);
2814 c2 = Calendar::createInstance("th_TH@calendar=buddhist",status);
2815
2816 if(!c1 || !c2 || U_FAILURE(status)) {
2817 errln("Couldn't create calendars for add of HOUR");
2818 return;
2819 }
2820
2821 c2->set(UCAL_HOUR,2);
2822 c1->setTime(c2->getTime(status),status);
2823 //*c1 = *c2;
2824
2825 c1->add(Calendar::HOUR,(int32_t)1,status);
2826
2827 if(U_FAILURE(status)) {
2828 errln("Error code when trying to add Calendar::HOUR - %s", u_errorName(status));
2829 }
2830
2831 c2->add(UCAL_HOUR,(int32_t)1,status);
2832
2833 if(U_FAILURE(status)) {
2834 errln("Error code when trying to add - UCAL_HOUR %s", u_errorName(status));
2835 } else if(*c1 != *c2) {
2836 errln("add(EDateField) had different effect than add(UCalendarField)");
2837 }
2838
2839 delete c1;
2840 delete c2;
2841
2842 status = U_ZERO_ERROR;
2843
2844 c1 = Calendar::createInstance("es_ES",status);
2845 c2 = Calendar::createInstance("es_ES",status);
2846
2847 if(!c1 || !c2 || U_FAILURE(status)) {
2848 errln("Couldn't create calendars for add of YEAR");
2849 return;
2850 }
2851
2852 c2->set(UCAL_YEAR,1900);
2853 c1->setTime(c2->getTime(status),status);
2854 //*c1 = *c2;
2855
2856 c1->add(Calendar::YEAR,(int32_t)9,status);
2857 c2->add(UCAL_YEAR,(int32_t)9,status);
2858
2859 if(U_FAILURE(status)) {
2860 errln("Error code when trying to add YEARs");
2861 } else if(*c1 != *c2) {
2862 errln("add(EDateField YEAR) had different effect than add(UCalendarField YEAR)");
2863 }
2864
2865 delete c1;
2866 delete c2;
2867
2868 }
2869
TestT8057(void)2870 void CalendarRegressionTest::TestT8057(void) {
2871 // Set the calendar to the last day in a leap year
2872 UErrorCode status = U_ZERO_ERROR;
2873 GregorianCalendar *cal = (GregorianCalendar*)Calendar::createInstance(status);
2874 if(U_FAILURE(status)) {
2875 errln("Error creating Calendar: %s", u_errorName(status));
2876 delete cal;
2877 return;
2878 }
2879 cal->setLenient(false);
2880 cal->clear();
2881 cal->set(2008, UCAL_DECEMBER, 31);
2882
2883 // Force calculating then fields once.
2884 UDate t = cal->getTime(status);
2885 if(U_FAILURE(status)) {
2886 errln("Error while calculating the date");
2887 delete cal;
2888 return;
2889 }
2890
2891 UDate expected = 1262246400000.0; // 2009-12-31 00:00 PST
2892
2893 cal->add(UCAL_YEAR, 1, status);
2894 t = cal->getTime(status);
2895 if (U_SUCCESS(status)) {
2896 if (t != expected) {
2897 dataerrln((UnicodeString)"FAIL: wrong date after add: expected=" + expected + " returned=" + t);
2898 }
2899 } else {
2900 errln("FAIL: error while adding one year");
2901 }
2902
2903 delete cal;
2904 }
2905
2906 // Test case for ticket#8596.
2907 // Setting an year followed by getActualMaximum(Calendar.WEEK_OF_YEAR)
2908 // may result wrong maximum week.
TestT8596(void)2909 void CalendarRegressionTest::TestT8596(void) {
2910 UErrorCode status = U_ZERO_ERROR;
2911 GregorianCalendar *gc = new GregorianCalendar(*TimeZone::getGMT(), status);
2912
2913 if (U_FAILURE(status)) {
2914 dataerrln("Error creating Calendar: %s", u_errorName(status));
2915 delete gc;
2916 return;
2917 }
2918
2919 gc->setFirstDayOfWeek(UCAL_MONDAY);
2920 gc->setMinimalDaysInFirstWeek(4);
2921
2922 // Force the calendar to resolve the fields once.
2923 // The maximum week number in 2011 is 52.
2924 gc->set(UCAL_YEAR, 2011);
2925 gc->get(UCAL_YEAR, status);
2926
2927 // Set a date in year 2009, but not calling get to resolve
2928 // the calendar's internal field yet.
2929 gc->set(2009, UCAL_JULY, 1);
2930
2931 // Then call getActuamMaximum for week of year.
2932 // #8596 was caused by conflict between year set
2933 // above and internal work calendar field resolution.
2934 int32_t maxWeeks = gc->getActualMaximum(UCAL_WEEK_OF_YEAR, status);
2935
2936 if (U_FAILURE(status)) {
2937 errln("Error calendar calculation: %s", u_errorName(status));
2938 delete gc;
2939 return;
2940 }
2941
2942 if (maxWeeks != 53) {
2943 errln((UnicodeString)"FAIL: Max week in 2009 in ISO calendar is 53, but got " + maxWeeks);
2944 }
2945
2946 delete gc;
2947 }
2948
2949 // Test case for ticket 9452
2950 // Calendar addition fall onto the missing date - 2011-12-30 in Samoa
TestT9452(void)2951 void CalendarRegressionTest::TestT9452(void) {
2952 UErrorCode status = U_ZERO_ERROR;
2953 GregorianCalendar cal(TimeZone::createTimeZone("Pacific/Apia"), status);
2954 failure(status, "initializing GregorianCalendar");
2955
2956 SimpleDateFormat sdf(UnicodeString("y-MM-dd'T'HH:mm:ssZZZZZ"), status);
2957 failure(status, "initializing SimpleDateFormat");
2958 sdf.setCalendar(cal);
2959
2960 UnicodeString dstr;
2961
2962 // Set date to 2011-12-29 00:00
2963 cal.clear();
2964 cal.set(2011, UCAL_DECEMBER, 29, 0, 0, 0);
2965
2966 UDate d = cal.getTime(status);
2967 if (!failure(status, "getTime for initial date")) {
2968 sdf.format(d, dstr);
2969 logln(UnicodeString("Initial date: ") + dstr);
2970
2971 // Add 1 day
2972 cal.add(UCAL_DATE, 1, status);
2973 failure(status, "add 1 day");
2974 d = cal.getTime(status);
2975 failure(status, "getTime after +1 day");
2976 dstr.remove();
2977 sdf.format(d, dstr);
2978 logln(UnicodeString("+1 day: ") + dstr);
2979 assertEquals("Add 1 day", UnicodeString("2011-12-31T00:00:00+14:00"), dstr);
2980
2981 // Subtract 1 day
2982 cal.add(UCAL_DATE, -1, status);
2983 failure(status, "subtract 1 day");
2984 d = cal.getTime(status);
2985 failure(status, "getTime after -1 day");
2986 dstr.remove();
2987 sdf.format(d, dstr);
2988 logln(UnicodeString("-1 day: ") + dstr);
2989 assertEquals("Subtract 1 day", UnicodeString("2011-12-29T00:00:00-10:00"), dstr);
2990 }
2991 }
2992
2993 /**
2994 * @bug ticket 11632
2995 */
TestT11632(void)2996 void CalendarRegressionTest::TestT11632(void) {
2997 UErrorCode status = U_ZERO_ERROR;
2998 GregorianCalendar cal(TimeZone::createTimeZone("Pacific/Apia"), status);
2999 if(U_FAILURE(status)) {
3000 dataerrln("Error creating Calendar: %s", u_errorName(status));
3001 return;
3002 }
3003 failure(status, "Calendar::createInstance(status)");
3004 cal.clear();
3005 failure(status, "clear calendar");
3006 cal.set(UCAL_HOUR, 597);
3007 failure(status, "set hour value in calendar");
3008 SimpleDateFormat sdf(UnicodeString("y-MM-dd'T'HH:mm:ss"), status);
3009 failure(status, "initializing SimpleDateFormat");
3010 sdf.setCalendar(cal);
3011 UnicodeString dstr;
3012 UDate d = cal.getTime(status);
3013 if (!failure(status, "getTime for date")) {
3014 sdf.format(d, dstr);
3015 std::string utf8;
3016 dstr.toUTF8String(utf8);
3017 assertEquals("correct datetime displayed for hour value", UnicodeString("1970-01-25T21:00:00"), dstr);
3018 cal.clear();
3019 failure(status, "clear calendar");
3020 cal.set(UCAL_HOUR, 300);
3021 failure(status, "set hour value in calendar");
3022 sdf.setCalendar(cal);
3023 d = cal.getTime(status);
3024 if (!failure(status, "getTime for initial date")) {
3025 dstr.remove();
3026 sdf.format(d, dstr);
3027 dstr.toUTF8String(utf8);
3028 assertEquals("correct datetime displayed for hour value", UnicodeString("1970-01-13T12:00:00"), dstr);
3029 }
3030 }
3031 }
3032
3033 /**
3034 * @bug ticket 13454
3035 */
TestPersianCalOverflow(void)3036 void CalendarRegressionTest::TestPersianCalOverflow(void) {
3037 const char* localeID = "bs_Cyrl@calendar=persian";
3038 UErrorCode status = U_ZERO_ERROR;
3039 Calendar* cal = Calendar::createInstance(Locale(localeID), status);
3040 if(U_FAILURE(status)) {
3041 dataerrln("FAIL: Calendar::createInstance for localeID %s: %s", localeID, u_errorName(status));
3042 } else {
3043 int32_t maxMonth = cal->getMaximum(UCAL_MONTH);
3044 int32_t maxDayOfMonth = cal->getMaximum(UCAL_DATE);
3045 int32_t jd, month, dayOfMonth;
3046 for (jd = 67023580; jd <= 67023584; jd++) { // year 178171, int32_t overflow if jd >= 67023582
3047 status = U_ZERO_ERROR;
3048 cal->clear();
3049 cal->set(UCAL_JULIAN_DAY, jd);
3050 month = cal->get(UCAL_MONTH, status);
3051 dayOfMonth = cal->get(UCAL_DATE, status);
3052 if ( U_FAILURE(status) ) {
3053 errln("FAIL: Calendar->get MONTH/DATE for localeID %s, julianDay %d, status %s", localeID, jd, u_errorName(status));
3054 } else if (month > maxMonth || dayOfMonth > maxDayOfMonth) {
3055 errln("FAIL: localeID %s, julianDay %d; maxMonth %d, got month %d; maxDayOfMonth %d, got dayOfMonth %d",
3056 localeID, jd, maxMonth, month, maxDayOfMonth, dayOfMonth);
3057 }
3058 }
3059 delete cal;
3060 }
3061 }
3062
3063 /**
3064 * @bug tickets 12661, 13538
3065 */
TestIslamicCalOverflow(void)3066 void CalendarRegressionTest::TestIslamicCalOverflow(void) {
3067 const char* localeID = "ar@calendar=islamic-civil";
3068 UErrorCode status = U_ZERO_ERROR;
3069 Calendar* cal = Calendar::createInstance(Locale(localeID), status);
3070 if(U_FAILURE(status)) {
3071 dataerrln("FAIL: Calendar::createInstance for localeID %s: %s", localeID, u_errorName(status));
3072 } else {
3073 int32_t maxMonth = cal->getMaximum(UCAL_MONTH);
3074 int32_t maxDayOfMonth = cal->getMaximum(UCAL_DATE);
3075 int32_t jd, year, month, dayOfMonth;
3076 for (jd = 73530872; jd <= 73530876; jd++) { // year 202002, int32_t overflow if jd >= 73530874
3077 status = U_ZERO_ERROR;
3078 cal->clear();
3079 cal->set(UCAL_JULIAN_DAY, jd);
3080 year = cal->get(UCAL_YEAR, status);
3081 month = cal->get(UCAL_MONTH, status);
3082 dayOfMonth = cal->get(UCAL_DATE, status);
3083 if ( U_FAILURE(status) ) {
3084 errln("FAIL: Calendar->get YEAR/MONTH/DATE for localeID %s, julianDay %d, status %s", localeID, jd, u_errorName(status));
3085 } else if (month > maxMonth || dayOfMonth > maxDayOfMonth) {
3086 errln("FAIL: localeID %s, julianDay %d; got year %d; maxMonth %d, got month %d; maxDayOfMonth %d, got dayOfMonth %d",
3087 localeID, jd, year, maxMonth, month, maxDayOfMonth, dayOfMonth);
3088 }
3089 }
3090 delete cal;
3091 }
3092 }
3093
VerifyGetStayInBound(double time)3094 void CalendarRegressionTest::VerifyGetStayInBound(double time) {
3095 UErrorCode status = U_ZERO_ERROR;
3096 LocalPointer<Calendar> utc(
3097 Calendar::createInstance(TimeZone::createTimeZone(u"UTC"), status));
3098 utc->setTime(time, status);
3099 if (U_FAILURE(status)) {
3100 errln("UTC setTime(%e, status)", time);
3101 }
3102
3103 status = U_ZERO_ERROR;
3104 LocalPointer<Calendar> gmt(Calendar::createInstance(
3105 *TimeZone::getGMT(), status));
3106 gmt->setTime(time, status);
3107 if (U_FAILURE(status)) {
3108 errln("UTC setTime(%e, status)", time);
3109 }
3110
3111 status = U_ZERO_ERROR;
3112 int32_t value = utc->get(UCAL_AM_PM, status);
3113 if (U_FAILURE(status)) {
3114 errln("UTC %e get(UCAL_AM_PM, status)", time);
3115 }
3116 if (value != UCAL_AM && value != UCAL_PM) {
3117 errln("UTC %e UCAL_AM_PM should be either UCAL_AM | UCAL_PM but is %d",
3118 time, value);
3119 }
3120
3121 status = U_ZERO_ERROR;
3122 value = gmt->get(UCAL_AM_PM, status);
3123 if (U_FAILURE(status)) {
3124 errln("GMT %e get(UCAL_AM_PM, status)", time);
3125 }
3126 if (value != UCAL_AM && value != UCAL_PM) {
3127 errln("GMT %e UCAL_AM_PM should be either UCAL_AM | UCAL_PM but is %d",
3128 time, value);
3129 }
3130
3131 int32_t fields[] = {
3132 UCAL_WEEK_OF_YEAR,
3133 UCAL_YEAR_WOY,
3134 UCAL_DAY_OF_MONTH,
3135 UCAL_WEEK_OF_MONTH,
3136 UCAL_DAY_OF_WEEK_IN_MONTH,
3137 UCAL_MILLISECONDS_IN_DAY,
3138 UCAL_MILLISECOND,
3139 UCAL_SECOND,
3140 UCAL_MINUTE,
3141 UCAL_HOUR_OF_DAY,
3142 UCAL_AM_PM,
3143 UCAL_HOUR,
3144 UCAL_ZONE_OFFSET,
3145 UCAL_DST_OFFSET
3146 };
3147 for (auto& f : fields) {
3148 UnicodeString info("Fields = ");
3149 info += f;
3150 status = U_ZERO_ERROR;
3151 UCalendarDateFields field = static_cast<UCalendarDateFields>(f);
3152 value = utc->get(field, status);
3153 if (U_FAILURE(status)) {
3154 errln("UTC %e get(%d)", time, field);
3155 }
3156 int32_t min = utc->getMinimum(field);
3157 int32_t max = utc->getMaximum(field);
3158 if (value < min) {
3159 errln("UTC %e get(%d) < getMinimum(%d) : %d < %d", time, field,
3160 field, value, min);
3161 }
3162 if (max < value) {
3163 errln("UTC %e getMaximum(%d) < get(%d) : %d < %d", time, field,
3164 field, max, value);
3165 }
3166
3167 status = U_ZERO_ERROR;
3168 value = gmt->get(field, status);
3169 if (U_FAILURE(status)) {
3170 errln("GMT %e get(%d)", time, field);
3171 }
3172 min = gmt->getMinimum(field);
3173 max = gmt->getMaximum(field);
3174 if (value < min) {
3175 errln("GMT %e get(%d) < getMinimum(%d) : %d < %d", time, field,
3176 field, value, min);
3177 }
3178 if (max < value) {
3179 errln("GMT %e getMaximum(%d) < get(%d) : %d < %d", time, field,
3180 field, max, value);
3181 }
3182 }
3183 }
3184
TestUTCWrongAMPM22023(void)3185 void CalendarRegressionTest::TestUTCWrongAMPM22023(void) {
3186 VerifyGetStayInBound(-1);
3187 VerifyGetStayInBound(0);
3188 VerifyGetStayInBound(-1e-8);
3189 VerifyGetStayInBound(-1e-9);
3190 VerifyGetStayInBound(-1e-15);
3191 }
3192
VerifyNoAssertWithSetGregorianChange(const char * timezone)3193 void CalendarRegressionTest::VerifyNoAssertWithSetGregorianChange(const char* timezone) {
3194 UErrorCode status = U_ZERO_ERROR;
3195 std::unique_ptr<Calendar> cal(
3196 Calendar::createInstance(
3197 TimeZone::createTimeZone(UnicodeString(timezone, -1, US_INV)),
3198 Locale::getEnglish(),
3199 status));
3200 cal->setTime(Calendar::getNow(), status);
3201
3202 if (cal->getDynamicClassID() ==
3203 GregorianCalendar::getStaticClassID()) {
3204 GregorianCalendar* gc =
3205 static_cast<GregorianCalendar*>(cal.get());
3206 // The beginning of ECMAScript time, namely -(2**53)
3207 const double start_of_time = -9007199254740992;
3208 gc->setGregorianChange(start_of_time, status);
3209 }
3210 cal->get(UCAL_YEAR, status);
3211 }
3212
TestAsiaManilaAfterSetGregorianChange22043(void)3213 void CalendarRegressionTest::TestAsiaManilaAfterSetGregorianChange22043(void) {
3214 VerifyNoAssertWithSetGregorianChange("Asia/Malina");
3215 UErrorCode status = U_ZERO_ERROR;
3216 std::unique_ptr<StringEnumeration> ids(TimeZone::createEnumeration(status));
3217 if (U_FAILURE(status)) {
3218 errln("TimeZone::createEnumeration failed");
3219 return;
3220 }
3221 const char* id;
3222 while ((id = ids->next(nullptr, status)) != nullptr && U_SUCCESS(status)) {
3223 VerifyNoAssertWithSetGregorianChange(id);
3224 }
3225 }
3226
TestWeekOfYear13548(void)3227 void CalendarRegressionTest::TestWeekOfYear13548(void) {
3228 int32_t year = 2000;
3229 UErrorCode status = U_ZERO_ERROR;
3230 LocalPointer<Calendar> cal(Calendar::createInstance(status));
3231 failure(status, "Calendar::createInstance(status)");
3232
3233 cal->set(UCAL_YEAR, year);
3234 cal->set(UCAL_WEEK_OF_YEAR, 4);
3235
3236 int32_t resultYear = cal->get(UCAL_YEAR, status);
3237 failure(status, "get(UCAL_YEAR, status)");
3238 if (year != resultYear) {
3239 errln((UnicodeString)"Fail: Expected year=" + year + ", actual=" + resultYear);
3240 }
3241 }
3242
3243 #endif /* #if !UCONFIG_NO_FORMATTING */
3244