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