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