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