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