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