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