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