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