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