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