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