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 #include "unicode/utypes.h"
      9 
     10 #if !UCONFIG_NO_FORMATTING
     11 
     12 #include "caltest.h"
     13 #include "unicode/dtfmtsym.h"
     14 #include "unicode/gregocal.h"
     15 #include "unicode/localpointer.h"
     16 #include "hebrwcal.h"
     17 #include "unicode/smpdtfmt.h"
     18 #include "unicode/simpletz.h"
     19 #include "dbgutil.h"
     20 #include "unicode/udat.h"
     21 #include "unicode/ustring.h"
     22 #include "cstring.h"
     23 #include "unicode/localpointer.h"
     24 #include "islamcal.h"
     25 
     26 #define mkcstr(U) u_austrcpy(calloc(8, u_strlen(U) + 1), U)
     27 
     28 #define TEST_CHECK_STATUS { \
     29     if (U_FAILURE(status)) { \
     30         if (status == U_MISSING_RESOURCE_ERROR) { \
     31             dataerrln("%s:%d: Test failure.  status=%s", __FILE__, __LINE__, u_errorName(status)); \
     32         } else { \
     33             errln("%s:%d: Test failure.  status=%s", __FILE__, __LINE__, u_errorName(status)); \
     34         } return;}}
     35 
     36 #define TEST_CHECK_STATUS_LOCALE(testlocale) { \
     37     if (U_FAILURE(status)) { \
     38         if (status == U_MISSING_RESOURCE_ERROR) { \
     39             dataerrln("%s:%d: Test failure, locale %s.  status=%s", __FILE__, __LINE__, testlocale, u_errorName(status)); \
     40         } else { \
     41             errln("%s:%d: Test failure, locale %s.  status=%s", __FILE__, __LINE__, testlocale, u_errorName(status)); \
     42         } return;}}
     43 
     44 #define TEST_ASSERT(expr) {if ((expr)==FALSE) {errln("%s:%d: Test failure \n", __FILE__, __LINE__);};}
     45 
     46 // *****************************************************************************
     47 // class CalendarTest
     48 // *****************************************************************************
     49 
     50 UnicodeString CalendarTest::calToStr(const Calendar & cal)
     51 {
     52   UnicodeString out;
     53   UErrorCode status = U_ZERO_ERROR;
     54   int i;
     55   UDate d;
     56   for(i = 0;i<UCAL_FIELD_COUNT;i++) {
     57     out += (UnicodeString("") + fieldName((UCalendarDateFields)i) + "=" +  cal.get((UCalendarDateFields)i, status) + UnicodeString(" "));
     58   }
     59   out += "[" + UnicodeString(cal.getType()) + "]";
     60 
     61   if(cal.inDaylightTime(status)) {
     62     out += UnicodeString(" (in DST), zone=");
     63   }
     64   else {
     65     out += UnicodeString(", zone=");
     66   }
     67 
     68   UnicodeString str2;
     69   out += cal.getTimeZone().getDisplayName(str2);
     70   d = cal.getTime(status);
     71   out += UnicodeString(" :","") + d;
     72 
     73   return out;
     74 }
     75 
     76 void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
     77 {
     78     if (exec) logln("TestSuite TestCalendar");
     79     switch (index) {
     80         case 0:
     81             name = "TestDOW943";
     82             if (exec) {
     83                 logln("TestDOW943---"); logln("");
     84                 TestDOW943();
     85             }
     86             break;
     87         case 1:
     88             name = "TestClonesUnique908";
     89             if (exec) {
     90                 logln("TestClonesUnique908---"); logln("");
     91                 TestClonesUnique908();
     92             }
     93             break;
     94         case 2:
     95             name = "TestGregorianChange768";
     96             if (exec) {
     97                 logln("TestGregorianChange768---"); logln("");
     98                 TestGregorianChange768();
     99             }
    100             break;
    101         case 3:
    102             name = "TestDisambiguation765";
    103             if (exec) {
    104                 logln("TestDisambiguation765---"); logln("");
    105                 TestDisambiguation765();
    106             }
    107             break;
    108         case 4:
    109             name = "TestGMTvsLocal4064654";
    110             if (exec) {
    111                 logln("TestGMTvsLocal4064654---"); logln("");
    112                 TestGMTvsLocal4064654();
    113             }
    114             break;
    115         case 5:
    116             name = "TestAddSetOrder621";
    117             if (exec) {
    118                 logln("TestAddSetOrder621---"); logln("");
    119                 TestAddSetOrder621();
    120             }
    121             break;
    122         case 6:
    123             name = "TestAdd520";
    124             if (exec) {
    125                 logln("TestAdd520---"); logln("");
    126                 TestAdd520();
    127             }
    128             break;
    129         case 7:
    130             name = "TestFieldSet4781";
    131             if (exec) {
    132                 logln("TestFieldSet4781---"); logln("");
    133                 TestFieldSet4781();
    134             }
    135             break;
    136         case 8:
    137             name = "TestSerialize337";
    138             if (exec) {
    139                 logln("TestSerialize337---"); logln("");
    140             //  TestSerialize337();
    141             }
    142             break;
    143         case 9:
    144             name = "TestSecondsZero121";
    145             if (exec) {
    146                 logln("TestSecondsZero121---"); logln("");
    147                 TestSecondsZero121();
    148             }
    149             break;
    150         case 10:
    151             name = "TestAddSetGet0610";
    152             if (exec) {
    153                 logln("TestAddSetGet0610---"); logln("");
    154                 TestAddSetGet0610();
    155             }
    156             break;
    157         case 11:
    158             name = "TestFields060";
    159             if (exec) {
    160                 logln("TestFields060---"); logln("");
    161                 TestFields060();
    162             }
    163             break;
    164         case 12:
    165             name = "TestEpochStartFields";
    166             if (exec) {
    167                 logln("TestEpochStartFields---"); logln("");
    168                 TestEpochStartFields();
    169             }
    170             break;
    171         case 13:
    172             name = "TestDOWProgression";
    173             if (exec) {
    174                 logln("TestDOWProgression---"); logln("");
    175                 TestDOWProgression();
    176             }
    177             break;
    178         case 14:
    179             name = "TestGenericAPI";
    180             if (exec) {
    181                 logln("TestGenericAPI---"); logln("");
    182                 TestGenericAPI();
    183             }
    184             break;
    185         case 15:
    186             name = "TestAddRollExtensive";
    187             if (exec) {
    188                 logln("TestAddRollExtensive---"); logln("");
    189                 TestAddRollExtensive();
    190             }
    191             break;
    192         case 16:
    193             name = "TestDOW_LOCALandYEAR_WOY";
    194             if (exec) {
    195                 logln("TestDOW_LOCALandYEAR_WOY---"); logln("");
    196                 TestDOW_LOCALandYEAR_WOY();
    197             }
    198             break;
    199         case 17:
    200             name = "TestWOY";
    201             if (exec) {
    202                 logln("TestWOY---"); logln("");
    203                 TestWOY();
    204             }
    205             break;
    206         case 18:
    207             name = "TestRog";
    208             if (exec) {
    209                 logln("TestRog---"); logln("");
    210                 TestRog();
    211             }
    212             break;
    213         case 19:
    214            name = "TestYWOY";
    215             if (exec) {
    216                 logln("TestYWOY---"); logln("");
    217                 TestYWOY();
    218             }
    219             break;
    220         case 20:
    221           name = "TestJD";
    222           if(exec) {
    223             logln("TestJD---"); logln("");
    224             TestJD();
    225           }
    226           break;
    227         case 21:
    228           name = "TestDebug";
    229           if(exec) {
    230             logln("TestDebug---"); logln("");
    231             TestDebug();
    232           }
    233           break;
    234         case 22:
    235           name = "Test6703";
    236           if(exec) {
    237             logln("Test6703---"); logln("");
    238             Test6703();
    239           }
    240           break;
    241         case 23:
    242           name = "Test3785";
    243           if(exec) {
    244             logln("Test3785---"); logln("");
    245             Test3785();
    246           }
    247           break;
    248         case 24:
    249           name = "Test1624";
    250           if(exec) {
    251             logln("Test1624---"); logln("");
    252             Test1624();
    253           }
    254           break;
    255         case 25:
    256           name = "TestTimeStamp";
    257           if(exec) {
    258             logln("TestTimeStamp---"); logln("");
    259             TestTimeStamp();
    260           }
    261           break;
    262         case 26:
    263           name = "TestISO8601";
    264           if(exec) {
    265             logln("TestISO8601---"); logln("");
    266             TestISO8601();
    267           }
    268           break;
    269         case 27:
    270           name = "TestAmbiguousWallTimeAPIs";
    271           if(exec) {
    272             logln("TestAmbiguousWallTimeAPIs---"); logln("");
    273             TestAmbiguousWallTimeAPIs();
    274           }
    275           break;
    276         case 28:
    277           name = "TestRepeatedWallTime";
    278           if(exec) {
    279             logln("TestRepeatedWallTime---"); logln("");
    280             TestRepeatedWallTime();
    281           }
    282           break;
    283         case 29:
    284           name = "TestSkippedWallTime";
    285           if(exec) {
    286             logln("TestSkippedWallTime---"); logln("");
    287             TestSkippedWallTime();
    288           }
    289           break;
    290         case 30:
    291           name = "TestCloneLocale";
    292           if(exec) {
    293             logln("TestCloneLocale---"); logln("");
    294             TestCloneLocale();
    295           }
    296           break;
    297         case 31:
    298           name = "TestIslamicUmAlQura";
    299           if(exec) {
    300             logln("TestIslamicUmAlQura---"); logln("");
    301             TestIslamicUmAlQura();
    302           }
    303           break;
    304         case 32:
    305           name = "TestIslamicTabularDates";
    306           if(exec) {
    307             logln("TestIslamicTabularDates---"); logln("");
    308             TestIslamicTabularDates();
    309           }
    310           break;
    311         case 33:
    312           name = "TestHebrewMonthValidation";
    313           if(exec) {
    314             logln("TestHebrewMonthValidation---"); logln("");
    315             TestHebrewMonthValidation();
    316           }
    317           break;
    318         case 34:
    319           name = "TestWeekData";
    320           if(exec) {
    321             logln("TestWeekData---"); logln("");
    322             TestWeekData();
    323           }
    324           break;
    325         case 35:
    326           name = "TestAddAcrossZoneTransition";
    327           if(exec) {
    328             logln("TestAddAcrossZoneTransition---"); logln("");
    329             TestAddAcrossZoneTransition();
    330           }
    331           break;
    332         case 36:
    333           name = "TestChineseCalendarMapping";
    334           if(exec) {
    335             logln("TestChineseCalendarMapping---"); logln("");
    336             TestChineseCalendarMapping();
    337           }
    338           break;
    339         default: name = ""; break;
    340     }
    341 }
    342 
    343 // ---------------------------------------------------------------------------------
    344 
    345 UnicodeString CalendarTest::fieldName(UCalendarDateFields f) {
    346     switch (f) {
    347 #define FIELD_NAME_STR(x) case x: return (#x+5)
    348       FIELD_NAME_STR( UCAL_ERA );
    349       FIELD_NAME_STR( UCAL_YEAR );
    350       FIELD_NAME_STR( UCAL_MONTH );
    351       FIELD_NAME_STR( UCAL_WEEK_OF_YEAR );
    352       FIELD_NAME_STR( UCAL_WEEK_OF_MONTH );
    353       FIELD_NAME_STR( UCAL_DATE );
    354       FIELD_NAME_STR( UCAL_DAY_OF_YEAR );
    355       FIELD_NAME_STR( UCAL_DAY_OF_WEEK );
    356       FIELD_NAME_STR( UCAL_DAY_OF_WEEK_IN_MONTH );
    357       FIELD_NAME_STR( UCAL_AM_PM );
    358       FIELD_NAME_STR( UCAL_HOUR );
    359       FIELD_NAME_STR( UCAL_HOUR_OF_DAY );
    360       FIELD_NAME_STR( UCAL_MINUTE );
    361       FIELD_NAME_STR( UCAL_SECOND );
    362       FIELD_NAME_STR( UCAL_MILLISECOND );
    363       FIELD_NAME_STR( UCAL_ZONE_OFFSET );
    364       FIELD_NAME_STR( UCAL_DST_OFFSET );
    365       FIELD_NAME_STR( UCAL_YEAR_WOY );
    366       FIELD_NAME_STR( UCAL_DOW_LOCAL );
    367       FIELD_NAME_STR( UCAL_EXTENDED_YEAR );
    368       FIELD_NAME_STR( UCAL_JULIAN_DAY );
    369       FIELD_NAME_STR( UCAL_MILLISECONDS_IN_DAY );
    370 #undef FIELD_NAME_STR
    371     default:
    372         return UnicodeString("") + ((int32_t)f);
    373     }
    374 }
    375 
    376 /**
    377  * Test various API methods for API completeness.
    378  */
    379 void
    380 CalendarTest::TestGenericAPI()
    381 {
    382     UErrorCode status = U_ZERO_ERROR;
    383     UDate d;
    384     UnicodeString str;
    385     UBool eq = FALSE,b4 = FALSE,af = FALSE;
    386 
    387     UDate when = date(90, UCAL_APRIL, 15);
    388 
    389     UnicodeString tzid("TestZone");
    390     int32_t tzoffset = 123400;
    391 
    392     SimpleTimeZone *zone = new SimpleTimeZone(tzoffset, tzid);
    393     Calendar *cal = Calendar::createInstance(zone->clone(), status);
    394     if (failure(status, "Calendar::createInstance #1", TRUE)) return;
    395 
    396     if (*zone != cal->getTimeZone()) errln("FAIL: Calendar::getTimeZone failed");
    397 
    398     Calendar *cal2 = Calendar::createInstance(cal->getTimeZone(), status);
    399     if (failure(status, "Calendar::createInstance #2")) return;
    400     cal->setTime(when, status);
    401     cal2->setTime(when, status);
    402     if (failure(status, "Calendar::setTime")) return;
    403 
    404     if (!(*cal == *cal2)) errln("FAIL: Calendar::operator== failed");
    405     if ((*cal != *cal2))  errln("FAIL: Calendar::operator!= failed");
    406     if (!cal->equals(*cal2, status) ||
    407         cal->before(*cal2, status) ||
    408         cal->after(*cal2, status) ||
    409         U_FAILURE(status)) errln("FAIL: equals/before/after failed");
    410 
    411     logln(UnicodeString("cal=")  +cal->getTime(status)  + UnicodeString(calToStr(*cal)));
    412     logln(UnicodeString("cal2=")  +cal2->getTime(status)  + UnicodeString(calToStr(*cal2)));
    413     logln("cal2->setTime(when+1000)");
    414     cal2->setTime(when + 1000, status);
    415     logln(UnicodeString("cal2=")  +cal2->getTime(status)  + UnicodeString(calToStr(*cal2)));
    416 
    417     if (failure(status, "Calendar::setTime")) return;
    418     if (cal->equals(*cal2, status) ||
    419         cal2->before(*cal, status) ||
    420         cal->after(*cal2, status) ||
    421         U_FAILURE(status)) errln("FAIL: equals/before/after failed after setTime(+1000)");
    422 
    423     logln("cal->roll(UCAL_SECOND)");
    424     cal->roll(UCAL_SECOND, (UBool) TRUE, status);
    425     logln(UnicodeString("cal=")  +cal->getTime(status)  + UnicodeString(calToStr(*cal)));
    426     cal->roll(UCAL_SECOND, (int32_t)0, status);
    427     logln(UnicodeString("cal=")  +cal->getTime(status)  + UnicodeString(calToStr(*cal)));
    428     if (failure(status, "Calendar::roll")) return;
    429 
    430     if (!(eq=cal->equals(*cal2, status)) ||
    431         (b4=cal->before(*cal2, status)) ||
    432         (af=cal->after(*cal2, status)) ||
    433         U_FAILURE(status)) {
    434       errln("FAIL: equals[%c]/before[%c]/after[%c] failed after roll 1 second [should be T/F/F]",
    435             eq?'T':'F',
    436             b4?'T':'F',
    437             af?'T':'F');
    438       logln(UnicodeString("cal=")  +cal->getTime(status)  + UnicodeString(calToStr(*cal)));
    439       logln(UnicodeString("cal2=")  +cal2->getTime(status)  + UnicodeString(calToStr(*cal2)));
    440     }
    441 
    442     // Roll back to January
    443     cal->roll(UCAL_MONTH, (int32_t)(1 + UCAL_DECEMBER - cal->get(UCAL_MONTH, status)), status);
    444     if (failure(status, "Calendar::roll")) return;
    445     if (cal->equals(*cal2, status) ||
    446         cal2->before(*cal, status) ||
    447         cal->after(*cal2, status) ||
    448         U_FAILURE(status)) errln("FAIL: equals/before/after failed after rollback to January");
    449 
    450     TimeZone *z = cal->orphanTimeZone();
    451     if (z->getID(str) != tzid ||
    452         z->getRawOffset() != tzoffset)
    453         errln("FAIL: orphanTimeZone failed");
    454 
    455     int32_t i;
    456     for (i=0; i<2; ++i)
    457     {
    458         UBool lenient = ( i > 0 );
    459         cal->setLenient(lenient);
    460         if (lenient != cal->isLenient()) errln("FAIL: setLenient/isLenient failed");
    461         // Later: Check for lenient behavior
    462     }
    463 
    464     for (i=UCAL_SUNDAY; i<=UCAL_SATURDAY; ++i)
    465     {
    466         cal->setFirstDayOfWeek((UCalendarDaysOfWeek)i);
    467         if (cal->getFirstDayOfWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
    468         UErrorCode aStatus = U_ZERO_ERROR;
    469         if (cal->getFirstDayOfWeek(aStatus) != i || U_FAILURE(aStatus)) errln("FAIL: getFirstDayOfWeek(status) failed");
    470     }
    471 
    472     for (i=1; i<=7; ++i)
    473     {
    474         cal->setMinimalDaysInFirstWeek((uint8_t)i);
    475         if (cal->getMinimalDaysInFirstWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
    476     }
    477 
    478     for (i=0; i<UCAL_FIELD_COUNT; ++i)
    479     {
    480         if (cal->getMinimum((UCalendarDateFields)i) > cal->getGreatestMinimum((UCalendarDateFields)i))
    481             errln(UnicodeString("FAIL: getMinimum larger than getGreatestMinimum for field ") + i);
    482         if (cal->getLeastMaximum((UCalendarDateFields)i) > cal->getMaximum((UCalendarDateFields)i))
    483             errln(UnicodeString("FAIL: getLeastMaximum larger than getMaximum for field ") + i);
    484         if (cal->getMinimum((UCalendarDateFields)i) >= cal->getMaximum((UCalendarDateFields)i))
    485             errln(UnicodeString("FAIL: getMinimum not less than getMaximum for field ") + i);
    486     }
    487 
    488     cal->adoptTimeZone(TimeZone::createDefault());
    489     cal->clear();
    490     cal->set(1984, 5, 24);
    491     if (cal->getTime(status) != date(84, 5, 24) || U_FAILURE(status))
    492         errln("FAIL: Calendar::set(3 args) failed");
    493 
    494     cal->clear();
    495     cal->set(1985, 3, 2, 11, 49);
    496     if (cal->getTime(status) != date(85, 3, 2, 11, 49) || U_FAILURE(status))
    497         errln("FAIL: Calendar::set(5 args) failed");
    498 
    499     cal->clear();
    500     cal->set(1995, 9, 12, 1, 39, 55);
    501     if (cal->getTime(status) != date(95, 9, 12, 1, 39, 55) || U_FAILURE(status))
    502         errln("FAIL: Calendar::set(6 args) failed");
    503 
    504     cal->getTime(status);
    505     if (failure(status, "Calendar::getTime")) return;
    506     for (i=0; i<UCAL_FIELD_COUNT; ++i)
    507     {
    508         switch(i) {
    509             case UCAL_YEAR: case UCAL_MONTH: case UCAL_DATE:
    510             case UCAL_HOUR_OF_DAY: case UCAL_MINUTE: case UCAL_SECOND:
    511             case UCAL_EXTENDED_YEAR:
    512               if (!cal->isSet((UCalendarDateFields)i)) errln("FAIL: Calendar::isSet F, should be T " + fieldName((UCalendarDateFields)i));
    513                 break;
    514             default:
    515               if (cal->isSet((UCalendarDateFields)i)) errln("FAIL: Calendar::isSet = T, should be F  " + fieldName((UCalendarDateFields)i));
    516         }
    517         cal->clear((UCalendarDateFields)i);
    518         if (cal->isSet((UCalendarDateFields)i)) errln("FAIL: Calendar::clear/isSet failed " + fieldName((UCalendarDateFields)i));
    519     }
    520 
    521     if(cal->getActualMinimum(Calendar::SECOND, status) != 0){
    522         errln("Calendar is suppose to return 0 for getActualMinimum");
    523     }
    524 
    525     Calendar *cal3 = Calendar::createInstance(status);
    526     cal3->roll(Calendar::SECOND, (int32_t)0, status);
    527     if (failure(status, "Calendar::roll(EDateFields, int32_t, UErrorCode)")) return;
    528 
    529     delete cal;
    530     delete cal2;
    531     delete cal3;
    532 
    533     int32_t count;
    534     const Locale* loc = Calendar::getAvailableLocales(count);
    535     if (count < 1 || loc == 0)
    536     {
    537         dataerrln("FAIL: getAvailableLocales failed");
    538     }
    539     else
    540     {
    541         for (i=0; i<count; ++i)
    542         {
    543             cal = Calendar::createInstance(loc[i], status);
    544             if (U_FAILURE(status)) {
    545                 errcheckln(status, UnicodeString("FAIL: Calendar::createInstance #3, locale ") +  loc[i].getName() + " , error " + u_errorName(status));
    546                 return;
    547             }
    548             delete cal;
    549         }
    550     }
    551 
    552     cal = Calendar::createInstance(TimeZone::createDefault(), Locale::getEnglish(), status);
    553     if (failure(status, "Calendar::createInstance #4")) return;
    554     delete cal;
    555 
    556     cal = Calendar::createInstance(*zone, Locale::getEnglish(), status);
    557     if (failure(status, "Calendar::createInstance #5")) return;
    558     delete cal;
    559 
    560     GregorianCalendar *gc = new GregorianCalendar(*zone, status);
    561     if (failure(status, "new GregorianCalendar")) return;
    562     delete gc;
    563 
    564     gc = new GregorianCalendar(Locale::getEnglish(), status);
    565     if (failure(status, "new GregorianCalendar")) return;
    566     delete gc;
    567 
    568     gc = new GregorianCalendar(Locale::getEnglish(), status);
    569     delete gc;
    570 
    571     gc = new GregorianCalendar(*zone, Locale::getEnglish(), status);
    572     if (failure(status, "new GregorianCalendar")) return;
    573     delete gc;
    574 
    575     gc = new GregorianCalendar(zone, status);
    576     if (failure(status, "new GregorianCalendar")) return;
    577     delete gc;
    578 
    579     gc = new GregorianCalendar(1998, 10, 14, 21, 43, status);
    580     if (gc->getTime(status) != (d =date(98, 10, 14, 21, 43) )|| U_FAILURE(status))
    581       errln("FAIL: new GregorianCalendar(ymdhm) failed with " + UnicodeString(u_errorName(status)) + ",  cal="  + gc->getTime(status)  + UnicodeString(calToStr(*gc)) + ", d=" + d);
    582     else
    583       logln(UnicodeString("GOOD: cal=")  +gc->getTime(status)  + UnicodeString(calToStr(*gc)) + ", d=" + d);
    584     delete gc;
    585 
    586     gc = new GregorianCalendar(1998, 10, 14, 21, 43, 55, status);
    587     if (gc->getTime(status) != (d=date(98, 10, 14, 21, 43, 55)) || U_FAILURE(status))
    588       errln("FAIL: new GregorianCalendar(ymdhms) failed with " + UnicodeString(u_errorName(status)));
    589 
    590     GregorianCalendar gc2(Locale::getEnglish(), status);
    591     if (failure(status, "new GregorianCalendar")) return;
    592     gc2 = *gc;
    593     if (gc2 != *gc || !(gc2 == *gc)) errln("FAIL: GregorianCalendar assignment/operator==/operator!= failed");
    594     delete gc;
    595     delete z;
    596 
    597     /* Code coverage for Calendar class. */
    598     cal = Calendar::createInstance(status);
    599     if (failure(status, "Calendar::createInstance #6")) {
    600         return;
    601     }else {
    602         ((Calendar *)cal)->roll(UCAL_HOUR, (int32_t)100, status);
    603         ((Calendar *)cal)->clear(UCAL_HOUR);
    604 #if !UCONFIG_NO_SERVICE
    605         URegistryKey key = cal->registerFactory(NULL, status);
    606         cal->unregister(key, status);
    607 #endif
    608     }
    609     delete cal;
    610 
    611     status = U_ZERO_ERROR;
    612     cal = Calendar::createInstance(Locale("he_IL@calendar=hebrew"), status);
    613     if (failure(status, "Calendar::createInstance #7")) {
    614         return;
    615     } else {
    616         cal->roll(Calendar::MONTH, (int32_t)100, status);
    617     }
    618 
    619     LocalPointer<StringEnumeration> values(
    620         Calendar::getKeywordValuesForLocale("calendar", Locale("he"), FALSE, status));
    621     if (values.isNull() || U_FAILURE(status)) {
    622         dataerrln("FAIL: Calendar::getKeywordValuesForLocale(he): %s", u_errorName(status));
    623     } else {
    624         UBool containsHebrew = FALSE;
    625         const char *charValue;
    626         int32_t valueLength;
    627         while ((charValue = values->next(&valueLength, status)) != NULL) {
    628             if (valueLength == 6 && strcmp(charValue, "hebrew") == 0) {
    629                 containsHebrew = TRUE;
    630             }
    631         }
    632         if (!containsHebrew) {
    633             errln("Calendar::getKeywordValuesForLocale(he)->next() does not contain \"hebrew\"");
    634         }
    635 
    636         values->reset(status);
    637         containsHebrew = FALSE;
    638         UnicodeString hebrew = UNICODE_STRING_SIMPLE("hebrew");
    639         const UChar *ucharValue;
    640         while ((ucharValue = values->unext(&valueLength, status)) != NULL) {
    641             UnicodeString value(FALSE, ucharValue, valueLength);
    642             if (value == hebrew) {
    643                 containsHebrew = TRUE;
    644             }
    645         }
    646         if (!containsHebrew) {
    647             errln("Calendar::getKeywordValuesForLocale(he)->unext() does not contain \"hebrew\"");
    648         }
    649 
    650         values->reset(status);
    651         containsHebrew = FALSE;
    652         const UnicodeString *stringValue;
    653         while ((stringValue = values->snext(status)) != NULL) {
    654             if (*stringValue == hebrew) {
    655                 containsHebrew = TRUE;
    656             }
    657         }
    658         if (!containsHebrew) {
    659             errln("Calendar::getKeywordValuesForLocale(he)->snext() does not contain \"hebrew\"");
    660         }
    661     }
    662     delete cal;
    663 }
    664 
    665 // -------------------------------------
    666 
    667 /**
    668  * This test confirms the correct behavior of add when incrementing
    669  * through subsequent days.
    670  */
    671 void
    672 CalendarTest::TestRog()
    673 {
    674     UErrorCode status = U_ZERO_ERROR;
    675     GregorianCalendar* gc = new GregorianCalendar(status);
    676     if (failure(status, "new GregorianCalendar", TRUE)) return;
    677     int32_t year = 1997, month = UCAL_APRIL, date = 1;
    678     gc->set(year, month, date);
    679     gc->set(UCAL_HOUR_OF_DAY, 23);
    680     gc->set(UCAL_MINUTE, 0);
    681     gc->set(UCAL_SECOND, 0);
    682     gc->set(UCAL_MILLISECOND, 0);
    683     for (int32_t i = 0; i < 9; i++, gc->add(UCAL_DATE, 1, status)) {
    684         if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
    685         if (gc->get(UCAL_YEAR, status) != year ||
    686             gc->get(UCAL_MONTH, status) != month ||
    687             gc->get(UCAL_DATE, status) != (date + i)) errln("FAIL: Date wrong");
    688         if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
    689     }
    690     delete gc;
    691 }
    692 
    693 // -------------------------------------
    694 
    695 /**
    696  * Test the handling of the day of the week, checking for correctness and
    697  * for correct minimum and maximum values.
    698  */
    699 void
    700 CalendarTest::TestDOW943()
    701 {
    702     dowTest(FALSE);
    703     dowTest(TRUE);
    704 }
    705 
    706 void CalendarTest::dowTest(UBool lenient)
    707 {
    708     UErrorCode status = U_ZERO_ERROR;
    709     GregorianCalendar* cal = new GregorianCalendar(status);
    710     if (failure(status, "new GregorianCalendar", TRUE)) return;
    711     logln("cal - Aug 12, 1997\n");
    712     cal->set(1997, UCAL_AUGUST, 12);
    713     cal->getTime(status);
    714     if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
    715     logln((lenient?UnicodeString("LENIENT0: "):UnicodeString("nonlenient0: ")) + UnicodeString(calToStr(*cal)));
    716     cal->setLenient(lenient);
    717     logln("cal - Dec 1, 1996\n");
    718     cal->set(1996, UCAL_DECEMBER, 1);
    719     logln((lenient?UnicodeString("LENIENT: "):UnicodeString("nonlenient: ")) + UnicodeString(calToStr(*cal)));
    720     int32_t dow = cal->get(UCAL_DAY_OF_WEEK, status);
    721     if (U_FAILURE(status)) { errln("Calendar::get failed [%s]", u_errorName(status)); return; }
    722     int32_t min = cal->getMinimum(UCAL_DAY_OF_WEEK);
    723     int32_t max = cal->getMaximum(UCAL_DAY_OF_WEEK);
    724     if (dow < min ||
    725         dow > max) errln(UnicodeString("FAIL: Day of week ") + (int32_t)dow + " out of range");
    726     if (dow != UCAL_SUNDAY) errln("FAIL: Day of week should be SUNDAY[%d] not %d", UCAL_SUNDAY, dow);
    727     if (min != UCAL_SUNDAY ||
    728         max != UCAL_SATURDAY) errln("FAIL: Min/max bad");
    729     delete cal;
    730 }
    731 
    732 // -------------------------------------
    733 
    734 /**
    735  * Confirm that cloned Calendar objects do not inadvertently share substructures.
    736  */
    737 void
    738 CalendarTest::TestClonesUnique908()
    739 {
    740     UErrorCode status = U_ZERO_ERROR;
    741     Calendar *c = Calendar::createInstance(status);
    742     if (failure(status, "Calendar::createInstance", TRUE)) return;
    743     Calendar *d = (Calendar*) c->clone();
    744     c->set(UCAL_MILLISECOND, 123);
    745     d->set(UCAL_MILLISECOND, 456);
    746     if (c->get(UCAL_MILLISECOND, status) != 123 ||
    747         d->get(UCAL_MILLISECOND, status) != 456) {
    748         errln("FAIL: Clones share fields");
    749     }
    750     if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
    751     delete c;
    752     delete d;
    753 }
    754 
    755 // -------------------------------------
    756 
    757 /**
    758  * Confirm that the Gregorian cutoff value works as advertised.
    759  */
    760 void
    761 CalendarTest::TestGregorianChange768()
    762 {
    763     UBool b;
    764     UErrorCode status = U_ZERO_ERROR;
    765     UnicodeString str;
    766     GregorianCalendar* c = new GregorianCalendar(status);
    767     if (failure(status, "new GregorianCalendar", TRUE)) return;
    768     logln(UnicodeString("With cutoff ") + dateToString(c->getGregorianChange(), str));
    769     b = c->isLeapYear(1800);
    770     logln(UnicodeString(" isLeapYear(1800) = ") + (b ? "true" : "false"));
    771     logln(UnicodeString(" (should be FALSE)"));
    772     if (b) errln("FAIL");
    773     c->setGregorianChange(date(0, 0, 1), status);
    774     if (U_FAILURE(status)) { errln("GregorianCalendar::setGregorianChange failed"); return; }
    775     logln(UnicodeString("With cutoff ") + dateToString(c->getGregorianChange(), str));
    776     b = c->isLeapYear(1800);
    777     logln(UnicodeString(" isLeapYear(1800) = ") + (b ? "true" : "false"));
    778     logln(UnicodeString(" (should be TRUE)"));
    779     if (!b) errln("FAIL");
    780     delete c;
    781 }
    782 
    783 // -------------------------------------
    784 
    785 /**
    786  * Confirm the functioning of the field disambiguation algorithm.
    787  */
    788 void
    789 CalendarTest::TestDisambiguation765()
    790 {
    791     UErrorCode status = U_ZERO_ERROR;
    792     Calendar *c = Calendar::createInstance("en_US", status);
    793     if (failure(status, "Calendar::createInstance", TRUE)) return;
    794     c->setLenient(FALSE);
    795     c->clear();
    796     c->set(UCAL_YEAR, 1997);
    797     c->set(UCAL_MONTH, UCAL_JUNE);
    798     c->set(UCAL_DATE, 3);
    799     verify765("1997 third day of June = ", c, 1997, UCAL_JUNE, 3);
    800     c->clear();
    801     c->set(UCAL_YEAR, 1997);
    802     c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
    803     c->set(UCAL_MONTH, UCAL_JUNE);
    804     c->set(UCAL_DAY_OF_WEEK_IN_MONTH, 1);
    805     verify765("1997 first Tuesday in June = ", c, 1997, UCAL_JUNE, 3);
    806     c->clear();
    807     c->set(UCAL_YEAR, 1997);
    808     c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
    809     c->set(UCAL_MONTH, UCAL_JUNE);
    810     c->set(UCAL_DAY_OF_WEEK_IN_MONTH, - 1);
    811     verify765("1997 last Tuesday in June = ", c, 1997, UCAL_JUNE, 24);
    812 
    813     status = U_ZERO_ERROR;
    814     c->clear();
    815     c->set(UCAL_YEAR, 1997);
    816     c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
    817     c->set(UCAL_MONTH, UCAL_JUNE);
    818     c->set(UCAL_DAY_OF_WEEK_IN_MONTH, 0);
    819     c->getTime(status);
    820     verify765("1997 zero-th Tuesday in June = ", status);
    821 
    822     c->clear();
    823     c->set(UCAL_YEAR, 1997);
    824     c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
    825     c->set(UCAL_MONTH, UCAL_JUNE);
    826     c->set(UCAL_WEEK_OF_MONTH, 1);
    827     verify765("1997 Tuesday in week 1 of June = ", c, 1997, UCAL_JUNE, 3);
    828     c->clear();
    829     c->set(UCAL_YEAR, 1997);
    830     c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
    831     c->set(UCAL_MONTH, UCAL_JUNE);
    832     c->set(UCAL_WEEK_OF_MONTH, 5);
    833     verify765("1997 Tuesday in week 5 of June = ", c, 1997, UCAL_JULY, 1);
    834 
    835     status = U_ZERO_ERROR;
    836     c->clear();
    837     c->set(UCAL_YEAR, 1997);
    838     c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
    839     c->set(UCAL_MONTH, UCAL_JUNE);
    840     c->set(UCAL_WEEK_OF_MONTH, 0);
    841     c->setMinimalDaysInFirstWeek(1);
    842     c->getTime(status);
    843     verify765("1997 Tuesday in week 0 of June = ", status);
    844 
    845     /* Note: The following test used to expect YEAR 1997, WOY 1 to
    846      * resolve to a date in Dec 1996; that is, to behave as if
    847      * YEAR_WOY were 1997.  With the addition of a new explicit
    848      * YEAR_WOY field, YEAR_WOY must itself be set if that is what is
    849      * desired.  Using YEAR in combination with WOY is ambiguous, and
    850      * results in the first WOY/DOW day of the year satisfying the
    851      * given fields (there may be up to two such days). In this case,
    852      * it propertly resolves to Tue Dec 30 1997, which has a WOY value
    853      * of 1 (for YEAR_WOY 1998) and a DOW of Tuesday, and falls in the
    854      * _calendar_ year 1997, as specified. - aliu */
    855     c->clear();
    856     c->set(UCAL_YEAR_WOY, 1997); // aliu
    857     c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
    858     c->set(UCAL_WEEK_OF_YEAR, 1);
    859     verify765("1997 Tuesday in week 1 of yearWOY = ", c, 1996, UCAL_DECEMBER, 31);
    860     c->clear(); // - add test for YEAR
    861     c->setMinimalDaysInFirstWeek(1);
    862     c->set(UCAL_YEAR, 1997);
    863     c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
    864     c->set(UCAL_WEEK_OF_YEAR, 1);
    865     verify765("1997 Tuesday in week 1 of year = ", c, 1997, UCAL_DECEMBER, 30);
    866     c->clear();
    867     c->set(UCAL_YEAR, 1997);
    868     c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
    869     c->set(UCAL_WEEK_OF_YEAR, 10);
    870     verify765("1997 Tuesday in week 10 of year = ", c, 1997, UCAL_MARCH, 4);
    871     //try {
    872 
    873     // {sfb} week 0 is no longer a valid week of year
    874     /*c->clear();
    875     c->set(Calendar::YEAR, 1997);
    876     c->set(Calendar::DAY_OF_WEEK, Calendar::TUESDAY);
    877     //c->set(Calendar::WEEK_OF_YEAR, 0);
    878     c->set(Calendar::WEEK_OF_YEAR, 1);
    879     verify765("1997 Tuesday in week 0 of year = ", c, 1996, Calendar::DECEMBER, 24);*/
    880 
    881     //}
    882     //catch(IllegalArgumentException ex) {
    883     //    errln("FAIL: Exception seen:");
    884     //    ex.printStackTrace(log);
    885     //}
    886     delete c;
    887 }
    888 
    889 // -------------------------------------
    890 
    891 void
    892 CalendarTest::verify765(const UnicodeString& msg, Calendar* c, int32_t year, int32_t month, int32_t day)
    893 {
    894     UnicodeString str;
    895     UErrorCode status = U_ZERO_ERROR;
    896     int32_t y = c->get(UCAL_YEAR, status);
    897     int32_t m = c->get(UCAL_MONTH, status);
    898     int32_t d = c->get(UCAL_DATE, status);
    899     if ( y == year &&
    900          m == month &&
    901          d == day) {
    902         if (U_FAILURE(status)) { errln("FAIL: Calendar::get failed"); return; }
    903         logln("PASS: " + msg + dateToString(c->getTime(status), str));
    904         if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
    905     }
    906     else {
    907         errln("FAIL: " + msg + dateToString(c->getTime(status), str) + "; expected " + (int32_t)year + "/" + (int32_t)(month + 1) + "/" + (int32_t)day +
    908             "; got " + (int32_t)y + "/" + (int32_t)(m + 1) + "/" + (int32_t)d + " for Locale: " + c->getLocaleID(ULOC_ACTUAL_LOCALE,status));
    909         if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
    910     }
    911 }
    912 
    913 // -------------------------------------
    914 
    915 void
    916 CalendarTest::verify765(const UnicodeString& msg/*, IllegalArgumentException e*/, UErrorCode status)
    917 {
    918     if (status != U_ILLEGAL_ARGUMENT_ERROR) errln("FAIL: No IllegalArgumentException for " + msg);
    919     else logln("PASS: " + msg + "IllegalArgument as expected");
    920 }
    921 
    922 // -------------------------------------
    923 
    924 /**
    925  * Confirm that the offset between local time and GMT behaves as expected.
    926  */
    927 void
    928 CalendarTest::TestGMTvsLocal4064654()
    929 {
    930     test4064654(1997, 1, 1, 12, 0, 0);
    931     test4064654(1997, 4, 16, 18, 30, 0);
    932 }
    933 
    934 // -------------------------------------
    935 
    936 void
    937 CalendarTest::test4064654(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn, int32_t sc)
    938 {
    939     UDate date;
    940     UErrorCode status = U_ZERO_ERROR;
    941     UnicodeString str;
    942     Calendar *gmtcal = Calendar::createInstance(status);
    943     if (failure(status, "Calendar::createInstance", TRUE)) return;
    944     gmtcal->adoptTimeZone(TimeZone::createTimeZone("Africa/Casablanca"));
    945     gmtcal->set(yr, mo - 1, dt, hr, mn, sc);
    946     gmtcal->set(UCAL_MILLISECOND, 0);
    947     date = gmtcal->getTime(status);
    948     if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
    949     logln("date = " + dateToString(date, str));
    950     Calendar *cal = Calendar::createInstance(status);
    951     if (U_FAILURE(status)) { errln("Calendar::createInstance failed"); return; }
    952     cal->setTime(date, status);
    953     if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
    954     int32_t offset = cal->getTimeZone().getOffset((uint8_t)cal->get(UCAL_ERA, status),
    955                                                   cal->get(UCAL_YEAR, status),
    956                                                   cal->get(UCAL_MONTH, status),
    957                                                   cal->get(UCAL_DATE, status),
    958                                                   (uint8_t)cal->get(UCAL_DAY_OF_WEEK, status),
    959                                                   cal->get(UCAL_MILLISECOND, status), status);
    960     if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
    961     logln("offset for " + dateToString(date, str) + "= " + (offset / 1000 / 60 / 60.0) + "hr");
    962     int32_t utc = ((cal->get(UCAL_HOUR_OF_DAY, status) * 60 +
    963                     cal->get(UCAL_MINUTE, status)) * 60 +
    964                    cal->get(UCAL_SECOND, status)) * 1000 +
    965         cal->get(UCAL_MILLISECOND, status) - offset;
    966     if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
    967     int32_t expected = ((hr * 60 + mn) * 60 + sc) * 1000;
    968     if (utc != expected) errln(UnicodeString("FAIL: Discrepancy of ") + (utc - expected) +
    969                                " millis = " + ((utc - expected) / 1000 / 60 / 60.0) + " hr");
    970     delete gmtcal;
    971     delete cal;
    972 }
    973 
    974 // -------------------------------------
    975 
    976 /**
    977  * The operations of adding and setting should not exhibit pathological
    978  * dependence on the order of operations.  This test checks for this.
    979  */
    980 void
    981 CalendarTest::TestAddSetOrder621()
    982 {
    983     UDate d = date(97, 4, 14, 13, 23, 45);
    984     UErrorCode status = U_ZERO_ERROR;
    985     Calendar *cal = Calendar::createInstance(status);
    986     if (failure(status, "Calendar::createInstance", TRUE)) return;
    987 
    988     cal->setTime(d, status);
    989     if (U_FAILURE(status)) {
    990         errln("Calendar::setTime failed");
    991         delete cal;
    992         return;
    993     }
    994     cal->add(UCAL_DATE, - 5, status);
    995     if (U_FAILURE(status)) {
    996         errln("Calendar::add failed");
    997         delete cal;
    998         return;
    999     }
   1000     cal->set(UCAL_HOUR_OF_DAY, 0);
   1001     cal->set(UCAL_MINUTE, 0);
   1002     cal->set(UCAL_SECOND, 0);
   1003     UnicodeString s;
   1004     dateToString(cal->getTime(status), s);
   1005     if (U_FAILURE(status)) {
   1006         errln("Calendar::getTime failed");
   1007         delete cal;
   1008         return;
   1009     }
   1010     delete cal;
   1011 
   1012     cal = Calendar::createInstance(status);
   1013     if (U_FAILURE(status)) {
   1014         errln("Calendar::createInstance failed");
   1015         delete cal;
   1016         return;
   1017     }
   1018     cal->setTime(d, status);
   1019     if (U_FAILURE(status)) {
   1020         errln("Calendar::setTime failed");
   1021         delete cal;
   1022         return;
   1023     }
   1024     cal->set(UCAL_HOUR_OF_DAY, 0);
   1025     cal->set(UCAL_MINUTE, 0);
   1026     cal->set(UCAL_SECOND, 0);
   1027     cal->add(UCAL_DATE, - 5, status);
   1028     if (U_FAILURE(status)) {
   1029         errln("Calendar::add failed");
   1030         delete cal;
   1031         return;
   1032     }
   1033     UnicodeString s2;
   1034     dateToString(cal->getTime(status), s2);
   1035     if (U_FAILURE(status)) {
   1036         errln("Calendar::getTime failed");
   1037         delete cal;
   1038         return;
   1039     }
   1040     if (s == s2)
   1041         logln("Pass: " + s + " == " + s2);
   1042     else
   1043         errln("FAIL: " + s + " != " + s2);
   1044     delete cal;
   1045 }
   1046 
   1047 // -------------------------------------
   1048 
   1049 /**
   1050  * Confirm that adding to various fields works.
   1051  */
   1052 void
   1053 CalendarTest::TestAdd520()
   1054 {
   1055     int32_t y = 1997, m = UCAL_FEBRUARY, d = 1;
   1056     UErrorCode status = U_ZERO_ERROR;
   1057     GregorianCalendar *temp = new GregorianCalendar(y, m, d, status);
   1058     if (failure(status, "new GregorianCalendar", TRUE)) return;
   1059     check520(temp, y, m, d);
   1060     temp->add(UCAL_YEAR, 1, status);
   1061     if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
   1062     y++;
   1063     check520(temp, y, m, d);
   1064     temp->add(UCAL_MONTH, 1, status);
   1065     if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
   1066     m++;
   1067     check520(temp, y, m, d);
   1068     temp->add(UCAL_DATE, 1, status);
   1069     if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
   1070     d++;
   1071     check520(temp, y, m, d);
   1072     temp->add(UCAL_DATE, 2, status);
   1073     if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
   1074     d += 2;
   1075     check520(temp, y, m, d);
   1076     temp->add(UCAL_DATE, 28, status);
   1077     if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
   1078     d = 1;++m;
   1079     check520(temp, y, m, d);
   1080     delete temp;
   1081 }
   1082 
   1083 // -------------------------------------
   1084 
   1085 /**
   1086  * Execute adding and rolling in GregorianCalendar extensively,
   1087  */
   1088 void
   1089 CalendarTest::TestAddRollExtensive()
   1090 {
   1091     int32_t maxlimit = 40;
   1092     int32_t y = 1997, m = UCAL_FEBRUARY, d = 1, hr = 1, min = 1, sec = 0, ms = 0;
   1093     UErrorCode status = U_ZERO_ERROR;
   1094     GregorianCalendar *temp = new GregorianCalendar(y, m, d, status);
   1095     if (failure(status, "new GregorianCalendar", TRUE)) return;
   1096 
   1097     temp->set(UCAL_HOUR, hr);
   1098     temp->set(UCAL_MINUTE, min);
   1099     temp->set(UCAL_SECOND, sec);
   1100     temp->set(UCAL_MILLISECOND, ms);
   1101     temp->setMinimalDaysInFirstWeek(1);
   1102 
   1103     UCalendarDateFields e;
   1104 
   1105     logln("Testing GregorianCalendar add...");
   1106     e = UCAL_YEAR;
   1107     while (e < UCAL_FIELD_COUNT) {
   1108         int32_t i;
   1109         int32_t limit = maxlimit;
   1110         status = U_ZERO_ERROR;
   1111         for (i = 0; i < limit; i++) {
   1112             temp->add(e, 1, status);
   1113             if (U_FAILURE(status)) { limit = i; status = U_ZERO_ERROR; }
   1114         }
   1115         for (i = 0; i < limit; i++) {
   1116             temp->add(e, -1, status);
   1117             if (U_FAILURE(status)) { errln("GregorianCalendar::add -1 failed"); return; }
   1118         }
   1119         check520(temp, y, m, d, hr, min, sec, ms, e);
   1120 
   1121         e = (UCalendarDateFields) ((int32_t) e + 1);
   1122     }
   1123 
   1124     logln("Testing GregorianCalendar roll...");
   1125     e = UCAL_YEAR;
   1126     while (e < UCAL_FIELD_COUNT) {
   1127         int32_t i;
   1128         int32_t limit = maxlimit;
   1129         status = U_ZERO_ERROR;
   1130         for (i = 0; i < limit; i++) {
   1131             logln(calToStr(*temp) + UnicodeString("  " ) + fieldName(e) + UnicodeString("++") );
   1132             temp->roll(e, 1, status);
   1133             if (U_FAILURE(status)) {
   1134               logln("caltest.cpp:%d e=%d, i=%d - roll(+) err %s\n",  __LINE__, (int) e, (int) i, u_errorName(status));
   1135               logln(calToStr(*temp));
   1136               limit = i; status = U_ZERO_ERROR;
   1137             }
   1138         }
   1139         for (i = 0; i < limit; i++) {
   1140             logln("caltest.cpp:%d e=%d, i=%d\n",  __LINE__, (int) e, (int) i);
   1141             logln(calToStr(*temp) + UnicodeString("  " ) + fieldName(e) + UnicodeString("--") );
   1142             temp->roll(e, -1, status);
   1143             if (U_FAILURE(status)) { errln(UnicodeString("GregorianCalendar::roll ") + CalendarTest::fieldName(e) + " count=" + UnicodeString('@'+i) + " by -1 failed with " + u_errorName(status) ); return; }
   1144         }
   1145         check520(temp, y, m, d, hr, min, sec, ms, e);
   1146 
   1147         e = (UCalendarDateFields) ((int32_t) e + 1);
   1148     }
   1149 
   1150     delete temp;
   1151 }
   1152 
   1153 // -------------------------------------
   1154 void
   1155 CalendarTest::check520(Calendar* c,
   1156                         int32_t y, int32_t m, int32_t d,
   1157                         int32_t hr, int32_t min, int32_t sec,
   1158                         int32_t ms, UCalendarDateFields field)
   1159 
   1160 {
   1161     UErrorCode status = U_ZERO_ERROR;
   1162     if (c->get(UCAL_YEAR, status) != y ||
   1163         c->get(UCAL_MONTH, status) != m ||
   1164         c->get(UCAL_DATE, status) != d ||
   1165         c->get(UCAL_HOUR, status) != hr ||
   1166         c->get(UCAL_MINUTE, status) != min ||
   1167         c->get(UCAL_SECOND, status) != sec ||
   1168         c->get(UCAL_MILLISECOND, status) != ms) {
   1169         errln(UnicodeString("U_FAILURE for field ") + (int32_t)field +
   1170                 ": Expected y/m/d h:m:s:ms of " +
   1171                 y + "/" + (m + 1) + "/" + d + " " +
   1172               hr + ":" + min + ":" + sec + ":" + ms +
   1173               "; got " + c->get(UCAL_YEAR, status) +
   1174               "/" + (c->get(UCAL_MONTH, status) + 1) +
   1175               "/" + c->get(UCAL_DATE, status) +
   1176               " " + c->get(UCAL_HOUR, status) + ":" +
   1177               c->get(UCAL_MINUTE, status) + ":" +
   1178               c->get(UCAL_SECOND, status) + ":" +
   1179               c->get(UCAL_MILLISECOND, status)
   1180               );
   1181 
   1182         if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
   1183     }
   1184     else
   1185         logln(UnicodeString("Confirmed: ") + y + "/" +
   1186                 (m + 1) + "/" + d + " " +
   1187                 hr + ":" + min + ":" + sec + ":" + ms);
   1188 }
   1189 
   1190 // -------------------------------------
   1191 void
   1192 CalendarTest::check520(Calendar* c,
   1193                         int32_t y, int32_t m, int32_t d)
   1194 
   1195 {
   1196     UErrorCode status = U_ZERO_ERROR;
   1197     if (c->get(UCAL_YEAR, status) != y ||
   1198         c->get(UCAL_MONTH, status) != m ||
   1199         c->get(UCAL_DATE, status) != d) {
   1200         errln(UnicodeString("FAILURE: Expected y/m/d of ") +
   1201               y + "/" + (m + 1) + "/" + d + " " +
   1202               "; got " + c->get(UCAL_YEAR, status) +
   1203               "/" + (c->get(UCAL_MONTH, status) + 1) +
   1204               "/" + c->get(UCAL_DATE, status)
   1205               );
   1206 
   1207         if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
   1208     }
   1209     else
   1210         logln(UnicodeString("Confirmed: ") + y + "/" +
   1211                 (m + 1) + "/" + d);
   1212 }
   1213 
   1214 // -------------------------------------
   1215 
   1216 /**
   1217  * Test that setting of fields works.  In particular, make sure that all instances
   1218  * of GregorianCalendar don't share a static instance of the fields array.
   1219  */
   1220 void
   1221 CalendarTest::TestFieldSet4781()
   1222 {
   1223     // try {
   1224         UErrorCode status = U_ZERO_ERROR;
   1225         GregorianCalendar *g = new GregorianCalendar(status);
   1226         if (failure(status, "new GregorianCalendar", TRUE)) return;
   1227         GregorianCalendar *g2 = new GregorianCalendar(status);
   1228         if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
   1229         g2->set(UCAL_HOUR, 12, status);
   1230         g2->set(UCAL_MINUTE, 0, status);
   1231         g2->set(UCAL_SECOND, 0, status);
   1232         if (U_FAILURE(status)) { errln("Calendar::set failed"); return; }
   1233         if (*g == *g2) logln("Same");
   1234         else logln("Different");
   1235     //}
   1236         //catch(IllegalArgumentException e) {
   1237         //errln("Unexpected exception seen: " + e);
   1238     //}
   1239         delete g;
   1240         delete g2;
   1241 }
   1242 
   1243 // -------------------------------------
   1244 
   1245 /* We don't support serialization on C++
   1246 void
   1247 CalendarTest::TestSerialize337()
   1248 {
   1249     Calendar cal = Calendar::getInstance();
   1250     UBool ok = FALSE;
   1251     try {
   1252         FileOutputStream f = new FileOutputStream(FILENAME);
   1253         ObjectOutput s = new ObjectOutputStream(f);
   1254         s.writeObject(PREFIX);
   1255         s.writeObject(cal);
   1256         s.writeObject(POSTFIX);
   1257         f.close();
   1258         FileInputStream in = new FileInputStream(FILENAME);
   1259         ObjectInputStream t = new ObjectInputStream(in);
   1260         UnicodeString& pre = (UnicodeString&) t.readObject();
   1261         Calendar c = (Calendar) t.readObject();
   1262         UnicodeString& post = (UnicodeString&) t.readObject();
   1263         in.close();
   1264         ok = pre.equals(PREFIX) &&
   1265             post.equals(POSTFIX) &&
   1266             cal->equals(c);
   1267         File fl = new File(FILENAME);
   1268         fl.delete();
   1269     }
   1270     catch(IOException e) {
   1271         errln("FAIL: Exception received:");
   1272         e.printStackTrace(log);
   1273     }
   1274     catch(ClassNotFoundException e) {
   1275         errln("FAIL: Exception received:");
   1276         e.printStackTrace(log);
   1277     }
   1278     if (!ok) errln("Serialization of Calendar object failed.");
   1279 }
   1280 
   1281 UnicodeString& CalendarTest::PREFIX = "abc";
   1282 
   1283 UnicodeString& CalendarTest::POSTFIX = "def";
   1284 
   1285 UnicodeString& CalendarTest::FILENAME = "tmp337.bin";
   1286  */
   1287 
   1288 // -------------------------------------
   1289 
   1290 /**
   1291  * Verify that the seconds of a Calendar can be zeroed out through the
   1292  * expected sequence of operations.
   1293  */
   1294 void
   1295 CalendarTest::TestSecondsZero121()
   1296 {
   1297     UErrorCode status = U_ZERO_ERROR;
   1298     Calendar *cal = new GregorianCalendar(status);
   1299     if (failure(status, "new GregorianCalendar", TRUE)) return;
   1300     cal->setTime(Calendar::getNow(), status);
   1301     if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
   1302     cal->set(UCAL_SECOND, 0);
   1303     if (U_FAILURE(status)) { errln("Calendar::set failed"); return; }
   1304     UDate d = cal->getTime(status);
   1305     if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
   1306     UnicodeString s;
   1307     dateToString(d, s);
   1308     if (s.indexOf("DATE_FORMAT_FAILURE") >= 0) {
   1309         dataerrln("Got: \"DATE_FORMAT_FAILURE\".");
   1310     } else if (s.indexOf(":00 ") < 0) {
   1311         errln("Expected to see :00 in " + s);
   1312     }
   1313     delete cal;
   1314 }
   1315 
   1316 // -------------------------------------
   1317 
   1318 /**
   1319  * Verify that a specific sequence of adding and setting works as expected;
   1320  * it should not vary depending on when and whether the get method is
   1321  * called.
   1322  */
   1323 void
   1324 CalendarTest::TestAddSetGet0610()
   1325 {
   1326     UnicodeString EXPECTED_0610("1993/0/5", "");
   1327     UErrorCode status = U_ZERO_ERROR;
   1328     {
   1329         Calendar *calendar = new GregorianCalendar(status);
   1330         if (failure(status, "new GregorianCalendar", TRUE)) return;
   1331         calendar->set(1993, UCAL_JANUARY, 4);
   1332         logln("1A) " + value(calendar));
   1333         calendar->add(UCAL_DATE, 1, status);
   1334         if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
   1335         UnicodeString v = value(calendar);
   1336         logln("1B) " + v);
   1337         logln("--) 1993/0/5");
   1338         if (!(v == EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + "; saw " + v);
   1339         delete calendar;
   1340     }
   1341     {
   1342         Calendar *calendar = new GregorianCalendar(1993, UCAL_JANUARY, 4, status);
   1343         if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
   1344         logln("2A) " + value(calendar));
   1345         calendar->add(UCAL_DATE, 1, status);
   1346         if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
   1347         UnicodeString v = value(calendar);
   1348         logln("2B) " + v);
   1349         logln("--) 1993/0/5");
   1350         if (!(v == EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + "; saw " + v);
   1351         delete calendar;
   1352     }
   1353     {
   1354         Calendar *calendar = new GregorianCalendar(1993, UCAL_JANUARY, 4, status);
   1355         if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
   1356         logln("3A) " + value(calendar));
   1357         calendar->getTime(status);
   1358         if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
   1359         calendar->add(UCAL_DATE, 1, status);
   1360         if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
   1361         UnicodeString v = value(calendar);
   1362         logln("3B) " + v);
   1363         logln("--) 1993/0/5");
   1364         if (!(v == EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + "; saw " + v);
   1365         delete calendar;
   1366     }
   1367 }
   1368 
   1369 // -------------------------------------
   1370 
   1371 UnicodeString
   1372 CalendarTest::value(Calendar* calendar)
   1373 {
   1374     UErrorCode status = U_ZERO_ERROR;
   1375     return UnicodeString("") + (int32_t)calendar->get(UCAL_YEAR, status) +
   1376         "/" + (int32_t)calendar->get(UCAL_MONTH, status) +
   1377         "/" + (int32_t)calendar->get(UCAL_DATE, status) +
   1378         (U_FAILURE(status) ? " FAIL: Calendar::get failed" : "");
   1379 }
   1380 
   1381 
   1382 // -------------------------------------
   1383 
   1384 /**
   1385  * Verify that various fields on a known date are set correctly.
   1386  */
   1387 void
   1388 CalendarTest::TestFields060()
   1389 {
   1390     UErrorCode status = U_ZERO_ERROR;
   1391     int32_t year = 1997;
   1392     int32_t month = UCAL_OCTOBER;
   1393     int32_t dDate = 22;
   1394     GregorianCalendar *calendar = 0;
   1395     calendar = new GregorianCalendar(year, month, dDate, status);
   1396     if (failure(status, "new GregorianCalendar", TRUE)) return;
   1397     for (int32_t i = 0; i < EXPECTED_FIELDS_length;) {
   1398         UCalendarDateFields field = (UCalendarDateFields)EXPECTED_FIELDS[i++];
   1399         int32_t expected = EXPECTED_FIELDS[i++];
   1400         if (calendar->get(field, status) != expected) {
   1401             errln(UnicodeString("Expected field ") + (int32_t)field + " to have value " + (int32_t)expected +
   1402                   "; received " + (int32_t)calendar->get(field, status) + " instead");
   1403             if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
   1404         }
   1405     }
   1406     delete calendar;
   1407 }
   1408 
   1409 int32_t CalendarTest::EXPECTED_FIELDS[] = {
   1410     UCAL_YEAR, 1997,
   1411     UCAL_MONTH, UCAL_OCTOBER,
   1412     UCAL_DATE, 22,
   1413     UCAL_DAY_OF_WEEK, UCAL_WEDNESDAY,
   1414     UCAL_DAY_OF_WEEK_IN_MONTH, 4,
   1415     UCAL_DAY_OF_YEAR, 295
   1416 };
   1417 
   1418 const int32_t CalendarTest::EXPECTED_FIELDS_length = (int32_t)(sizeof(CalendarTest::EXPECTED_FIELDS) /
   1419     sizeof(CalendarTest::EXPECTED_FIELDS[0]));
   1420 
   1421 // -------------------------------------
   1422 
   1423 /**
   1424  * Verify that various fields on a known date are set correctly.  In this
   1425  * case, the start of the epoch (January 1 1970).
   1426  */
   1427 void
   1428 CalendarTest::TestEpochStartFields()
   1429 {
   1430     UErrorCode status = U_ZERO_ERROR;
   1431     TimeZone *z = TimeZone::createDefault();
   1432     Calendar *c = Calendar::createInstance(status);
   1433     if (failure(status, "Calendar::createInstance", TRUE)) return;
   1434     UDate d = - z->getRawOffset();
   1435     GregorianCalendar *gc = new GregorianCalendar(status);
   1436     if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
   1437     gc->setTimeZone(*z);
   1438     gc->setTime(d, status);
   1439     if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
   1440     UBool idt = gc->inDaylightTime(status);
   1441     if (U_FAILURE(status)) { errln("GregorianCalendar::inDaylightTime failed"); return; }
   1442     if (idt) {
   1443         UnicodeString str;
   1444         logln("Warning: Skipping test because " + dateToString(d, str) + " is in DST.");
   1445     }
   1446     else {
   1447         c->setTime(d, status);
   1448         if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
   1449         for (int32_t i = 0; i < UCAL_ZONE_OFFSET;++i) {
   1450             if (c->get((UCalendarDateFields)i, status) != EPOCH_FIELDS[i])
   1451                 dataerrln(UnicodeString("Expected field ") + i + " to have value " + EPOCH_FIELDS[i] +
   1452                       "; saw " + c->get((UCalendarDateFields)i, status) + " instead");
   1453             if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
   1454         }
   1455         if (c->get(UCAL_ZONE_OFFSET, status) != z->getRawOffset())
   1456         {
   1457             errln(UnicodeString("Expected field ZONE_OFFSET to have value ") + z->getRawOffset() +
   1458                   "; saw " + c->get(UCAL_ZONE_OFFSET, status) + " instead");
   1459             if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
   1460         }
   1461         if (c->get(UCAL_DST_OFFSET, status) != 0)
   1462         {
   1463             errln(UnicodeString("Expected field DST_OFFSET to have value 0") +
   1464                   "; saw " + c->get(UCAL_DST_OFFSET, status) + " instead");
   1465             if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
   1466         }
   1467     }
   1468     delete c;
   1469     delete z;
   1470     delete gc;
   1471 }
   1472 
   1473 int32_t CalendarTest::EPOCH_FIELDS[] = {
   1474     1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, - 28800000, 0
   1475 };
   1476 
   1477 // -------------------------------------
   1478 
   1479 /**
   1480  * Test that the days of the week progress properly when add is called repeatedly
   1481  * for increments of 24 days.
   1482  */
   1483 void
   1484 CalendarTest::TestDOWProgression()
   1485 {
   1486     UErrorCode status = U_ZERO_ERROR;
   1487     Calendar *cal = new GregorianCalendar(1972, UCAL_OCTOBER, 26, status);
   1488     if (failure(status, "new GregorianCalendar", TRUE)) return;
   1489     marchByDelta(cal, 24);
   1490     delete cal;
   1491 }
   1492 
   1493 // -------------------------------------
   1494 
   1495 void
   1496 CalendarTest::TestDOW_LOCALandYEAR_WOY()
   1497 {
   1498     /* Note: I've commented out the loop_addroll tests for YEAR and
   1499      * YEAR_WOY below because these two fields should NOT behave
   1500      * identically when adding.  YEAR should keep the month/dom
   1501      * invariant.  YEAR_WOY should keep the woy/dow invariant.  I've
   1502      * added a new test that checks for this in place of the old call
   1503      * to loop_addroll. - aliu */
   1504     UErrorCode status = U_ZERO_ERROR;
   1505     int32_t times = 20;
   1506     Calendar *cal=Calendar::createInstance(Locale::getGermany(), status);
   1507     if (failure(status, "Calendar::createInstance", TRUE)) return;
   1508     SimpleDateFormat *sdf=new SimpleDateFormat(UnicodeString("YYYY'-W'ww-ee"), Locale::getGermany(), status);
   1509     if (U_FAILURE(status)) { dataerrln("Couldn't create SimpleDateFormat - %s", u_errorName(status)); return; }
   1510 
   1511     // ICU no longer use localized date-time pattern characters by default.
   1512     // So we set pattern chars using 'J' instead of 'Y'.
   1513     DateFormatSymbols *dfs = new DateFormatSymbols(Locale::getGermany(), status);
   1514     dfs->setLocalPatternChars(UnicodeString("GyMdkHmsSEDFwWahKzJeugAZvcLQq"));
   1515     sdf->adoptDateFormatSymbols(dfs);
   1516     sdf->applyLocalizedPattern(UnicodeString("JJJJ'-W'ww-ee"), status);
   1517     if (U_FAILURE(status)) { errln("Couldn't apply localized pattern"); return; }
   1518 
   1519     cal->clear();
   1520     cal->set(1997, UCAL_DECEMBER, 25);
   1521     doYEAR_WOYLoop(cal, sdf, times, status);
   1522     //loop_addroll(cal, /*sdf,*/ times, UCAL_YEAR_WOY, UCAL_YEAR,  status);
   1523     yearAddTest(*cal, status); // aliu
   1524     loop_addroll(cal, /*sdf,*/ times, UCAL_DOW_LOCAL, UCAL_DAY_OF_WEEK, status);
   1525     if (U_FAILURE(status)) { errln("Error in parse/calculate test for 1997"); return; }
   1526 
   1527     cal->clear();
   1528     cal->set(1998, UCAL_DECEMBER, 25);
   1529     doYEAR_WOYLoop(cal, sdf, times, status);
   1530     //loop_addroll(cal, /*sdf,*/ times, UCAL_YEAR_WOY, UCAL_YEAR,  status);
   1531     yearAddTest(*cal, status); // aliu
   1532     loop_addroll(cal, /*sdf,*/ times, UCAL_DOW_LOCAL, UCAL_DAY_OF_WEEK, status);
   1533     if (U_FAILURE(status)) { errln("Error in parse/calculate test for 1998"); return; }
   1534 
   1535     cal->clear();
   1536     cal->set(1582, UCAL_OCTOBER, 1);
   1537     doYEAR_WOYLoop(cal, sdf, times, status);
   1538     //loop_addroll(cal, /*sdf,*/ times, Calendar::YEAR_WOY, Calendar::YEAR,  status);
   1539     yearAddTest(*cal, status); // aliu
   1540     loop_addroll(cal, /*sdf,*/ times, UCAL_DOW_LOCAL, UCAL_DAY_OF_WEEK, status);
   1541     if (U_FAILURE(status)) { errln("Error in parse/calculate test for 1582"); return; }
   1542     delete sdf;
   1543     delete cal;
   1544 
   1545     return;
   1546 }
   1547 
   1548 /**
   1549  * Confirm that adding a YEAR and adding a YEAR_WOY work properly for
   1550  * the given Calendar at its current setting.
   1551  */
   1552 void CalendarTest::yearAddTest(Calendar& cal, UErrorCode& status) {
   1553     /**
   1554      * When adding the YEAR, the month and day should remain constant.
   1555      * When adding the YEAR_WOY, the WOY and DOW should remain constant. - aliu
   1556      * Examples:
   1557      *  Wed Jan 14 1998 / 1998-W03-03 Add(YEAR_WOY, 1) -> Wed Jan 20 1999 / 1999-W03-03
   1558      *                                Add(YEAR, 1)     -> Thu Jan 14 1999 / 1999-W02-04
   1559      *  Thu Jan 14 1999 / 1999-W02-04 Add(YEAR_WOY, 1) -> Thu Jan 13 2000 / 2000-W02-04
   1560      *                                Add(YEAR, 1)     -> Fri Jan 14 2000 / 2000-W02-05
   1561      *  Sun Oct 31 1582 / 1582-W42-07 Add(YEAR_WOY, 1) -> Sun Oct 23 1583 / 1583-W42-07
   1562      *                                Add(YEAR, 1)     -> Mon Oct 31 1583 / 1583-W44-01
   1563      */
   1564     int32_t y   = cal.get(UCAL_YEAR, status);
   1565     int32_t mon = cal.get(UCAL_MONTH, status);
   1566     int32_t day = cal.get(UCAL_DATE, status);
   1567     int32_t ywy = cal.get(UCAL_YEAR_WOY, status);
   1568     int32_t woy = cal.get(UCAL_WEEK_OF_YEAR, status);
   1569     int32_t dow = cal.get(UCAL_DOW_LOCAL, status);
   1570     UDate t = cal.getTime(status);
   1571 
   1572     if(U_FAILURE(status)){
   1573         errln(UnicodeString("Failed to create Calendar for locale. Error: ") + UnicodeString(u_errorName(status)));
   1574         return;
   1575     }
   1576     UnicodeString str, str2;
   1577     SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"), status);
   1578     fmt.setCalendar(cal);
   1579 
   1580     fmt.format(t, str.remove());
   1581     str += ".add(YEAR, 1)    =>";
   1582     cal.add(UCAL_YEAR, 1, status);
   1583     int32_t y2   = cal.get(UCAL_YEAR, status);
   1584     int32_t mon2 = cal.get(UCAL_MONTH, status);
   1585     int32_t day2 = cal.get(UCAL_DATE, status);
   1586     fmt.format(cal.getTime(status), str);
   1587     if (y2 != (y+1) || mon2 != mon || day2 != day) {
   1588         str += (UnicodeString)", expected year " +
   1589             (y+1) + ", month " + (mon+1) + ", day " + day;
   1590         errln((UnicodeString)"FAIL: " + str);
   1591         logln( UnicodeString(" -> ") + CalendarTest::calToStr(cal) );
   1592     } else {
   1593         logln(str);
   1594     }
   1595 
   1596     fmt.format(t, str.remove());
   1597     str += ".add(YEAR_WOY, 1)=>";
   1598     cal.setTime(t, status);
   1599     logln( UnicodeString(" <- ") + CalendarTest::calToStr(cal) );
   1600     cal.add(UCAL_YEAR_WOY, 1, status);
   1601     int32_t ywy2 = cal.get(UCAL_YEAR_WOY, status);
   1602     int32_t woy2 = cal.get(UCAL_WEEK_OF_YEAR, status);
   1603     int32_t dow2 = cal.get(UCAL_DOW_LOCAL, status);
   1604     fmt.format(cal.getTime(status), str);
   1605     if (ywy2 != (ywy+1) || woy2 != woy || dow2 != dow) {
   1606         str += (UnicodeString)", expected yearWOY " +
   1607             (ywy+1) + ", woy " + woy + ", dowLocal " + dow;
   1608         errln((UnicodeString)"FAIL: " + str);
   1609         logln( UnicodeString(" -> ") + CalendarTest::calToStr(cal) );
   1610     } else {
   1611         logln(str);
   1612     }
   1613 }
   1614 
   1615 // -------------------------------------
   1616 
   1617 void CalendarTest::loop_addroll(Calendar *cal, /*SimpleDateFormat *sdf,*/ int times, UCalendarDateFields field, UCalendarDateFields field2, UErrorCode& errorCode) {
   1618     Calendar *calclone;
   1619     SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"), errorCode);
   1620     fmt.setCalendar(*cal);
   1621     int i;
   1622 
   1623     for(i = 0; i<times; i++) {
   1624         calclone = cal->clone();
   1625         UDate start = cal->getTime(errorCode);
   1626         cal->add(field,1,errorCode);
   1627         if (U_FAILURE(errorCode)) { errln("Error in add"); delete calclone; return; }
   1628         calclone->add(field2,1,errorCode);
   1629         if (U_FAILURE(errorCode)) { errln("Error in add"); delete calclone; return; }
   1630         if(cal->getTime(errorCode) != calclone->getTime(errorCode)) {
   1631             UnicodeString str("FAIL: Results of add differ. "), str2;
   1632             str += fmt.format(start, str2) + " ";
   1633             str += UnicodeString("Add(") + fieldName(field) + ", 1) -> " +
   1634                 fmt.format(cal->getTime(errorCode), str2.remove()) + "; ";
   1635             str += UnicodeString("Add(") + fieldName(field2) + ", 1) -> " +
   1636                 fmt.format(calclone->getTime(errorCode), str2.remove());
   1637             errln(str);
   1638             delete calclone;
   1639             return;
   1640         }
   1641         delete calclone;
   1642     }
   1643 
   1644     for(i = 0; i<times; i++) {
   1645         calclone = cal->clone();
   1646         cal->roll(field,(int32_t)1,errorCode);
   1647         if (U_FAILURE(errorCode)) { errln("Error in roll"); delete calclone; return; }
   1648         calclone->roll(field2,(int32_t)1,errorCode);
   1649         if (U_FAILURE(errorCode)) { errln("Error in roll"); delete calclone; return; }
   1650         if(cal->getTime(errorCode) != calclone->getTime(errorCode)) {
   1651             delete calclone;
   1652             errln("Results of roll differ!");
   1653             return;
   1654         }
   1655         delete calclone;
   1656     }
   1657 }
   1658 
   1659 // -------------------------------------
   1660 
   1661 void
   1662 CalendarTest::doYEAR_WOYLoop(Calendar *cal, SimpleDateFormat *sdf,
   1663                                     int32_t times, UErrorCode& errorCode) {
   1664 
   1665     UnicodeString us;
   1666     UDate tst, original;
   1667     Calendar *tstres = new GregorianCalendar(Locale::getGermany(), errorCode);
   1668     for(int i=0; i<times; ++i) {
   1669         sdf->format(Formattable(cal->getTime(errorCode),Formattable::kIsDate), us, errorCode);
   1670         //logln("expected: "+us);
   1671         if (U_FAILURE(errorCode)) { errln("Format error"); return; }
   1672         tst=sdf->parse(us,errorCode);
   1673         if (U_FAILURE(errorCode)) { errln("Parse error"); return; }
   1674         tstres->clear();
   1675         tstres->setTime(tst, errorCode);
   1676         //logln((UnicodeString)"Parsed week of year is "+tstres->get(UCAL_WEEK_OF_YEAR, errorCode));
   1677         if (U_FAILURE(errorCode)) { errln("Set time error"); return; }
   1678         original = cal->getTime(errorCode);
   1679         us.remove();
   1680         sdf->format(Formattable(tst,Formattable::kIsDate), us, errorCode);
   1681         //logln("got: "+us);
   1682         if (U_FAILURE(errorCode)) { errln("Get time error"); return; }
   1683         if(original!=tst) {
   1684             us.remove();
   1685             sdf->format(Formattable(original, Formattable::kIsDate), us, errorCode);
   1686             errln("FAIL: Parsed time doesn't match with regular");
   1687             logln("expected "+us + " " + calToStr(*cal));
   1688             us.remove();
   1689             sdf->format(Formattable(tst, Formattable::kIsDate), us, errorCode);
   1690             logln("got "+us + " " + calToStr(*tstres));
   1691         }
   1692         tstres->clear();
   1693         tstres->set(UCAL_YEAR_WOY, cal->get(UCAL_YEAR_WOY, errorCode));
   1694         tstres->set(UCAL_WEEK_OF_YEAR, cal->get(UCAL_WEEK_OF_YEAR, errorCode));
   1695         tstres->set(UCAL_DOW_LOCAL, cal->get(UCAL_DOW_LOCAL, errorCode));
   1696         if(cal->get(UCAL_YEAR, errorCode) != tstres->get(UCAL_YEAR, errorCode)) {
   1697             errln("FAIL: Different Year!");
   1698             logln((UnicodeString)"Expected "+cal->get(UCAL_YEAR, errorCode));
   1699             logln((UnicodeString)"Got "+tstres->get(UCAL_YEAR, errorCode));
   1700             return;
   1701         }
   1702         if(cal->get(UCAL_DAY_OF_YEAR, errorCode) != tstres->get(UCAL_DAY_OF_YEAR, errorCode)) {
   1703             errln("FAIL: Different Day Of Year!");
   1704             logln((UnicodeString)"Expected "+cal->get(UCAL_DAY_OF_YEAR, errorCode));
   1705             logln((UnicodeString)"Got "+tstres->get(UCAL_DAY_OF_YEAR, errorCode));
   1706             return;
   1707         }
   1708         //logln(calToStr(*cal));
   1709         cal->add(UCAL_DATE, 1, errorCode);
   1710         if (U_FAILURE(errorCode)) { errln("Add error"); return; }
   1711         us.remove();
   1712     }
   1713     delete (tstres);
   1714 }
   1715 // -------------------------------------
   1716 
   1717 void
   1718 CalendarTest::marchByDelta(Calendar* cal, int32_t delta)
   1719 {
   1720     UErrorCode status = U_ZERO_ERROR;
   1721     Calendar *cur = (Calendar*) cal->clone();
   1722     int32_t initialDOW = cur->get(UCAL_DAY_OF_WEEK, status);
   1723     if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
   1724     int32_t DOW, newDOW = initialDOW;
   1725     do {
   1726         UnicodeString str;
   1727         DOW = newDOW;
   1728         logln(UnicodeString("DOW = ") + DOW + "  " + dateToString(cur->getTime(status), str));
   1729         if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
   1730         cur->add(UCAL_DAY_OF_WEEK, delta, status);
   1731         if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
   1732         newDOW = cur->get(UCAL_DAY_OF_WEEK, status);
   1733         if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
   1734         int32_t expectedDOW = 1 + (DOW + delta - 1) % 7;
   1735         if (newDOW != expectedDOW) {
   1736             errln(UnicodeString("Day of week should be ") + expectedDOW + " instead of " + newDOW +
   1737                   " on " + dateToString(cur->getTime(status), str));
   1738             if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
   1739             return;
   1740         }
   1741     }
   1742     while (newDOW != initialDOW);
   1743     delete cur;
   1744 }
   1745 
   1746 #define CHECK(status, msg) \
   1747     if (U_FAILURE(status)) { \
   1748         errcheckln(status, msg); \
   1749         return; \
   1750     }
   1751 
   1752 void CalendarTest::TestWOY(void) {
   1753     /*
   1754       FDW = Mon, MDFW = 4:
   1755          Sun Dec 26 1999, WOY 51
   1756          Mon Dec 27 1999, WOY 52
   1757          Tue Dec 28 1999, WOY 52
   1758          Wed Dec 29 1999, WOY 52
   1759          Thu Dec 30 1999, WOY 52
   1760          Fri Dec 31 1999, WOY 52
   1761          Sat Jan 01 2000, WOY 52 ***
   1762          Sun Jan 02 2000, WOY 52 ***
   1763          Mon Jan 03 2000, WOY 1
   1764          Tue Jan 04 2000, WOY 1
   1765          Wed Jan 05 2000, WOY 1
   1766          Thu Jan 06 2000, WOY 1
   1767          Fri Jan 07 2000, WOY 1
   1768          Sat Jan 08 2000, WOY 1
   1769          Sun Jan 09 2000, WOY 1
   1770          Mon Jan 10 2000, WOY 2
   1771 
   1772       FDW = Mon, MDFW = 2:
   1773          Sun Dec 26 1999, WOY 52
   1774          Mon Dec 27 1999, WOY 1  ***
   1775          Tue Dec 28 1999, WOY 1  ***
   1776          Wed Dec 29 1999, WOY 1  ***
   1777          Thu Dec 30 1999, WOY 1  ***
   1778          Fri Dec 31 1999, WOY 1  ***
   1779          Sat Jan 01 2000, WOY 1
   1780          Sun Jan 02 2000, WOY 1
   1781          Mon Jan 03 2000, WOY 2
   1782          Tue Jan 04 2000, WOY 2
   1783          Wed Jan 05 2000, WOY 2
   1784          Thu Jan 06 2000, WOY 2
   1785          Fri Jan 07 2000, WOY 2
   1786          Sat Jan 08 2000, WOY 2
   1787          Sun Jan 09 2000, WOY 2
   1788          Mon Jan 10 2000, WOY 3
   1789     */
   1790 
   1791     UnicodeString str;
   1792     UErrorCode status = U_ZERO_ERROR;
   1793     int32_t i;
   1794 
   1795     GregorianCalendar cal(status);
   1796     SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy', WOY' w"), status);
   1797     if (failure(status, "Cannot construct calendar/format", TRUE)) return;
   1798 
   1799     UCalendarDaysOfWeek fdw = (UCalendarDaysOfWeek) 0;
   1800 
   1801     //for (int8_t pass=2; pass<=2; ++pass) {
   1802     for (int8_t pass=1; pass<=2; ++pass) {
   1803         switch (pass) {
   1804         case 1:
   1805             fdw = UCAL_MONDAY;
   1806             cal.setFirstDayOfWeek(fdw);
   1807             cal.setMinimalDaysInFirstWeek(4);
   1808             fmt.adoptCalendar(cal.clone());
   1809             break;
   1810         case 2:
   1811             fdw = UCAL_MONDAY;
   1812             cal.setFirstDayOfWeek(fdw);
   1813             cal.setMinimalDaysInFirstWeek(2);
   1814             fmt.adoptCalendar(cal.clone());
   1815             break;
   1816         }
   1817 
   1818         //for (i=2; i<=6; ++i) {
   1819         for (i=0; i<16; ++i) {
   1820         UDate t, t2;
   1821         int32_t t_y, t_woy, t_dow;
   1822         cal.clear();
   1823         cal.set(1999, UCAL_DECEMBER, 26 + i);
   1824         fmt.format(t = cal.getTime(status), str.remove());
   1825         CHECK(status, "Fail: getTime failed");
   1826         logln(UnicodeString("* ") + str);
   1827         int32_t dow = cal.get(UCAL_DAY_OF_WEEK, status);
   1828         int32_t woy = cal.get(UCAL_WEEK_OF_YEAR, status);
   1829         int32_t year = cal.get(UCAL_YEAR, status);
   1830         int32_t mon = cal.get(UCAL_MONTH, status);
   1831         logln(calToStr(cal));
   1832         CHECK(status, "Fail: get failed");
   1833         int32_t dowLocal = dow - fdw;
   1834         if (dowLocal < 0) dowLocal += 7;
   1835         dowLocal++;
   1836         int32_t yearWoy = year;
   1837         if (mon == UCAL_JANUARY) {
   1838             if (woy >= 52) --yearWoy;
   1839         } else {
   1840             if (woy == 1) ++yearWoy;
   1841         }
   1842 
   1843         // Basic fields->time check y/woy/dow
   1844         // Since Y/WOY is ambiguous, we do a check of the fields,
   1845         // not of the specific time.
   1846         cal.clear();
   1847         cal.set(UCAL_YEAR, year);
   1848         cal.set(UCAL_WEEK_OF_YEAR, woy);
   1849         cal.set(UCAL_DAY_OF_WEEK, dow);
   1850         t_y = cal.get(UCAL_YEAR, status);
   1851         t_woy = cal.get(UCAL_WEEK_OF_YEAR, status);
   1852         t_dow = cal.get(UCAL_DAY_OF_WEEK, status);
   1853         CHECK(status, "Fail: get failed");
   1854         if (t_y != year || t_woy != woy || t_dow != dow) {
   1855             str = "Fail: y/woy/dow fields->time => ";
   1856             fmt.format(cal.getTime(status), str);
   1857             errln(str);
   1858             logln(calToStr(cal));
   1859             logln("[get!=set] Y%d!=%d || woy%d!=%d || dow%d!=%d\n",
   1860                   t_y, year, t_woy, woy, t_dow, dow);
   1861         } else {
   1862           logln("y/woy/dow fields->time OK");
   1863         }
   1864 
   1865         // Basic fields->time check y/woy/dow_local
   1866         // Since Y/WOY is ambiguous, we do a check of the fields,
   1867         // not of the specific time.
   1868         cal.clear();
   1869         cal.set(UCAL_YEAR, year);
   1870         cal.set(UCAL_WEEK_OF_YEAR, woy);
   1871         cal.set(UCAL_DOW_LOCAL, dowLocal);
   1872         t_y = cal.get(UCAL_YEAR, status);
   1873         t_woy = cal.get(UCAL_WEEK_OF_YEAR, status);
   1874         t_dow = cal.get(UCAL_DOW_LOCAL, status);
   1875         CHECK(status, "Fail: get failed");
   1876         if (t_y != year || t_woy != woy || t_dow != dowLocal) {
   1877             str = "Fail: y/woy/dow_local fields->time => ";
   1878             fmt.format(cal.getTime(status), str);
   1879             errln(str);
   1880         }
   1881 
   1882         // Basic fields->time check y_woy/woy/dow
   1883         cal.clear();
   1884         cal.set(UCAL_YEAR_WOY, yearWoy);
   1885         cal.set(UCAL_WEEK_OF_YEAR, woy);
   1886         cal.set(UCAL_DAY_OF_WEEK, dow);
   1887         t2 = cal.getTime(status);
   1888         CHECK(status, "Fail: getTime failed");
   1889         if (t != t2) {
   1890             str = "Fail: y_woy/woy/dow fields->time => ";
   1891             fmt.format(t2, str);
   1892             errln(str);
   1893             logln(calToStr(cal));
   1894             logln("%.f != %.f\n", t, t2);
   1895         } else {
   1896           logln("y_woy/woy/dow OK");
   1897         }
   1898 
   1899         // Basic fields->time check y_woy/woy/dow_local
   1900         cal.clear();
   1901         cal.set(UCAL_YEAR_WOY, yearWoy);
   1902         cal.set(UCAL_WEEK_OF_YEAR, woy);
   1903         cal.set(UCAL_DOW_LOCAL, dowLocal);
   1904         t2 = cal.getTime(status);
   1905         CHECK(status, "Fail: getTime failed");
   1906         if (t != t2) {
   1907             str = "Fail: y_woy/woy/dow_local fields->time => ";
   1908             fmt.format(t2, str);
   1909             errln(str);
   1910         }
   1911 
   1912         logln("Testing DOW_LOCAL.. dow%d\n", dow);
   1913         // Make sure DOW_LOCAL disambiguates over DOW
   1914         int32_t wrongDow = dow - 3;
   1915         if (wrongDow < 1) wrongDow += 7;
   1916         cal.setTime(t, status);
   1917         cal.set(UCAL_DAY_OF_WEEK, wrongDow);
   1918         cal.set(UCAL_DOW_LOCAL, dowLocal);
   1919         t2 = cal.getTime(status);
   1920         CHECK(status, "Fail: set/getTime failed");
   1921         if (t != t2) {
   1922             str = "Fail: DOW_LOCAL fields->time => ";
   1923             fmt.format(t2, str);
   1924             errln(str);
   1925             logln(calToStr(cal));
   1926             logln("%.f :   DOW%d, DOW_LOCAL%d -> %.f\n",
   1927                   t, wrongDow, dowLocal, t2);
   1928         }
   1929 
   1930         // Make sure DOW disambiguates over DOW_LOCAL
   1931         int32_t wrongDowLocal = dowLocal - 3;
   1932         if (wrongDowLocal < 1) wrongDowLocal += 7;
   1933         cal.setTime(t, status);
   1934         cal.set(UCAL_DOW_LOCAL, wrongDowLocal);
   1935         cal.set(UCAL_DAY_OF_WEEK, dow);
   1936         t2 = cal.getTime(status);
   1937         CHECK(status, "Fail: set/getTime failed");
   1938         if (t != t2) {
   1939             str = "Fail: DOW       fields->time => ";
   1940             fmt.format(t2, str);
   1941             errln(str);
   1942         }
   1943 
   1944         // Make sure YEAR_WOY disambiguates over YEAR
   1945         cal.setTime(t, status);
   1946         cal.set(UCAL_YEAR, year - 2);
   1947         cal.set(UCAL_YEAR_WOY, yearWoy);
   1948         t2 = cal.getTime(status);
   1949         CHECK(status, "Fail: set/getTime failed");
   1950         if (t != t2) {
   1951             str = "Fail: YEAR_WOY  fields->time => ";
   1952             fmt.format(t2, str);
   1953             errln(str);
   1954         }
   1955 
   1956         // Make sure YEAR disambiguates over YEAR_WOY
   1957         cal.setTime(t, status);
   1958         cal.set(UCAL_YEAR_WOY, yearWoy - 2);
   1959         cal.set(UCAL_YEAR, year);
   1960         t2 = cal.getTime(status);
   1961         CHECK(status, "Fail: set/getTime failed");
   1962         if (t != t2) {
   1963             str = "Fail: YEAR      fields->time => ";
   1964             fmt.format(t2, str);
   1965             errln(str);
   1966         }
   1967     }
   1968     }
   1969 
   1970     /*
   1971       FDW = Mon, MDFW = 4:
   1972          Sun Dec 26 1999, WOY 51
   1973          Mon Dec 27 1999, WOY 52
   1974          Tue Dec 28 1999, WOY 52
   1975          Wed Dec 29 1999, WOY 52
   1976          Thu Dec 30 1999, WOY 52
   1977          Fri Dec 31 1999, WOY 52
   1978          Sat Jan 01 2000, WOY 52
   1979          Sun Jan 02 2000, WOY 52
   1980     */
   1981 
   1982     // Roll the DOW_LOCAL within week 52
   1983     for (i=27; i<=33; ++i) {
   1984         int32_t amount;
   1985         for (amount=-7; amount<=7; ++amount) {
   1986             str = "roll(";
   1987             cal.set(1999, UCAL_DECEMBER, i);
   1988             UDate t, t2;
   1989             fmt.format(cal.getTime(status), str);
   1990             CHECK(status, "Fail: getTime failed");
   1991             str += UnicodeString(", ") + amount + ") = ";
   1992 
   1993             cal.roll(UCAL_DOW_LOCAL, amount, status);
   1994             CHECK(status, "Fail: roll failed");
   1995 
   1996             t = cal.getTime(status);
   1997             int32_t newDom = i + amount;
   1998             while (newDom < 27) newDom += 7;
   1999             while (newDom > 33) newDom -= 7;
   2000             cal.set(1999, UCAL_DECEMBER, newDom);
   2001             t2 = cal.getTime(status);
   2002             CHECK(status, "Fail: getTime failed");
   2003             fmt.format(t, str);
   2004 
   2005             if (t != t2) {
   2006                 str.append(", exp ");
   2007                 fmt.format(t2, str);
   2008                 errln(str);
   2009             } else {
   2010                 logln(str);
   2011             }
   2012         }
   2013     }
   2014 }
   2015 
   2016 void CalendarTest::TestYWOY()
   2017 {
   2018    UnicodeString str;
   2019    UErrorCode status = U_ZERO_ERROR;
   2020 
   2021    GregorianCalendar cal(status);
   2022    if (failure(status, "construct GregorianCalendar", TRUE)) return;
   2023 
   2024    cal.setFirstDayOfWeek(UCAL_SUNDAY);
   2025    cal.setMinimalDaysInFirstWeek(1);
   2026 
   2027    logln("Setting:  ywoy=2004, woy=1, dow=MONDAY");
   2028    cal.clear();
   2029    cal.set(UCAL_YEAR_WOY,2004);
   2030    cal.set(UCAL_WEEK_OF_YEAR,1);
   2031    cal.set(UCAL_DAY_OF_WEEK, UCAL_MONDAY);
   2032 
   2033    logln(calToStr(cal));
   2034    if(cal.get(UCAL_YEAR, status) != 2003) {
   2035      errln("year not 2003");
   2036    }
   2037 
   2038    logln("+ setting DOW to THURSDAY");
   2039    cal.clear();
   2040    cal.set(UCAL_YEAR_WOY,2004);
   2041    cal.set(UCAL_WEEK_OF_YEAR,1);
   2042    cal.set(UCAL_DAY_OF_WEEK, UCAL_THURSDAY);
   2043 
   2044    logln(calToStr(cal));
   2045    if(cal.get(UCAL_YEAR, status) != 2004) {
   2046      errln("year not 2004");
   2047    }
   2048 
   2049    logln("+ setting DOW_LOCAL to 1");
   2050    cal.clear();
   2051    cal.set(UCAL_YEAR_WOY,2004);
   2052    cal.set(UCAL_WEEK_OF_YEAR,1);
   2053    cal.set(UCAL_DAY_OF_WEEK, UCAL_THURSDAY);
   2054    cal.set(UCAL_DOW_LOCAL, 1);
   2055 
   2056    logln(calToStr(cal));
   2057    if(cal.get(UCAL_YEAR, status) != 2003) {
   2058      errln("year not 2003");
   2059    }
   2060 
   2061    cal.setFirstDayOfWeek(UCAL_MONDAY);
   2062    cal.setMinimalDaysInFirstWeek(4);
   2063    UDate t = 946713600000.;
   2064    cal.setTime(t, status);
   2065    cal.set(UCAL_DAY_OF_WEEK, 4);
   2066    cal.set(UCAL_DOW_LOCAL, 6);
   2067    if(cal.getTime(status) != t) {
   2068      logln(calToStr(cal));
   2069      errln("FAIL:  DOW_LOCAL did not take precedence");
   2070    }
   2071 
   2072 }
   2073 
   2074 void CalendarTest::TestJD()
   2075 {
   2076   int32_t jd;
   2077   static const int32_t kEpochStartAsJulianDay = 2440588;
   2078   UErrorCode status = U_ZERO_ERROR;
   2079   GregorianCalendar cal(status);
   2080   if (failure(status, "construct GregorianCalendar", TRUE)) return;
   2081   cal.setTimeZone(*TimeZone::getGMT());
   2082   cal.clear();
   2083   jd = cal.get(UCAL_JULIAN_DAY, status);
   2084   if(jd != kEpochStartAsJulianDay) {
   2085     errln("Wanted JD of %d at time=0, [epoch 1970] but got %d\n", kEpochStartAsJulianDay, jd);
   2086   } else {
   2087     logln("Wanted JD of %d at time=0, [epoch 1970], got %d\n", kEpochStartAsJulianDay, jd);
   2088   }
   2089 
   2090   cal.setTime(Calendar::getNow(), status);
   2091   cal.clear();
   2092   cal.set(UCAL_JULIAN_DAY, kEpochStartAsJulianDay);
   2093   UDate epochTime = cal.getTime(status);
   2094   if(epochTime != 0) {
   2095     errln("Wanted time of 0 at jd=%d, got %.1lf\n", kEpochStartAsJulianDay, epochTime);
   2096   } else {
   2097     logln("Wanted time of 0 at jd=%d, got %.1lf\n", kEpochStartAsJulianDay, epochTime);
   2098   }
   2099 
   2100 }
   2101 
   2102 // make sure the ctestfw utilities are in sync with the Calendar
   2103 void CalendarTest::TestDebug()
   2104 {
   2105     for(int32_t  t=0;t<=UDBG_ENUM_COUNT;t++) {
   2106         int32_t count = udbg_enumCount((UDebugEnumType)t);
   2107         if(count == -1) {
   2108             logln("enumCount(%d) returned -1", count);
   2109             continue;
   2110         }
   2111         for(int32_t i=0;i<=count;i++) {
   2112             if(t<=UDBG_HIGHEST_CONTIGUOUS_ENUM && i<count) {
   2113                 if( i!=udbg_enumArrayValue((UDebugEnumType)t, i)) {
   2114                     errln("FAIL: udbg_enumArrayValue(%d,%d) returned %d, expected %d", t, i, udbg_enumArrayValue((UDebugEnumType)t,i), i);
   2115                 }
   2116             } else {
   2117                 logln("Testing count+1:");
   2118             }
   2119                   const char *name = udbg_enumName((UDebugEnumType)t,i);
   2120                   if(name==NULL) {
   2121                           if(i==count || t>UDBG_HIGHEST_CONTIGUOUS_ENUM  ) {
   2122                                 logln(" null name - expected.\n");
   2123                           } else {
   2124                                 errln("FAIL: udbg_enumName(%d,%d) returned NULL", t, i);
   2125                           }
   2126                           name = "(null)";
   2127                   }
   2128           logln("udbg_enumArrayValue(%d,%d) = %s, returned %d", t, i,
   2129                       name, udbg_enumArrayValue((UDebugEnumType)t,i));
   2130             logln("udbg_enumString = " + udbg_enumString((UDebugEnumType)t,i));
   2131         }
   2132         if(udbg_enumExpectedCount((UDebugEnumType)t) != count && t<=UDBG_HIGHEST_CONTIGUOUS_ENUM) {
   2133             errln("FAIL: udbg_enumExpectedCount(%d): %d, != UCAL_FIELD_COUNT=%d ", t, udbg_enumExpectedCount((UDebugEnumType)t), count);
   2134         } else {
   2135             logln("udbg_ucal_fieldCount: %d, UCAL_FIELD_COUNT=udbg_enumCount %d ", udbg_enumExpectedCount((UDebugEnumType)t), count);
   2136         }
   2137     }
   2138 }
   2139 
   2140 
   2141 #undef CHECK
   2142 
   2143 // List of interesting locales
   2144 const char *CalendarTest::testLocaleID(int32_t i)
   2145 {
   2146   switch(i) {
   2147   case 0: return "he_IL@calendar=hebrew";
   2148   case 1: return "en_US@calendar=hebrew";
   2149   case 2: return "fr_FR@calendar=hebrew";
   2150   case 3: return "fi_FI@calendar=hebrew";
   2151   case 4: return "nl_NL@calendar=hebrew";
   2152   case 5: return "hu_HU@calendar=hebrew";
   2153   case 6: return "nl_BE@currency=MTL;calendar=islamic";
   2154   case 7: return "th_TH_TRADITIONAL@calendar=gregorian";
   2155   case 8: return "ar_JO@calendar=islamic-civil";
   2156   case 9: return "fi_FI@calendar=islamic";
   2157   case 10: return "fr_CH@calendar=islamic-civil";
   2158   case 11: return "he_IL@calendar=islamic-civil";
   2159   case 12: return "hu_HU@calendar=buddhist";
   2160   case 13: return "hu_HU@calendar=islamic";
   2161   case 14: return "en_US@calendar=japanese";
   2162   default: return NULL;
   2163   }
   2164 }
   2165 
   2166 int32_t CalendarTest::testLocaleCount()
   2167 {
   2168   static int32_t gLocaleCount = -1;
   2169   if(gLocaleCount < 0) {
   2170     int32_t i;
   2171     for(i=0;testLocaleID(i) != NULL;i++) {
   2172       ;
   2173     }
   2174     gLocaleCount = i;
   2175   }
   2176   return gLocaleCount;
   2177 }
   2178 
   2179 static UDate doMinDateOfCalendar(Calendar* adopt, UBool &isGregorian, UErrorCode& status) {
   2180   if(U_FAILURE(status)) return 0.0;
   2181 
   2182   adopt->clear();
   2183   adopt->set(UCAL_EXTENDED_YEAR, adopt->getActualMinimum(UCAL_EXTENDED_YEAR, status));
   2184   UDate ret = adopt->getTime(status);
   2185   isGregorian = dynamic_cast<GregorianCalendar*>(adopt) != NULL;
   2186   delete adopt;
   2187   return ret;
   2188 }
   2189 
   2190 UDate CalendarTest::minDateOfCalendar(const Locale& locale, UBool &isGregorian, UErrorCode& status) {
   2191   if(U_FAILURE(status)) return 0.0;
   2192   return doMinDateOfCalendar(Calendar::createInstance(locale, status), isGregorian, status);
   2193 }
   2194 
   2195 UDate CalendarTest::minDateOfCalendar(const Calendar& cal, UBool &isGregorian, UErrorCode& status) {
   2196   if(U_FAILURE(status)) return 0.0;
   2197   return doMinDateOfCalendar(cal.clone(), isGregorian, status);
   2198 }
   2199 
   2200 void CalendarTest::Test6703()
   2201 {
   2202     UErrorCode status = U_ZERO_ERROR;
   2203     Calendar *cal;
   2204 
   2205     Locale loc1("en@calendar=fubar");
   2206     cal = Calendar::createInstance(loc1, status);
   2207     if (failure(status, "Calendar::createInstance", TRUE)) return;
   2208     delete cal;
   2209 
   2210     status = U_ZERO_ERROR;
   2211     Locale loc2("en");
   2212     cal = Calendar::createInstance(loc2, status);
   2213     if (failure(status, "Calendar::createInstance")) return;
   2214     delete cal;
   2215 
   2216     status = U_ZERO_ERROR;
   2217     Locale loc3("en@calendar=roc");
   2218     cal = Calendar::createInstance(loc3, status);
   2219     if (failure(status, "Calendar::createInstance")) return;
   2220     delete cal;
   2221 
   2222     return;
   2223 }
   2224 
   2225 void CalendarTest::Test3785()
   2226 {
   2227     UErrorCode status = U_ZERO_ERROR;
   2228     UnicodeString uzone = UNICODE_STRING_SIMPLE("Europe/Paris");
   2229     UnicodeString exp1 = UNICODE_STRING_SIMPLE("Mon 30 Jumada II 1433 AH, 01:47:03");
   2230     UnicodeString exp2 = UNICODE_STRING_SIMPLE("Mon 1 Rajab 1433 AH, 01:47:04");
   2231 
   2232     LocalUDateFormatPointer df(udat_open(UDAT_NONE, UDAT_NONE, "en@calendar=islamic", uzone.getTerminatedBuffer(),
   2233                                          uzone.length(), NULL, 0, &status));
   2234     if (df.isNull() || U_FAILURE(status)) return;
   2235 
   2236     UChar upattern[64];
   2237     u_uastrcpy(upattern, "EEE d MMMM y G, HH:mm:ss");
   2238     udat_applyPattern(df.getAlias(), FALSE, upattern, u_strlen(upattern));
   2239 
   2240     UChar ubuffer[1024];
   2241     UDate ud0 = 1337557623000.0;
   2242 
   2243     status = U_ZERO_ERROR;
   2244     udat_format(df.getAlias(), ud0, ubuffer, 1024, NULL, &status);
   2245     if (U_FAILURE(status)) {
   2246         errln("Error formatting date 1\n");
   2247         return;
   2248     }
   2249     //printf("formatted: '%s'\n", mkcstr(ubuffer));
   2250 
   2251     UnicodeString act1(ubuffer);
   2252     if ( act1 != exp1 ) {
   2253         errln("Unexpected result from date 1 format\n");
   2254     }
   2255     ud0 += 1000.0; // add one second
   2256 
   2257     status = U_ZERO_ERROR;
   2258     udat_format(df.getAlias(), ud0, ubuffer, 1024, NULL, &status);
   2259     if (U_FAILURE(status)) {
   2260         errln("Error formatting date 2\n");
   2261         return;
   2262     }
   2263     //printf("formatted: '%s'\n", mkcstr(ubuffer));
   2264     UnicodeString act2(ubuffer);
   2265     if ( act2 != exp2 ) {
   2266         errln("Unexpected result from date 2 format\n");
   2267     }
   2268 
   2269     return;
   2270 }
   2271 
   2272 void CalendarTest::Test1624() {
   2273     UErrorCode status = U_ZERO_ERROR;
   2274     Locale loc("he_IL@calendar=hebrew");
   2275     HebrewCalendar hc(loc,status);
   2276 
   2277     for (int32_t year = 5600; year < 5800; year++ ) {
   2278 
   2279         for (int32_t month = HebrewCalendar::TISHRI; month <= HebrewCalendar::ELUL; month++) {
   2280             // skip the adar 1 month if year is not a leap year
   2281             if (HebrewCalendar::isLeapYear(year) == FALSE && month == HebrewCalendar::ADAR_1) {
   2282                 continue;
   2283             }
   2284             int32_t day = 15;
   2285             hc.set(year,month,day);
   2286             int32_t dayHC = hc.get(UCAL_DATE,status);
   2287             int32_t monthHC = hc.get(UCAL_MONTH,status);
   2288             int32_t yearHC = hc.get(UCAL_YEAR,status);
   2289 
   2290             if (failure(status, "HebrewCalendar.get()", TRUE)) continue;
   2291 
   2292             if (dayHC != day) {
   2293                 errln(" ==> day %d incorrect, should be: %d\n",dayHC,day);
   2294                 break;
   2295             }
   2296             if (monthHC != month) {
   2297                 errln(" ==> month %d incorrect, should be: %d\n",monthHC,month);
   2298                 break;
   2299             }
   2300             if (yearHC != year) {
   2301                 errln(" ==> day %d incorrect, should be: %d\n",yearHC,year);
   2302                 break;
   2303             }
   2304         }
   2305     }
   2306     return;
   2307 }
   2308 
   2309 void CalendarTest::TestTimeStamp() {
   2310     UErrorCode status = U_ZERO_ERROR;
   2311     UDate start = 0.0, time;
   2312     Calendar *cal;
   2313 
   2314     // Create a new Gregorian Calendar.
   2315     cal = Calendar::createInstance("en_US@calender=gregorian", status);
   2316     if (U_FAILURE(status)) {
   2317         dataerrln("Error creating Gregorian calendar.");
   2318         return;
   2319     }
   2320 
   2321     for (int i = 0; i < 20000; i++) {
   2322         // Set the Gregorian Calendar to a specific date for testing.
   2323         cal->set(2009, UCAL_JULY, 3, 0, 49, 46);
   2324 
   2325         time = cal->getTime(status);
   2326         if (U_FAILURE(status)) {
   2327             errln("Error calling getTime()");
   2328             break;
   2329         }
   2330 
   2331         if (i == 0) {
   2332             start = time;
   2333         } else {
   2334             if (start != time) {
   2335                 errln("start and time not equal.");
   2336                 break;
   2337             }
   2338         }
   2339     }
   2340 
   2341     delete cal;
   2342 }
   2343 
   2344 void CalendarTest::TestISO8601() {
   2345     const char* TEST_LOCALES[] = {
   2346         "en_US@calendar=iso8601",
   2347         "en_US@calendar=Iso8601",
   2348         "th_TH@calendar=iso8601",
   2349         "ar_EG@calendar=iso8601",
   2350         NULL
   2351     };
   2352 
   2353     int32_t TEST_DATA[][3] = {
   2354         {2008, 1, 2008},
   2355         {2009, 1, 2009},
   2356         {2010, 53, 2009},
   2357         {2011, 52, 2010},
   2358         {2012, 52, 2011},
   2359         {2013, 1, 2013},
   2360         {2014, 1, 2014},
   2361         {0, 0, 0},
   2362     };
   2363 
   2364     for (int i = 0; TEST_LOCALES[i] != NULL; i++) {
   2365         UErrorCode status = U_ZERO_ERROR;
   2366         Calendar *cal = Calendar::createInstance(TEST_LOCALES[i], status);
   2367         if (U_FAILURE(status)) {
   2368             errln("Error: Failed to create a calendar for locale: %s", TEST_LOCALES[i]);
   2369             continue;
   2370         }
   2371         if (uprv_strcmp(cal->getType(), "gregorian") != 0) {
   2372             errln("Error: Gregorian calendar is not used for locale: %s", TEST_LOCALES[i]);
   2373             continue;
   2374         }
   2375         for (int j = 0; TEST_DATA[j][0] != 0; j++) {
   2376             cal->set(TEST_DATA[j][0], UCAL_JANUARY, 1);
   2377             int32_t weekNum = cal->get(UCAL_WEEK_OF_YEAR, status);
   2378             int32_t weekYear = cal->get(UCAL_YEAR_WOY, status);
   2379             if (U_FAILURE(status)) {
   2380                 errln("Error: Failed to get week of year");
   2381                 break;
   2382             }
   2383             if (weekNum != TEST_DATA[j][1] || weekYear != TEST_DATA[j][2]) {
   2384                 errln("Error: Incorrect week of year on January 1st, %d for locale %s: Returned [weekNum=%d, weekYear=%d], Expected [weekNum=%d, weekYear=%d]",
   2385                     TEST_DATA[j][0], TEST_LOCALES[i], weekNum, weekYear, TEST_DATA[j][1], TEST_DATA[j][2]);
   2386             }
   2387         }
   2388         delete cal;
   2389     }
   2390 
   2391 }
   2392 
   2393 void
   2394 CalendarTest::TestAmbiguousWallTimeAPIs(void) {
   2395     UErrorCode status = U_ZERO_ERROR;
   2396     Calendar* cal = Calendar::createInstance(status);
   2397     if (U_FAILURE(status)) {
   2398         errln("Fail: Error creating a calendar instance.");
   2399         return;
   2400     }
   2401 
   2402     if (cal->getRepeatedWallTimeOption() != UCAL_WALLTIME_LAST) {
   2403         errln("Fail: Default repeted time option is not UCAL_WALLTIME_LAST");
   2404     }
   2405     if (cal->getSkippedWallTimeOption() != UCAL_WALLTIME_LAST) {
   2406         errln("Fail: Default skipped time option is not UCAL_WALLTIME_LAST");
   2407     }
   2408 
   2409     Calendar* cal2 = cal->clone();
   2410 
   2411     if (*cal != *cal2) {
   2412         errln("Fail: Cloned calendar != the original");
   2413     }
   2414     if (!cal->equals(*cal2, status)) {
   2415         errln("Fail: The time of cloned calendar is not equal to the original");
   2416     } else if (U_FAILURE(status)) {
   2417         errln("Fail: Error equals");
   2418     }
   2419     status = U_ZERO_ERROR;
   2420 
   2421     cal2->setRepeatedWallTimeOption(UCAL_WALLTIME_FIRST);
   2422     cal2->setSkippedWallTimeOption(UCAL_WALLTIME_FIRST);
   2423 
   2424     if (*cal == *cal2) {
   2425         errln("Fail: Cloned and modified calendar == the original");
   2426     }
   2427     if (!cal->equals(*cal2, status)) {
   2428         errln("Fail: The time of cloned calendar is not equal to the original after changing wall time options");
   2429     } else if (U_FAILURE(status)) {
   2430         errln("Fail: Error equals after changing wall time options");
   2431     }
   2432     status = U_ZERO_ERROR;
   2433 
   2434     if (cal2->getRepeatedWallTimeOption() != UCAL_WALLTIME_FIRST) {
   2435         errln("Fail: Repeted time option is not UCAL_WALLTIME_FIRST");
   2436     }
   2437     if (cal2->getSkippedWallTimeOption() != UCAL_WALLTIME_FIRST) {
   2438         errln("Fail: Skipped time option is not UCAL_WALLTIME_FIRST");
   2439     }
   2440 
   2441     cal2->setRepeatedWallTimeOption(UCAL_WALLTIME_NEXT_VALID);
   2442     if (cal2->getRepeatedWallTimeOption() != UCAL_WALLTIME_FIRST) {
   2443         errln("Fail: Repeated wall time option was updated other than UCAL_WALLTIME_FIRST");
   2444     }
   2445 
   2446     delete cal;
   2447     delete cal2;
   2448 }
   2449 
   2450 class CalFields {
   2451 public:
   2452     CalFields(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec, int32_t ms = 0);
   2453     CalFields(const Calendar& cal, UErrorCode& status);
   2454     void setTo(Calendar& cal) const;
   2455     char* toString(char* buf, int32_t len) const;
   2456     UBool operator==(const CalFields& rhs) const;
   2457     UBool operator!=(const CalFields& rhs) const;
   2458     UBool isEquivalentTo(const Calendar& cal, UErrorCode& status) const;
   2459 
   2460 private:
   2461     int32_t year;
   2462     int32_t month;
   2463     int32_t day;
   2464     int32_t hour;
   2465     int32_t min;
   2466     int32_t sec;
   2467     int32_t ms;
   2468 };
   2469 
   2470 CalFields::CalFields(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec, int32_t ms)
   2471     : year(year), month(month), day(day), hour(hour), min(min), sec(sec), ms(ms) {
   2472 }
   2473 
   2474 CalFields::CalFields(const Calendar& cal, UErrorCode& status) {
   2475     year = cal.get(UCAL_YEAR, status);
   2476     month = cal.get(UCAL_MONTH, status) + 1;
   2477     day = cal.get(UCAL_DAY_OF_MONTH, status);
   2478     hour = cal.get(UCAL_HOUR_OF_DAY, status);
   2479     min = cal.get(UCAL_MINUTE, status);
   2480     sec = cal.get(UCAL_SECOND, status);
   2481     ms = cal.get(UCAL_MILLISECOND, status);
   2482 }
   2483 
   2484 void
   2485 CalFields::setTo(Calendar& cal) const {
   2486     cal.clear();
   2487     cal.set(year, month - 1, day, hour, min, sec);
   2488     cal.set(UCAL_MILLISECOND, ms);
   2489 }
   2490 
   2491 char*
   2492 CalFields::toString(char* buf, int32_t len) const {
   2493     char local[32];
   2494     sprintf(local, "%04d-%02d-%02d %02d:%02d:%02d.%03d", year, month, day, hour, min, sec, ms);
   2495     uprv_strncpy(buf, local, len - 1);
   2496     buf[len - 1] = 0;
   2497     return buf;
   2498 }
   2499 
   2500 UBool
   2501 CalFields::operator==(const CalFields& rhs) const {
   2502     return year == rhs.year
   2503         && month == rhs.month
   2504         && day == rhs.day
   2505         && hour == rhs.hour
   2506         && min == rhs.min
   2507         && sec == rhs.sec
   2508         && ms == rhs.ms;
   2509 }
   2510 
   2511 UBool
   2512 CalFields::operator!=(const CalFields& rhs) const {
   2513     return !(*this == rhs);
   2514 }
   2515 
   2516 UBool
   2517 CalFields::isEquivalentTo(const Calendar& cal, UErrorCode& status) const {
   2518     return year == cal.get(UCAL_YEAR, status)
   2519         && month == cal.get(UCAL_MONTH, status) + 1
   2520         && day == cal.get(UCAL_DAY_OF_MONTH, status)
   2521         && hour == cal.get(UCAL_HOUR_OF_DAY, status)
   2522         && min == cal.get(UCAL_MINUTE, status)
   2523         && sec == cal.get(UCAL_SECOND, status)
   2524         && ms == cal.get(UCAL_MILLISECOND, status);
   2525 }
   2526 
   2527 typedef struct {
   2528     const char*     tzid;
   2529     const CalFields in;
   2530     const CalFields expLastGMT;
   2531     const CalFields expFirstGMT;
   2532 } RepeatedWallTimeTestData;
   2533 
   2534 static const RepeatedWallTimeTestData RPDATA[] =
   2535 {
   2536     // Time zone            Input wall time                 WALLTIME_LAST in GMT            WALLTIME_FIRST in GMT
   2537     {"America/New_York",    CalFields(2011,11,6,0,59,59),   CalFields(2011,11,6,4,59,59),   CalFields(2011,11,6,4,59,59)},
   2538     {"America/New_York",    CalFields(2011,11,6,1,0,0),     CalFields(2011,11,6,6,0,0),     CalFields(2011,11,6,5,0,0)},
   2539     {"America/New_York",    CalFields(2011,11,6,1,0,1),     CalFields(2011,11,6,6,0,1),     CalFields(2011,11,6,5,0,1)},
   2540     {"America/New_York",    CalFields(2011,11,6,1,30,0),    CalFields(2011,11,6,6,30,0),    CalFields(2011,11,6,5,30,0)},
   2541     {"America/New_York",    CalFields(2011,11,6,1,59,59),   CalFields(2011,11,6,6,59,59),   CalFields(2011,11,6,5,59,59)},
   2542     {"America/New_York",    CalFields(2011,11,6,2,0,0),     CalFields(2011,11,6,7,0,0),     CalFields(2011,11,6,7,0,0)},
   2543     {"America/New_York",    CalFields(2011,11,6,2,0,1),     CalFields(2011,11,6,7,0,1),     CalFields(2011,11,6,7,0,1)},
   2544 
   2545     {"Australia/Lord_Howe", CalFields(2011,4,3,1,29,59),    CalFields(2011,4,2,14,29,59),   CalFields(2011,4,2,14,29,59)},
   2546     {"Australia/Lord_Howe", CalFields(2011,4,3,1,30,0),     CalFields(2011,4,2,15,0,0),     CalFields(2011,4,2,14,30,0)},
   2547     {"Australia/Lord_Howe", CalFields(2011,4,3,1,45,0),     CalFields(2011,4,2,15,15,0),    CalFields(2011,4,2,14,45,0)},
   2548     {"Australia/Lord_Howe", CalFields(2011,4,3,1,59,59),    CalFields(2011,4,2,15,29,59),   CalFields(2011,4,2,14,59,59)},
   2549     {"Australia/Lord_Howe", CalFields(2011,4,3,2,0,0),      CalFields(2011,4,2,15,30,0),    CalFields(2011,4,2,15,30,0)},
   2550     {"Australia/Lord_Howe", CalFields(2011,4,3,2,0,1),      CalFields(2011,4,2,15,30,1),    CalFields(2011,4,2,15,30,1)},
   2551 
   2552     {NULL,                  CalFields(0,0,0,0,0,0),         CalFields(0,0,0,0,0,0),          CalFields(0,0,0,0,0,0)}
   2553 };
   2554 
   2555 void CalendarTest::TestRepeatedWallTime(void) {
   2556     UErrorCode status = U_ZERO_ERROR;
   2557     GregorianCalendar calGMT((const TimeZone&)*TimeZone::getGMT(), status);
   2558     GregorianCalendar calDefault(status);
   2559     GregorianCalendar calLast(status);
   2560     GregorianCalendar calFirst(status);
   2561 
   2562     if (U_FAILURE(status)) {
   2563         errln("Fail: Failed to create a calendar object.");
   2564         return;
   2565     }
   2566 
   2567     calLast.setRepeatedWallTimeOption(UCAL_WALLTIME_LAST);
   2568     calFirst.setRepeatedWallTimeOption(UCAL_WALLTIME_FIRST);
   2569 
   2570     for (int32_t i = 0; RPDATA[i].tzid != NULL; i++) {
   2571         char buf[32];
   2572         TimeZone *tz = TimeZone::createTimeZone(RPDATA[i].tzid);
   2573 
   2574         // UCAL_WALLTIME_LAST
   2575         status = U_ZERO_ERROR;
   2576         calLast.setTimeZone(*tz);
   2577         RPDATA[i].in.setTo(calLast);
   2578         calGMT.setTime(calLast.getTime(status), status);
   2579         CalFields outLastGMT(calGMT, status);
   2580         if (U_FAILURE(status)) {
   2581             errln(UnicodeString("Fail: Failed to get/set time calLast/calGMT (UCAL_WALLTIME_LAST) - ")
   2582                 + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "]");
   2583         } else {
   2584             if (outLastGMT != RPDATA[i].expLastGMT) {
   2585                 dataerrln(UnicodeString("Fail: UCAL_WALLTIME_LAST ") + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "] is parsed as "
   2586                     + outLastGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + RPDATA[i].expLastGMT.toString(buf, sizeof(buf)) + "[GMT]");
   2587             }
   2588         }
   2589 
   2590         // default
   2591         status = U_ZERO_ERROR;
   2592         calDefault.setTimeZone(*tz);
   2593         RPDATA[i].in.setTo(calDefault);
   2594         calGMT.setTime(calDefault.getTime(status), status);
   2595         CalFields outDefGMT(calGMT, status);
   2596         if (U_FAILURE(status)) {
   2597             errln(UnicodeString("Fail: Failed to get/set time calLast/calGMT (default) - ")
   2598                 + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "]");
   2599         } else {
   2600             if (outDefGMT != RPDATA[i].expLastGMT) {
   2601                 dataerrln(UnicodeString("Fail: (default) ") + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "] is parsed as "
   2602                     + outDefGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + RPDATA[i].expLastGMT.toString(buf, sizeof(buf)) + "[GMT]");
   2603             }
   2604         }
   2605 
   2606         // UCAL_WALLTIME_FIRST
   2607         status = U_ZERO_ERROR;
   2608         calFirst.setTimeZone(*tz);
   2609         RPDATA[i].in.setTo(calFirst);
   2610         calGMT.setTime(calFirst.getTime(status), status);
   2611         CalFields outFirstGMT(calGMT, status);
   2612         if (U_FAILURE(status)) {
   2613             errln(UnicodeString("Fail: Failed to get/set time calLast/calGMT (UCAL_WALLTIME_FIRST) - ")
   2614                 + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "]");
   2615         } else {
   2616             if (outFirstGMT != RPDATA[i].expFirstGMT) {
   2617                 dataerrln(UnicodeString("Fail: UCAL_WALLTIME_FIRST ") + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "] is parsed as "
   2618                     + outFirstGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + RPDATA[i].expFirstGMT.toString(buf, sizeof(buf)) + "[GMT]");
   2619             }
   2620         }
   2621         delete tz;
   2622     }
   2623 }
   2624 
   2625 typedef struct {
   2626     const char*     tzid;
   2627     const CalFields in;
   2628     UBool           isValid;
   2629     const CalFields expLastGMT;
   2630     const CalFields expFirstGMT;
   2631     const CalFields expNextAvailGMT;
   2632 } SkippedWallTimeTestData;
   2633 
   2634 static SkippedWallTimeTestData SKDATA[] =
   2635 {
   2636      // Time zone           Input wall time                 valid?  WALLTIME_LAST in GMT            WALLTIME_FIRST in GMT           WALLTIME_NEXT_VALID in GMT
   2637     {"America/New_York",    CalFields(2011,3,13,1,59,59),   TRUE,   CalFields(2011,3,13,6,59,59),   CalFields(2011,3,13,6,59,59),   CalFields(2011,3,13,6,59,59)},
   2638     {"America/New_York",    CalFields(2011,3,13,2,0,0),     FALSE,  CalFields(2011,3,13,7,0,0),     CalFields(2011,3,13,6,0,0),     CalFields(2011,3,13,7,0,0)},
   2639     {"America/New_York",    CalFields(2011,3,13,2,1,0),     FALSE,  CalFields(2011,3,13,7,1,0),     CalFields(2011,3,13,6,1,0),     CalFields(2011,3,13,7,0,0)},
   2640     {"America/New_York",    CalFields(2011,3,13,2,30,0),    FALSE,  CalFields(2011,3,13,7,30,0),    CalFields(2011,3,13,6,30,0),    CalFields(2011,3,13,7,0,0)},
   2641     {"America/New_York",    CalFields(2011,3,13,2,59,59),   FALSE,  CalFields(2011,3,13,7,59,59),   CalFields(2011,3,13,6,59,59),   CalFields(2011,3,13,7,0,0)},
   2642     {"America/New_York",    CalFields(2011,3,13,3,0,0),     TRUE,   CalFields(2011,3,13,7,0,0),     CalFields(2011,3,13,7,0,0),     CalFields(2011,3,13,7,0,0)},
   2643 
   2644     {"Pacific/Apia",        CalFields(2011,12,29,23,59,59), TRUE,   CalFields(2011,12,30,9,59,59),  CalFields(2011,12,30,9,59,59),  CalFields(2011,12,30,9,59,59)},
   2645     {"Pacific/Apia",        CalFields(2011,12,30,0,0,0),    FALSE,  CalFields(2011,12,30,10,0,0),   CalFields(2011,12,29,10,0,0),   CalFields(2011,12,30,10,0,0)},
   2646     {"Pacific/Apia",        CalFields(2011,12,30,12,0,0),   FALSE,  CalFields(2011,12,30,22,0,0),   CalFields(2011,12,29,22,0,0),   CalFields(2011,12,30,10,0,0)},
   2647     {"Pacific/Apia",        CalFields(2011,12,30,23,59,59), FALSE,  CalFields(2011,12,31,9,59,59),  CalFields(2011,12,30,9,59,59),  CalFields(2011,12,30,10,0,0)},
   2648     {"Pacific/Apia",        CalFields(2011,12,31,0,0,0),    TRUE,   CalFields(2011,12,30,10,0,0),   CalFields(2011,12,30,10,0,0),   CalFields(2011,12,30,10,0,0)},
   2649 
   2650     {NULL,                  CalFields(0,0,0,0,0,0),         TRUE,   CalFields(0,0,0,0,0,0),         CalFields(0,0,0,0,0,0),         CalFields(0,0,0,0,0,0)}
   2651 };
   2652 
   2653 
   2654 void CalendarTest::TestSkippedWallTime(void) {
   2655     UErrorCode status = U_ZERO_ERROR;
   2656     GregorianCalendar calGMT((const TimeZone&)*TimeZone::getGMT(), status);
   2657     GregorianCalendar calDefault(status);
   2658     GregorianCalendar calLast(status);
   2659     GregorianCalendar calFirst(status);
   2660     GregorianCalendar calNextAvail(status);
   2661 
   2662     if (U_FAILURE(status)) {
   2663         errln("Fail: Failed to create a calendar object.");
   2664         return;
   2665     }
   2666 
   2667     calLast.setSkippedWallTimeOption(UCAL_WALLTIME_LAST);
   2668     calFirst.setSkippedWallTimeOption(UCAL_WALLTIME_FIRST);
   2669     calNextAvail.setSkippedWallTimeOption(UCAL_WALLTIME_NEXT_VALID);
   2670 
   2671     for (int32_t i = 0; SKDATA[i].tzid != NULL; i++) {
   2672         UDate d;
   2673         char buf[32];
   2674         TimeZone *tz = TimeZone::createTimeZone(SKDATA[i].tzid);
   2675 
   2676         for (int32_t j = 0; j < 2; j++) {
   2677             UBool bLenient = (j == 0);
   2678 
   2679             // UCAL_WALLTIME_LAST
   2680             status = U_ZERO_ERROR;
   2681             calLast.setLenient(bLenient);
   2682             calLast.setTimeZone(*tz);
   2683             SKDATA[i].in.setTo(calLast);
   2684             d = calLast.getTime(status);
   2685             if (bLenient || SKDATA[i].isValid) {
   2686                 calGMT.setTime(d, status);
   2687                 CalFields outLastGMT(calGMT, status);
   2688                 if (U_FAILURE(status)) {
   2689                     errln(UnicodeString("Fail: Failed to get/set time calLast/calGMT (UCAL_WALLTIME_LAST) - ")
   2690                         + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
   2691                 } else {
   2692                     if (outLastGMT != SKDATA[i].expLastGMT) {
   2693                         dataerrln(UnicodeString("Fail: UCAL_WALLTIME_LAST ") + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "] is parsed as "
   2694                             + outLastGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + SKDATA[i].expLastGMT.toString(buf, sizeof(buf)) + "[GMT]");
   2695                     }
   2696                 }
   2697             } else if (U_SUCCESS(status)) {
   2698                 // strict, invalid wall time - must report an error
   2699                 dataerrln(UnicodeString("Fail: An error expected (UCAL_WALLTIME_LAST)") +
   2700                     + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
   2701             }
   2702 
   2703             // default
   2704             status = U_ZERO_ERROR;
   2705             calDefault.setLenient(bLenient);
   2706             calDefault.setTimeZone(*tz);
   2707             SKDATA[i].in.setTo(calDefault);
   2708             d = calDefault.getTime(status);
   2709             if (bLenient || SKDATA[i].isValid) {
   2710                 calGMT.setTime(d, status);
   2711                 CalFields outDefGMT(calGMT, status);
   2712                 if (U_FAILURE(status)) {
   2713                     errln(UnicodeString("Fail: Failed to get/set time calDefault/calGMT (default) - ")
   2714                         + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
   2715                 } else {
   2716                     if (outDefGMT != SKDATA[i].expLastGMT) {
   2717                         dataerrln(UnicodeString("Fail: (default) ") + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "] is parsed as "
   2718                             + outDefGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + SKDATA[i].expLastGMT.toString(buf, sizeof(buf)) + "[GMT]");
   2719                     }
   2720                 }
   2721             } else if (U_SUCCESS(status)) {
   2722                 // strict, invalid wall time - must report an error
   2723                 dataerrln(UnicodeString("Fail: An error expected (default)") +
   2724                     + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
   2725             }
   2726 
   2727             // UCAL_WALLTIME_FIRST
   2728             status = U_ZERO_ERROR;
   2729             calFirst.setLenient(bLenient);
   2730             calFirst.setTimeZone(*tz);
   2731             SKDATA[i].in.setTo(calFirst);
   2732             d = calFirst.getTime(status);
   2733             if (bLenient || SKDATA[i].isValid) {
   2734                 calGMT.setTime(d, status);
   2735                 CalFields outFirstGMT(calGMT, status);
   2736                 if (U_FAILURE(status)) {
   2737                     errln(UnicodeString("Fail: Failed to get/set time calFirst/calGMT (UCAL_WALLTIME_FIRST) - ")
   2738                         + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
   2739                 } else {
   2740                     if (outFirstGMT != SKDATA[i].expFirstGMT) {
   2741                         dataerrln(UnicodeString("Fail: UCAL_WALLTIME_FIRST ") + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "] is parsed as "
   2742                             + outFirstGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + SKDATA[i].expFirstGMT.toString(buf, sizeof(buf)) + "[GMT]");
   2743                     }
   2744                 }
   2745             } else if (U_SUCCESS(status)) {
   2746                 // strict, invalid wall time - must report an error
   2747                 dataerrln(UnicodeString("Fail: An error expected (UCAL_WALLTIME_FIRST)") +
   2748                     + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
   2749             }
   2750 
   2751             // UCAL_WALLTIME_NEXT_VALID
   2752             status = U_ZERO_ERROR;
   2753             calNextAvail.setLenient(bLenient);
   2754             calNextAvail.setTimeZone(*tz);
   2755             SKDATA[i].in.setTo(calNextAvail);
   2756             d = calNextAvail.getTime(status);
   2757             if (bLenient || SKDATA[i].isValid) {
   2758                 calGMT.setTime(d, status);
   2759                 CalFields outNextAvailGMT(calGMT, status);
   2760                 if (U_FAILURE(status)) {
   2761                     errln(UnicodeString("Fail: Failed to get/set time calNextAvail/calGMT (UCAL_WALLTIME_NEXT_VALID) - ")
   2762                         + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
   2763                 } else {
   2764                     if (outNextAvailGMT != SKDATA[i].expNextAvailGMT) {
   2765                         dataerrln(UnicodeString("Fail: UCAL_WALLTIME_NEXT_VALID ") + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "] is parsed as "
   2766                             + outNextAvailGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + SKDATA[i].expNextAvailGMT.toString(buf, sizeof(buf)) + "[GMT]");
   2767                     }
   2768                 }
   2769             } else if (U_SUCCESS(status)) {
   2770                 // strict, invalid wall time - must report an error
   2771                 dataerrln(UnicodeString("Fail: An error expected (UCAL_WALLTIME_NEXT_VALID)") +
   2772                     + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
   2773             }
   2774         }
   2775 
   2776         delete tz;
   2777     }
   2778 }
   2779 
   2780 void CalendarTest::TestCloneLocale(void) {
   2781   UErrorCode status = U_ZERO_ERROR;
   2782   LocalPointer<Calendar>  cal(Calendar::createInstance(TimeZone::getGMT()->clone(),
   2783                                                        Locale::createFromName("en"), status));
   2784   TEST_CHECK_STATUS;
   2785   Locale l0 = cal->getLocale(ULOC_VALID_LOCALE, status);
   2786   TEST_CHECK_STATUS;
   2787   LocalPointer<Calendar> cal2(cal->clone());
   2788   Locale l = cal2->getLocale(ULOC_VALID_LOCALE, status);
   2789   if(l0!=l) {
   2790     errln("Error: cloned locale %s != original locale %s, status %s\n", l0.getName(), l.getName(), u_errorName(status));
   2791   }
   2792   TEST_CHECK_STATUS;
   2793 }
   2794 
   2795 void CalendarTest::setAndTestCalendar(Calendar* cal, int32_t initMonth, int32_t initDay, int32_t initYear, UErrorCode& status) {
   2796         cal->clear();
   2797         cal->setLenient(FALSE);
   2798         cal->set(initYear, initMonth, initDay);
   2799         int32_t day = cal->get(UCAL_DAY_OF_MONTH, status);
   2800         int32_t month = cal->get(UCAL_MONTH, status);
   2801         int32_t year = cal->get(UCAL_YEAR, status);
   2802         if(U_FAILURE(status))
   2803             return;
   2804 
   2805         if(initDay != day || initMonth != month || initYear != year)
   2806         {
   2807             errln(" year init values:\tmonth %i\tday %i\tyear %i", initMonth, initDay, initYear);
   2808             errln("values post set():\tmonth %i\tday %i\tyear %i",month, day, year);
   2809         }
   2810 }
   2811 
   2812 void CalendarTest::setAndTestWholeYear(Calendar* cal, int32_t startYear, UErrorCode& status) {
   2813         for(int32_t startMonth = 0; startMonth < 12; startMonth++) {
   2814             for(int32_t startDay = 1; startDay < 31; startDay++ ) {
   2815                     setAndTestCalendar(cal, startMonth, startDay, startYear, status);
   2816                     if(U_FAILURE(status) && startDay == 30) {
   2817                         status = U_ZERO_ERROR;
   2818                         continue;
   2819                     }
   2820                     TEST_CHECK_STATUS;
   2821             }
   2822         }
   2823 }
   2824 
   2825 // =====================================================================
   2826 
   2827 typedef struct {
   2828     int16_t  gYear;
   2829     int8_t   gMon;
   2830     int8_t   gDay;
   2831     int16_t  uYear;
   2832     int8_t   uMon;
   2833     int8_t   uDay;
   2834 } GregoUmmAlQuraMap;
   2835 
   2836 // data from
   2837 // Official Umm-al-Qura calendar of SA:
   2838 // home, http://www.ummulqura.org.sa/default.aspx
   2839 // converter, http://www.ummulqura.org.sa/Index.aspx
   2840 static const GregoUmmAlQuraMap guMappings[] = {
   2841 //  gregorian,    ummAlQura
   2842 //  year mo da,   year mo da
   2843 //  (using 1-based months here)
   2844   { 1882,11,12,   1300, 1, 1 },
   2845   { 1892, 7,25,   1310, 1, 1 },
   2846   { 1896, 6,12,   1314, 1, 1 },
   2847   { 1898, 5,22,   1316, 1, 1 },
   2848   { 1900, 4,30,   1318, 1, 1 },
   2849   { 1901, 4,20,   1319, 1, 1 },
   2850   { 1902, 4,10,   1320, 1, 1 },
   2851   { 1903, 3,30,   1321, 1, 1 },
   2852   { 1904, 3,19,   1322, 1, 1 },
   2853   { 1905, 3, 8,   1323, 1, 1 },
   2854   { 1906, 2,25,   1324, 1, 1 },
   2855   { 1907, 2,14,   1325, 1, 1 },
   2856   { 1908, 2, 4,   1326, 1, 1 },
   2857   { 1909, 1,23,   1327, 1, 1 },
   2858   { 1910, 1,13,   1328, 1, 1 },
   2859   { 1911, 1, 2,   1329, 1, 1 },
   2860   { 1911,12,22,   1330, 1, 1 },
   2861   { 1912,12,10,   1331, 1, 1 },
   2862   { 1913,11,30,   1332, 1, 1 },
   2863   { 1914,11,19,   1333, 1, 1 },
   2864   { 1915,11, 9,   1334, 1, 1 },
   2865   { 1916,10,28,   1335, 1, 1 },
   2866   { 1917,10,18,   1336, 1, 1 },
   2867   { 1918,10, 7,   1337, 1, 1 },
   2868   { 1919, 9,26,   1338, 1, 1 },
   2869   { 1920, 9,14,   1339, 1, 1 },
   2870   { 1921, 9, 4,   1340, 1, 1 },
   2871   { 1922, 8,24,   1341, 1, 1 },
   2872   { 1923, 8,14,   1342, 1, 1 },
   2873   { 1924, 8, 2,   1343, 1, 1 },
   2874   { 1925, 7,22,   1344, 1, 1 },
   2875   { 1926, 7,11,   1345, 1, 1 },
   2876   { 1927, 6,30,   1346, 1, 1 },
   2877   { 1928, 6,19,   1347, 1, 1 },
   2878   { 1929, 6, 9,   1348, 1, 1 },
   2879   { 1930, 5,29,   1349, 1, 1 },
   2880   { 1931, 5,19,   1350, 1, 1 },
   2881   { 1932, 5, 7,   1351, 1, 1 },
   2882   { 1933, 4,26,   1352, 1, 1 },
   2883   { 1934, 4,15,   1353, 1, 1 },
   2884   { 1935, 4, 5,   1354, 1, 1 },
   2885   { 1936, 3,24,   1355, 1, 1 },
   2886   { 1937, 3,14,   1356, 1, 1 },
   2887   { 1938, 3, 4,   1357, 1, 1 },
   2888   { 1939, 2,21,   1358, 1, 1 },
   2889   { 1940, 2,10,   1359, 1, 1 },
   2890   { 1941, 1,29,   1360, 1, 1 },
   2891   { 1942, 1,18,   1361, 1, 1 },
   2892   { 1943, 1, 8,   1362, 1, 1 },
   2893   { 1943,12,28,   1363, 1, 1 },
   2894   { 1944,12,17,   1364, 1, 1 },
   2895   { 1945,12, 6,   1365, 1, 1 },
   2896   { 1946,11,25,   1366, 1, 1 },
   2897   { 1947,11,14,   1367, 1, 1 },
   2898   { 1948,11, 3,   1368, 1, 1 },
   2899   { 1949,10,23,   1369, 1, 1 },
   2900   { 1950,10,13,   1370, 1, 1 },
   2901   { 1951,10, 3,   1371, 1, 1 },
   2902   { 1952, 9,21,   1372, 1, 1 },
   2903   { 1953, 9,10,   1373, 1, 1 },
   2904   { 1954, 8,30,   1374, 1, 1 },
   2905   { 1955, 8,19,   1375, 1, 1 },
   2906   { 1956, 8, 8,   1376, 1, 1 },
   2907   { 1957, 7,29,   1377, 1, 1 },
   2908   { 1958, 7,18,   1378, 1, 1 },
   2909   { 1959, 7, 8,   1379, 1, 1 },
   2910   { 1960, 6,26,   1380, 1, 1 },
   2911   { 1961, 6,15,   1381, 1, 1 },
   2912   { 1962, 6, 4,   1382, 1, 1 },
   2913   { 1963, 5,24,   1383, 1, 1 },
   2914   { 1964, 5,13,   1384, 1, 1 },
   2915   { 1965, 5, 3,   1385, 1, 1 },
   2916   { 1966, 4,22,   1386, 1, 1 },
   2917   { 1967, 4,11,   1387, 1, 1 },
   2918   { 1968, 3,30,   1388, 1, 1 },
   2919   { 1969, 3,19,   1389, 1, 1 },
   2920   { 1970, 3, 9,   1390, 1, 1 },
   2921   { 1971, 2,27,   1391, 1, 1 },
   2922   { 1972, 2,16,   1392, 1, 1 },
   2923   { 1973, 2, 5,   1393, 1, 1 },
   2924   { 1974, 1,25,   1394, 1, 1 },
   2925   { 1975, 1,14,   1395, 1, 1 },
   2926   { 1976, 1, 3,   1396, 1, 1 },
   2927   { 1976,12,22,   1397, 1, 1 },
   2928   { 1977,12,12,   1398, 1, 1 },
   2929   { 1978,12, 1,   1399, 1, 1 },
   2930   { 1979,11,21,   1400, 1, 1 },
   2931   { 1980,11, 9,   1401, 1, 1 },
   2932   { 1981,10,29,   1402, 1, 1 },
   2933   { 1982,10,18,   1403, 1, 1 },
   2934   { 1983,10, 8,   1404, 1, 1 },
   2935   { 1984, 9,26,   1405, 1, 1 },
   2936   { 1985, 9,16,   1406, 1, 1 },
   2937   { 1986, 9, 6,   1407, 1, 1 },
   2938   { 1987, 8,26,   1408, 1, 1 },
   2939   { 1988, 8,14,   1409, 1, 1 },
   2940   { 1989, 8, 3,   1410, 1, 1 },
   2941   { 1990, 7,23,   1411, 1, 1 },
   2942   { 1991, 7,13,   1412, 1, 1 },
   2943   { 1992, 7, 2,   1413, 1, 1 },
   2944   { 1993, 6,21,   1414, 1, 1 },
   2945   { 1994, 6,11,   1415, 1, 1 },
   2946   { 1995, 5,31,   1416, 1, 1 },
   2947   { 1996, 5,19,   1417, 1, 1 },
   2948   { 1997, 5, 8,   1418, 1, 1 },
   2949   { 1998, 4,28,   1419, 1, 1 },
   2950   { 1999, 4,17,   1420, 1, 1 },
   2951   { 1999, 5,16,   1420, 2, 1 },
   2952   { 1999, 6,15,   1420, 3, 1 },
   2953   { 1999, 7,14,   1420, 4, 1 },
   2954   { 1999, 8,12,   1420, 5, 1 },
   2955   { 1999, 9,11,   1420, 6, 1 },
   2956   { 1999,10,10,   1420, 7, 1 },
   2957   { 1999,11, 9,   1420, 8, 1 },
   2958   { 1999,12, 9,   1420, 9, 1 },
   2959   { 2000, 1, 8,   1420,10, 1 },
   2960   { 2000, 2, 7,   1420,11, 1 },
   2961   { 2000, 3, 7,   1420,12, 1 },
   2962   { 2000, 4, 6,   1421, 1, 1 },
   2963   { 2000, 5, 5,   1421, 2, 1 },
   2964   { 2000, 6, 3,   1421, 3, 1 },
   2965   { 2000, 7, 3,   1421, 4, 1 },
   2966   { 2000, 8, 1,   1421, 5, 1 },
   2967   { 2000, 8,30,   1421, 6, 1 },
   2968   { 2000, 9,28,   1421, 7, 1 },
   2969   { 2000,10,28,   1421, 8, 1 },
   2970   { 2000,11,27,   1421, 9, 1 },
   2971   { 2000,12,27,   1421,10, 1 },
   2972   { 2001, 1,26,   1421,11, 1 },
   2973   { 2001, 2,24,   1421,12, 1 },
   2974   { 2001, 3,26,   1422, 1, 1 },
   2975   { 2001, 4,25,   1422, 2, 1 },
   2976   { 2001, 5,24,   1422, 3, 1 },
   2977   { 2001, 6,22,   1422, 4, 1 },
   2978   { 2001, 7,22,   1422, 5, 1 },
   2979   { 2001, 8,20,   1422, 6, 1 },
   2980   { 2001, 9,18,   1422, 7, 1 },
   2981   { 2001,10,17,   1422, 8, 1 },
   2982   { 2001,11,16,   1422, 9, 1 },
   2983   { 2001,12,16,   1422,10, 1 },
   2984   { 2002, 1,15,   1422,11, 1 },
   2985   { 2002, 2,13,   1422,12, 1 },
   2986   { 2002, 3,15,   1423, 1, 1 },
   2987   { 2002, 4,14,   1423, 2, 1 },
   2988   { 2002, 5,13,   1423, 3, 1 },
   2989   { 2002, 6,12,   1423, 4, 1 },
   2990   { 2002, 7,11,   1423, 5, 1 },
   2991   { 2002, 8,10,   1423, 6, 1 },
   2992   { 2002, 9, 8,   1423, 7, 1 },
   2993   { 2002,10, 7,   1423, 8, 1 },
   2994   { 2002,11, 6,   1423, 9, 1 },
   2995   { 2002,12, 5,   1423,10, 1 },
   2996   { 2003, 1, 4,   1423,11, 1 },
   2997   { 2003, 2, 2,   1423,12, 1 },
   2998   { 2003, 3, 4,   1424, 1, 1 },
   2999   { 2003, 4, 3,   1424, 2, 1 },
   3000   { 2003, 5, 2,   1424, 3, 1 },
   3001   { 2003, 6, 1,   1424, 4, 1 },
   3002   { 2003, 7, 1,   1424, 5, 1 },
   3003   { 2003, 7,30,   1424, 6, 1 },
   3004   { 2003, 8,29,   1424, 7, 1 },
   3005   { 2003, 9,27,   1424, 8, 1 },
   3006   { 2003,10,26,   1424, 9, 1 },
   3007   { 2003,11,25,   1424,10, 1 },
   3008   { 2003,12,24,   1424,11, 1 },
   3009   { 2004, 1,23,   1424,12, 1 },
   3010   { 2004, 2,21,   1425, 1, 1 },
   3011   { 2004, 3,22,   1425, 2, 1 },
   3012   { 2004, 4,20,   1425, 3, 1 },
   3013   { 2004, 5,20,   1425, 4, 1 },
   3014   { 2004, 6,19,   1425, 5, 1 },
   3015   { 2004, 7,18,   1425, 6, 1 },
   3016   { 2004, 8,17,   1425, 7, 1 },
   3017   { 2004, 9,15,   1425, 8, 1 },
   3018   { 2004,10,15,   1425, 9, 1 },
   3019   { 2004,11,14,   1425,10, 1 },
   3020   { 2004,12,13,   1425,11, 1 },
   3021   { 2005, 1,12,   1425,12, 1 },
   3022   { 2005, 2,10,   1426, 1, 1 },
   3023   { 2005, 3,11,   1426, 2, 1 },
   3024   { 2005, 4,10,   1426, 3, 1 },
   3025   { 2005, 5, 9,   1426, 4, 1 },
   3026   { 2005, 6, 8,   1426, 5, 1 },
   3027   { 2005, 7, 7,   1426, 6, 1 },
   3028   { 2005, 8, 6,   1426, 7, 1 },
   3029   { 2005, 9, 5,   1426, 8, 1 },
   3030   { 2005,10, 4,   1426, 9, 1 },
   3031   { 2005,11, 3,   1426,10, 1 },
   3032   { 2005,12, 3,   1426,11, 1 },
   3033   { 2006, 1, 1,   1426,12, 1 },
   3034   { 2006, 1,31,   1427, 1, 1 },
   3035   { 2006, 3, 1,   1427, 2, 1 },
   3036   { 2006, 3,30,   1427, 3, 1 },
   3037   { 2006, 4,29,   1427, 4, 1 },
   3038   { 2006, 5,28,   1427, 5, 1 },
   3039   { 2006, 6,27,   1427, 6, 1 },
   3040   { 2006, 7,26,   1427, 7, 1 },
   3041   { 2006, 8,25,   1427, 8, 1 },
   3042   { 2006, 9,24,   1427, 9, 1 },
   3043   { 2006,10,23,   1427,10, 1 },
   3044   { 2006,11,22,   1427,11, 1 },
   3045   { 2006,12,22,   1427,12, 1 },
   3046   { 2007, 1,20,   1428, 1, 1 },
   3047   { 2007, 2,19,   1428, 2, 1 },
   3048   { 2007, 3,20,   1428, 3, 1 },
   3049   { 2007, 4,18,   1428, 4, 1 },
   3050   { 2007, 5,18,   1428, 5, 1 },
   3051   { 2007, 6,16,   1428, 6, 1 },
   3052   { 2007, 7,15,   1428, 7, 1 },
   3053   { 2007, 8,14,   1428, 8, 1 },
   3054   { 2007, 9,13,   1428, 9, 1 },
   3055   { 2007,10,13,   1428,10, 1 },
   3056   { 2007,11,11,   1428,11, 1 },
   3057   { 2007,12,11,   1428,12, 1 },
   3058   { 2008, 1,10,   1429, 1, 1 },
   3059   { 2008, 2, 8,   1429, 2, 1 },
   3060   { 2008, 3, 9,   1429, 3, 1 },
   3061   { 2008, 4, 7,   1429, 4, 1 },
   3062   { 2008, 5, 6,   1429, 5, 1 },
   3063   { 2008, 6, 5,   1429, 6, 1 },
   3064   { 2008, 7, 4,   1429, 7, 1 },
   3065   { 2008, 8, 2,   1429, 8, 1 },
   3066   { 2008, 9, 1,   1429, 9, 1 },
   3067   { 2008,10, 1,   1429,10, 1 },
   3068   { 2008,10,30,   1429,11, 1 },
   3069   { 2008,11,29,   1429,12, 1 },
   3070   { 2008,12,29,   1430, 1, 1 },
   3071   { 2009, 1,27,   1430, 2, 1 },
   3072   { 2009, 2,26,   1430, 3, 1 },
   3073   { 2009, 3,28,   1430, 4, 1 },
   3074   { 2009, 4,26,   1430, 5, 1 },
   3075   { 2009, 5,25,   1430, 6, 1 },
   3076   { 2009, 6,24,   1430, 7, 1 },
   3077   { 2009, 7,23,   1430, 8, 1 },
   3078   { 2009, 8,22,   1430, 9, 1 },
   3079   { 2009, 9,20,   1430,10, 1 },
   3080   { 2009,10,20,   1430,11, 1 },
   3081   { 2009,11,18,   1430,12, 1 },
   3082   { 2009,12,18,   1431, 1, 1 },
   3083   { 2010, 1,16,   1431, 2, 1 },
   3084   { 2010, 2,15,   1431, 3, 1 },
   3085   { 2010, 3,17,   1431, 4, 1 },
   3086   { 2010, 4,15,   1431, 5, 1 },
   3087   { 2010, 5,15,   1431, 6, 1 },
   3088   { 2010, 6,13,   1431, 7, 1 },
   3089   { 2010, 7,13,   1431, 8, 1 },
   3090   { 2010, 8,11,   1431, 9, 1 },
   3091   { 2010, 9,10,   1431,10, 1 },
   3092   { 2010,10, 9,   1431,11, 1 },
   3093   { 2010,11, 7,   1431,12, 1 },
   3094   { 2010,12, 7,   1432, 1, 1 },
   3095   { 2011, 1, 5,   1432, 2, 1 },
   3096   { 2011, 2, 4,   1432, 3, 1 },
   3097   { 2011, 3, 6,   1432, 4, 1 },
   3098   { 2011, 4, 5,   1432, 5, 1 },
   3099   { 2011, 5, 4,   1432, 6, 1 },
   3100   { 2011, 6, 3,   1432, 7, 1 },
   3101   { 2011, 7, 2,   1432, 8, 1 },
   3102   { 2011, 8, 1,   1432, 9, 1 },
   3103   { 2011, 8,30,   1432,10, 1 },
   3104   { 2011, 9,29,   1432,11, 1 },
   3105   { 2011,10,28,   1432,12, 1 },
   3106   { 2011,11,26,   1433, 1, 1 },
   3107   { 2011,12,26,   1433, 2, 1 },
   3108   { 2012, 1,24,   1433, 3, 1 },
   3109   { 2012, 2,23,   1433, 4, 1 },
   3110   { 2012, 3,24,   1433, 5, 1 },
   3111   { 2012, 4,22,   1433, 6, 1 },
   3112   { 2012, 5,22,   1433, 7, 1 },
   3113   { 2012, 6,21,   1433, 8, 1 },
   3114   { 2012, 7,20,   1433, 9, 1 },
   3115   { 2012, 8,19,   1433,10, 1 },
   3116   { 2012, 9,17,   1433,11, 1 },
   3117   { 2012,10,17,   1433,12, 1 },
   3118   { 2012,11,15,   1434, 1, 1 },
   3119   { 2012,12,14,   1434, 2, 1 },
   3120   { 2013, 1,13,   1434, 3, 1 },
   3121   { 2013, 2,11,   1434, 4, 1 },
   3122   { 2013, 3,13,   1434, 5, 1 },
   3123   { 2013, 4,11,   1434, 6, 1 },
   3124   { 2013, 5,11,   1434, 7, 1 },
   3125   { 2013, 6,10,   1434, 8, 1 },
   3126   { 2013, 7, 9,   1434, 9, 1 },
   3127   { 2013, 8, 8,   1434,10, 1 },
   3128   { 2013, 9, 7,   1434,11, 1 },
   3129   { 2013,10, 6,   1434,12, 1 },
   3130   { 2013,11, 4,   1435, 1, 1 },
   3131   { 2013,12, 4,   1435, 2, 1 },
   3132   { 2014, 1, 2,   1435, 3, 1 },
   3133   { 2014, 2, 1,   1435, 4, 1 },
   3134   { 2014, 3, 2,   1435, 5, 1 },
   3135   { 2014, 4, 1,   1435, 6, 1 },
   3136   { 2014, 4,30,   1435, 7, 1 },
   3137   { 2014, 5,30,   1435, 8, 1 },
   3138   { 2014, 6,28,   1435, 9, 1 },
   3139   { 2014, 7,28,   1435,10, 1 },
   3140   { 2014, 8,27,   1435,11, 1 },
   3141   { 2014, 9,25,   1435,12, 1 },
   3142   { 2014,10,25,   1436, 1, 1 },
   3143   { 2014,11,23,   1436, 2, 1 },
   3144   { 2014,12,23,   1436, 3, 1 },
   3145   { 2015, 1,21,   1436, 4, 1 },
   3146   { 2015, 2,20,   1436, 5, 1 },
   3147   { 2015, 3,21,   1436, 6, 1 },
   3148   { 2015, 4,20,   1436, 7, 1 },
   3149   { 2015, 5,19,   1436, 8, 1 },
   3150   { 2015, 6,18,   1436, 9, 1 },
   3151   { 2015, 7,17,   1436,10, 1 },
   3152   { 2015, 8,16,   1436,11, 1 },
   3153   { 2015, 9,14,   1436,12, 1 },
   3154   { 2015,10,14,   1437, 1, 1 },
   3155   { 2015,11,13,   1437, 2, 1 },
   3156   { 2015,12,12,   1437, 3, 1 },
   3157   { 2016, 1,11,   1437, 4, 1 },
   3158   { 2016, 2,10,   1437, 5, 1 },
   3159   { 2016, 3,10,   1437, 6, 1 },
   3160   { 2016, 4, 8,   1437, 7, 1 },
   3161   { 2016, 5, 8,   1437, 8, 1 },
   3162   { 2016, 6, 6,   1437, 9, 1 },
   3163   { 2016, 7, 6,   1437,10, 1 },
   3164   { 2016, 8, 4,   1437,11, 1 },
   3165   { 2016, 9, 2,   1437,12, 1 },
   3166   { 2016,10, 2,   1438, 1, 1 },
   3167   { 2016,11, 1,   1438, 2, 1 },
   3168   { 2016,11,30,   1438, 3, 1 },
   3169   { 2016,12,30,   1438, 4, 1 },
   3170   { 2017, 1,29,   1438, 5, 1 },
   3171   { 2017, 2,28,   1438, 6, 1 },
   3172   { 2017, 3,29,   1438, 7, 1 },
   3173   { 2017, 4,27,   1438, 8, 1 },
   3174   { 2017, 5,27,   1438, 9, 1 },
   3175   { 2017, 6,25,   1438,10, 1 },
   3176   { 2017, 7,24,   1438,11, 1 },
   3177   { 2017, 8,23,   1438,12, 1 },
   3178   { 2017, 9,21,   1439, 1, 1 },
   3179   { 2017,10,21,   1439, 2, 1 },
   3180   { 2017,11,19,   1439, 3, 1 },
   3181   { 2017,12,19,   1439, 4, 1 },
   3182   { 2018, 1,18,   1439, 5, 1 },
   3183   { 2018, 2,17,   1439, 6, 1 },
   3184   { 2018, 3,18,   1439, 7, 1 },
   3185   { 2018, 4,17,   1439, 8, 1 },
   3186   { 2018, 5,16,   1439, 9, 1 },
   3187   { 2018, 6,15,   1439,10, 1 },
   3188   { 2018, 7,14,   1439,11, 1 },
   3189   { 2018, 8,12,   1439,12, 1 },
   3190   { 2018, 9,11,   1440, 1, 1 },
   3191   { 2019, 8,31,   1441, 1, 1 },
   3192   { 2020, 8,20,   1442, 1, 1 },
   3193   { 2021, 8, 9,   1443, 1, 1 },
   3194   { 2022, 7,30,   1444, 1, 1 },
   3195   { 2023, 7,19,   1445, 1, 1 },
   3196   { 2024, 7, 7,   1446, 1, 1 },
   3197   { 2025, 6,26,   1447, 1, 1 },
   3198   { 2026, 6,16,   1448, 1, 1 },
   3199   { 2027, 6, 6,   1449, 1, 1 },
   3200   { 2028, 5,25,   1450, 1, 1 },
   3201   { 2029, 5,14,   1451, 1, 1 },
   3202   { 2030, 5, 4,   1452, 1, 1 },
   3203   { 2031, 4,23,   1453, 1, 1 },
   3204   { 2032, 4,11,   1454, 1, 1 },
   3205   { 2033, 4, 1,   1455, 1, 1 },
   3206   { 2034, 3,22,   1456, 1, 1 },
   3207   { 2035, 3,11,   1457, 1, 1 },
   3208   { 2036, 2,29,   1458, 1, 1 },
   3209   { 2037, 2,17,   1459, 1, 1 },
   3210   { 2038, 2, 6,   1460, 1, 1 },
   3211   { 2039, 1,26,   1461, 1, 1 },
   3212   { 2040, 1,15,   1462, 1, 1 },
   3213   { 2041, 1, 4,   1463, 1, 1 },
   3214   { 2041,12,25,   1464, 1, 1 },
   3215   { 2042,12,14,   1465, 1, 1 },
   3216   { 2043,12, 3,   1466, 1, 1 },
   3217   { 2044,11,21,   1467, 1, 1 },
   3218   { 2045,11,11,   1468, 1, 1 },
   3219   { 2046,10,31,   1469, 1, 1 },
   3220   { 2047,10,21,   1470, 1, 1 },
   3221   { 2048,10, 9,   1471, 1, 1 },
   3222   { 2049, 9,29,   1472, 1, 1 },
   3223   { 2050, 9,18,   1473, 1, 1 },
   3224   { 2051, 9, 7,   1474, 1, 1 },
   3225   { 2052, 8,26,   1475, 1, 1 },
   3226   { 2053, 8,15,   1476, 1, 1 },
   3227   { 2054, 8, 5,   1477, 1, 1 },
   3228   { 2055, 7,26,   1478, 1, 1 },
   3229   { 2056, 7,14,   1479, 1, 1 },
   3230   { 2057, 7, 3,   1480, 1, 1 },
   3231   { 2058, 6,22,   1481, 1, 1 },
   3232   { 2059, 6,11,   1482, 1, 1 },
   3233   { 2061, 5,21,   1484, 1, 1 },
   3234   { 2063, 4,30,   1486, 1, 1 },
   3235   { 2065, 4, 7,   1488, 1, 1 },
   3236   { 2067, 3,17,   1490, 1, 1 },
   3237   { 2069, 2,23,   1492, 1, 1 },
   3238   { 2071, 2, 2,   1494, 1, 1 },
   3239   { 2073, 1,10,   1496, 1, 1 },
   3240   { 2074,12,20,   1498, 1, 1 },
   3241   { 2076,11,28,   1500, 1, 1 },
   3242   {    0, 0, 0,      0, 0, 0 }, // terminator
   3243 };
   3244 
   3245 static const UChar zoneSA[] = {0x41,0x73,0x69,0x61,0x2F,0x52,0x69,0x79,0x61,0x64,0x68,0}; // "Asia/Riyadh"
   3246 
   3247 void CalendarTest::TestIslamicUmAlQura() {
   3248 
   3249     UErrorCode status = U_ZERO_ERROR;
   3250     Locale umalquraLoc("ar_SA@calendar=islamic-umalqura");
   3251     Locale gregoLoc("ar_SA@calendar=gregorian");
   3252     TimeZone* tzSA = TimeZone::createTimeZone(UnicodeString(TRUE, zoneSA, -1));
   3253     Calendar* tstCal = Calendar::createInstance(*((const TimeZone *)tzSA), umalquraLoc, status);
   3254     Calendar* gregCal = Calendar::createInstance(*((const TimeZone *)tzSA), gregoLoc, status);
   3255 
   3256     IslamicCalendar* iCal = (IslamicCalendar*)tstCal;
   3257     if(strcmp(iCal->getType(), "islamic-umalqura") != 0) {
   3258         errln("wrong type of calendar created - %s", iCal->getType());
   3259     }
   3260 
   3261     int32_t firstYear = 1318;
   3262     int32_t lastYear = 1368;    // just enough to be pretty sure
   3263     //int32_t lastYear = 1480;    // the whole shootin' match
   3264 
   3265     tstCal->clear();
   3266     tstCal->setLenient(FALSE);
   3267 
   3268     int32_t day=0, month=0, year=0, initDay = 27, initMonth = IslamicCalendar::RAJAB, initYear = 1434;
   3269 
   3270     for( int32_t startYear = firstYear; startYear <= lastYear; startYear++) {
   3271         setAndTestWholeYear(tstCal, startYear, status);
   3272         status = U_ZERO_ERROR;
   3273     }
   3274 
   3275     initMonth = IslamicCalendar::RABI_2;
   3276     initDay = 5;
   3277     int32_t loopCnt = 25;
   3278     tstCal->clear();
   3279     setAndTestCalendar( tstCal, initMonth, initDay, initYear, status);
   3280     TEST_CHECK_STATUS;
   3281 
   3282     for(int x=1; x<=loopCnt; x++) {
   3283         day = tstCal->get(UCAL_DAY_OF_MONTH,status);
   3284         month = tstCal->get(UCAL_MONTH,status);
   3285         year = tstCal->get(UCAL_YEAR,status);
   3286         TEST_CHECK_STATUS;
   3287         tstCal->roll(UCAL_DAY_OF_MONTH, (UBool)TRUE, status);
   3288         TEST_CHECK_STATUS;
   3289     }
   3290 
   3291     if(day != (initDay + loopCnt - 1) || month != IslamicCalendar::RABI_2 || year != 1434)
   3292       errln("invalid values for RABI_2 date after roll of %d", loopCnt);
   3293 
   3294     status = U_ZERO_ERROR;
   3295     tstCal->clear();
   3296     initMonth = 2;
   3297     initDay = 30;
   3298     setAndTestCalendar( tstCal, initMonth, initDay, initYear, status);
   3299     if(U_SUCCESS(status)) {
   3300         errln("error NOT detected status %i",status);
   3301         errln("      init values:\tmonth %i\tday %i\tyear %i", initMonth, initDay, initYear);
   3302         int32_t day = tstCal->get(UCAL_DAY_OF_MONTH, status);
   3303         int32_t month = tstCal->get(UCAL_MONTH, status);
   3304         int32_t year = tstCal->get(UCAL_YEAR, status);
   3305         errln("values post set():\tmonth %i\tday %i\tyear %i",month, day, year);
   3306     }
   3307 
   3308     status = U_ZERO_ERROR;
   3309     tstCal->clear();
   3310     initMonth = 3;
   3311     initDay = 30;
   3312     setAndTestCalendar( tstCal, initMonth, initDay, initYear, status);
   3313     TEST_CHECK_STATUS;
   3314 
   3315     SimpleDateFormat* formatter = new SimpleDateFormat("yyyy-MM-dd", Locale::getUS(), status);
   3316     UDate date = formatter->parse("1975-05-06", status);
   3317     Calendar* is_cal = Calendar::createInstance(umalquraLoc, status);
   3318     is_cal->setTime(date, status);
   3319     int32_t is_day = is_cal->get(UCAL_DAY_OF_MONTH,status);
   3320     int32_t is_month = is_cal->get(UCAL_MONTH,status);
   3321     int32_t is_year = is_cal->get(UCAL_YEAR,status);
   3322     TEST_CHECK_STATUS;
   3323     if(is_day != 24 || is_month != IslamicCalendar::RABI_2 || is_year != 1395)
   3324         errln("unexpected conversion date month %i not %i or day %i not 24 or year %i not 1395", is_month, IslamicCalendar::RABI_2, is_day, is_year);
   3325 
   3326     UDate date2 = is_cal->getTime(status);
   3327     TEST_CHECK_STATUS;
   3328     if(date2 != date) {
   3329         errln("before(%f) and after(%f) dates don't match up!",date, date2);
   3330     }
   3331 
   3332     // check against data
   3333     const GregoUmmAlQuraMap* guMapPtr;
   3334     gregCal->clear();
   3335     tstCal->clear();
   3336     for (guMapPtr = guMappings; guMapPtr->gYear != 0; guMapPtr++) {
   3337         status = U_ZERO_ERROR;
   3338         gregCal->set(guMapPtr->gYear, guMapPtr->gMon - 1, guMapPtr->gDay, 12, 0);
   3339         date = gregCal->getTime(status);
   3340         tstCal->setTime(date, status);
   3341         int32_t uYear = tstCal->get(UCAL_YEAR, status);
   3342         int32_t uMon = tstCal->get(UCAL_MONTH, status) + 1;
   3343         int32_t uDay = tstCal->get(UCAL_DATE, status);
   3344         if(U_FAILURE(status)) {
   3345             errln("For gregorian %4d-%02d-%02d, get status %s",
   3346                     guMapPtr->gYear, guMapPtr->gMon, guMapPtr->gDay, u_errorName(status) );
   3347         } else if (uYear != guMapPtr->uYear || uMon != guMapPtr->uMon || uDay != guMapPtr->uDay) {
   3348             errln("For gregorian %4d-%02d-%02d, expect umalqura %4d-%02d-%02d, get %4d-%02d-%02d",
   3349                     guMapPtr->gYear, guMapPtr->gMon, guMapPtr->gDay,
   3350                     guMapPtr->uYear, guMapPtr->uMon, guMapPtr->uDay, uYear, uMon, uDay );
   3351         }
   3352     }
   3353 
   3354     delete is_cal;
   3355     delete formatter;
   3356     delete gregCal;
   3357     delete tstCal;
   3358     delete tzSA;
   3359 }
   3360 
   3361 void CalendarTest::TestIslamicTabularDates() {
   3362     UErrorCode status = U_ZERO_ERROR;
   3363     Locale islamicLoc("ar_SA@calendar=islamic-civil");
   3364     Locale tblaLoc("ar_SA@calendar=islamic-tbla");
   3365     SimpleDateFormat* formatter = new SimpleDateFormat("yyyy-MM-dd", Locale::getUS(), status);
   3366     UDate date = formatter->parse("1975-05-06", status);
   3367 
   3368     Calendar* tstCal = Calendar::createInstance(islamicLoc, status);
   3369     tstCal->setTime(date, status);
   3370     int32_t is_day = tstCal->get(UCAL_DAY_OF_MONTH,status);
   3371     int32_t is_month = tstCal->get(UCAL_MONTH,status);
   3372     int32_t is_year = tstCal->get(UCAL_YEAR,status);
   3373     TEST_CHECK_STATUS;
   3374     delete tstCal;
   3375 
   3376     tstCal = Calendar::createInstance(tblaLoc, status);
   3377     tstCal->setTime(date, status);
   3378     int32_t tbla_day = tstCal->get(UCAL_DAY_OF_MONTH,status);
   3379     int32_t tbla_month = tstCal->get(UCAL_MONTH,status);
   3380     int32_t tbla_year = tstCal->get(UCAL_YEAR,status);
   3381     TEST_CHECK_STATUS;
   3382 
   3383     if(tbla_month != is_month || tbla_year != is_year)
   3384         errln("unexpected difference between islamic and tbla month %d : %d and/or year %d : %d",tbla_month,is_month,tbla_year,is_year);
   3385 
   3386     if(tbla_day - is_day != 1)
   3387         errln("unexpected day difference between islamic and tbla: %d : %d ",tbla_day,is_day);
   3388     delete tstCal;
   3389     delete formatter;
   3390 }
   3391 
   3392 void CalendarTest::TestHebrewMonthValidation() {
   3393     UErrorCode status = U_ZERO_ERROR;
   3394     LocalPointer<Calendar>  cal(Calendar::createInstance(Locale::createFromName("he_IL@calendar=hebrew"), status));
   3395     if (failure(status, "Calendar::createInstance, locale:he_IL@calendar=hebrew", TRUE)) return;
   3396     Calendar *pCal = cal.getAlias();
   3397 
   3398     UDate d;
   3399     pCal->setLenient(FALSE);
   3400 
   3401     // 5776 is a leap year and has month Adar I
   3402     pCal->set(5776, HebrewCalendar::ADAR_1, 1);
   3403     d = pCal->getTime(status);
   3404     if (U_FAILURE(status)) {
   3405         errln("Fail: 5776 Adar I 1 is a valid date.");
   3406     }
   3407     status = U_ZERO_ERROR;
   3408 
   3409     // 5777 is NOT a lear year and does not have month Adar I
   3410     pCal->set(5777, HebrewCalendar::ADAR_1, 1);
   3411     d = pCal->getTime(status);
   3412     (void)d;
   3413     if (status == U_ILLEGAL_ARGUMENT_ERROR) {
   3414         logln("Info: U_ILLEGAL_ARGUMENT_ERROR, because 5777 Adar I 1 is not a valid date.");
   3415     } else {
   3416         errln("Fail: U_ILLEGAL_ARGUMENT_ERROR should be set for input date 5777 Adar I 1.");
   3417     }
   3418 }
   3419 
   3420 void CalendarTest::TestWeekData() {
   3421     // Each line contains two locales using the same set of week rule data.
   3422     const char* LOCALE_PAIRS[] = {
   3423         "en",       "en_US",
   3424         "de",       "de_DE",
   3425         "de_DE",    "en_DE",
   3426         "en_GB",    "und_GB",
   3427         "ar_EG",    "en_EG",
   3428         "ar_SA",    "fr_SA",
   3429         0
   3430     };
   3431 
   3432     UErrorCode status;
   3433 
   3434     for (int32_t i = 0; LOCALE_PAIRS[i] != 0; i += 2) {
   3435         status = U_ZERO_ERROR;
   3436         LocalPointer<Calendar>  cal1(Calendar::createInstance(LOCALE_PAIRS[i], status));
   3437         LocalPointer<Calendar>  cal2(Calendar::createInstance(LOCALE_PAIRS[i + 1], status));
   3438         TEST_CHECK_STATUS_LOCALE(LOCALE_PAIRS[i]);
   3439 
   3440         // First day of week
   3441         UCalendarDaysOfWeek dow1 = cal1->getFirstDayOfWeek(status);
   3442         UCalendarDaysOfWeek dow2 = cal2->getFirstDayOfWeek(status);
   3443         TEST_CHECK_STATUS;
   3444         TEST_ASSERT(dow1 == dow2);
   3445 
   3446         // Minimum days in first week
   3447         uint8_t minDays1 = cal1->getMinimalDaysInFirstWeek();
   3448         uint8_t minDays2 = cal2->getMinimalDaysInFirstWeek();
   3449         TEST_ASSERT(minDays1 == minDays2);
   3450 
   3451         // Weekdays and Weekends
   3452         for (int32_t d = UCAL_SUNDAY; d <= UCAL_SATURDAY; d++) {
   3453             status = U_ZERO_ERROR;
   3454             UCalendarWeekdayType wdt1 = cal1->getDayOfWeekType((UCalendarDaysOfWeek)d, status);
   3455             UCalendarWeekdayType wdt2 = cal2->getDayOfWeekType((UCalendarDaysOfWeek)d, status);
   3456             TEST_CHECK_STATUS;
   3457             TEST_ASSERT(wdt1 == wdt2);
   3458         }
   3459     }
   3460 }
   3461 
   3462 typedef struct {
   3463     const char* zone;
   3464     const CalFields base;
   3465     int32_t deltaDays;
   3466     UCalendarWallTimeOption skippedWTOpt;
   3467     const CalFields expected;
   3468 } TestAddAcrossZoneTransitionData;
   3469 
   3470 static const TestAddAcrossZoneTransitionData AAZTDATA[] =
   3471 {
   3472     // Time zone                Base wall time                      day(s)  Skipped time options
   3473     //                          Expected wall time
   3474 
   3475     // Add 1 day, from the date before DST transition
   3476     {"America/Los_Angeles",     CalFields(2014,3,8,1,59,59,999),    1,      UCAL_WALLTIME_FIRST,
   3477                                 CalFields(2014,3,9,1,59,59,999)},
   3478 
   3479     {"America/Los_Angeles",     CalFields(2014,3,8,1,59,59,999),    1,      UCAL_WALLTIME_LAST,
   3480                                 CalFields(2014,3,9,1,59,59,999)},
   3481 
   3482     {"America/Los_Angeles",     CalFields(2014,3,8,1,59,59,999),    1,      UCAL_WALLTIME_NEXT_VALID,
   3483                                 CalFields(2014,3,9,1,59,59,999)},
   3484 
   3485 
   3486     {"America/Los_Angeles",     CalFields(2014,3,8,2,0,0,0),        1,      UCAL_WALLTIME_FIRST,
   3487                                 CalFields(2014,3,9,1,0,0,0)},
   3488 
   3489     {"America/Los_Angeles",     CalFields(2014,3,8,2,0,0,0),        1,      UCAL_WALLTIME_LAST,
   3490                                 CalFields(2014,3,9,3,0,0,0)},
   3491 
   3492     {"America/Los_Angeles",     CalFields(2014,3,8,2,0,0,0),        1,      UCAL_WALLTIME_NEXT_VALID,
   3493                                 CalFields(2014,3,9,3,0,0,0)},
   3494 
   3495 
   3496     {"America/Los_Angeles",     CalFields(2014,3,8,2,30,0,0),       1,      UCAL_WALLTIME_FIRST,
   3497                                 CalFields(2014,3,9,1,30,0,0)},
   3498 
   3499     {"America/Los_Angeles",     CalFields(2014,3,8,2,30,0,0),       1,      UCAL_WALLTIME_LAST,
   3500                                 CalFields(2014,3,9,3,30,0,0)},
   3501 
   3502     {"America/Los_Angeles",     CalFields(2014,3,8,2,30,0,0),       1,      UCAL_WALLTIME_NEXT_VALID,
   3503                                 CalFields(2014,3,9,3,0,0,0)},
   3504 
   3505 
   3506     {"America/Los_Angeles",     CalFields(2014,3,8,3,0,0,0),        1,      UCAL_WALLTIME_FIRST,
   3507                                 CalFields(2014,3,9,3,0,0,0)},
   3508 
   3509     {"America/Los_Angeles",     CalFields(2014,3,8,3,0,0,0),        1,      UCAL_WALLTIME_LAST,
   3510                                 CalFields(2014,3,9,3,0,0,0)},
   3511 
   3512     {"America/Los_Angeles",     CalFields(2014,3,8,3,0,0,0),        1,      UCAL_WALLTIME_NEXT_VALID,
   3513                                 CalFields(2014,3,9,3,0,0,0)},
   3514 
   3515     // Subtract 1 day, from one day after DST transition
   3516     {"America/Los_Angeles",     CalFields(2014,3,10,1,59,59,999),   -1,     UCAL_WALLTIME_FIRST,
   3517                                 CalFields(2014,3,9,1,59,59,999)},
   3518 
   3519     {"America/Los_Angeles",     CalFields(2014,3,10,1,59,59,999),   -1,     UCAL_WALLTIME_LAST,
   3520                                 CalFields(2014,3,9,1,59,59,999)},
   3521 
   3522     {"America/Los_Angeles",     CalFields(2014,3,10,1,59,59,999),   -1,     UCAL_WALLTIME_NEXT_VALID,
   3523                                 CalFields(2014,3,9,1,59,59,999)},
   3524 
   3525 
   3526     {"America/Los_Angeles",     CalFields(2014,3,10,2,0,0,0),       -1,     UCAL_WALLTIME_FIRST,
   3527                                 CalFields(2014,3,9,1,0,0,0)},
   3528 
   3529     {"America/Los_Angeles",     CalFields(2014,3,10,2,0,0,0),       -1,     UCAL_WALLTIME_LAST,
   3530                                 CalFields(2014,3,9,3,0,0,0)},
   3531 
   3532     {"America/Los_Angeles",     CalFields(2014,3,10,2,0,0,0),       -1,     UCAL_WALLTIME_NEXT_VALID,
   3533                                 CalFields(2014,3,9,3,0,0,0)},
   3534 
   3535 
   3536     {"America/Los_Angeles",     CalFields(2014,3,10,2,30,0,0),      -1,     UCAL_WALLTIME_FIRST,
   3537                                 CalFields(2014,3,9,1,30,0,0)},
   3538 
   3539     {"America/Los_Angeles",     CalFields(2014,3,10,2,30,0,0),      -1,     UCAL_WALLTIME_LAST,
   3540                                 CalFields(2014,3,9,3,30,0,0)},
   3541 
   3542     {"America/Los_Angeles",     CalFields(2014,3,10,2,30,0,0),      -1,     UCAL_WALLTIME_NEXT_VALID,
   3543                                 CalFields(2014,3,9,3,0,0,0)},
   3544 
   3545 
   3546     {"America/Los_Angeles",     CalFields(2014,3,10,3,0,0,0),       -1,     UCAL_WALLTIME_FIRST,
   3547                                 CalFields(2014,3,9,3,0,0,0)},
   3548 
   3549     {"America/Los_Angeles",     CalFields(2014,3,10,3,0,0,0),       -1,     UCAL_WALLTIME_LAST,
   3550                                 CalFields(2014,3,9,3,0,0,0)},
   3551 
   3552     {"America/Los_Angeles",     CalFields(2014,3,10,3,0,0,0),       -1,     UCAL_WALLTIME_NEXT_VALID,
   3553                                 CalFields(2014,3,9,3,0,0,0)},
   3554 
   3555 
   3556     // Test case for ticket#10544
   3557     {"America/Santiago",        CalFields(2013,4,27,0,0,0,0),       134,    UCAL_WALLTIME_FIRST,
   3558                                 CalFields(2013,9,7,23,0,0,0)},
   3559 
   3560     {"America/Santiago",        CalFields(2013,4,27,0,0,0,0),       134,    UCAL_WALLTIME_LAST,
   3561                                 CalFields(2013,9,8,1,0,0,0)},
   3562 
   3563     {"America/Santiago",        CalFields(2013,4,27,0,0,0,0),       134,    UCAL_WALLTIME_NEXT_VALID,
   3564                                 CalFields(2013,9,8,1,0,0,0)},
   3565 
   3566 
   3567     {"America/Santiago",        CalFields(2013,4,27,0,30,0,0),      134,    UCAL_WALLTIME_FIRST,
   3568                                 CalFields(2013,9,7,23,30,0,0)},
   3569 
   3570     {"America/Santiago",        CalFields(2013,4,27,0,30,0,0),      134,    UCAL_WALLTIME_LAST,
   3571                                 CalFields(2013,9,8,1,30,0,0)},
   3572 
   3573     {"America/Santiago",        CalFields(2013,4,27,0,30,0,0),      134,    UCAL_WALLTIME_NEXT_VALID,
   3574                                 CalFields(2013,9,8,1,0,0,0)},
   3575 
   3576 
   3577     // Extreme transition - Pacific/Apia completely skips 2011-12-30
   3578     {"Pacific/Apia",            CalFields(2011,12,29,0,0,0,0),      1,      UCAL_WALLTIME_FIRST,
   3579                                 CalFields(2011,12,31,0,0,0,0)},
   3580 
   3581     {"Pacific/Apia",            CalFields(2011,12,29,0,0,0,0),      1,      UCAL_WALLTIME_LAST,
   3582                                 CalFields(2011,12,31,0,0,0,0)},
   3583 
   3584     {"Pacific/Apia",            CalFields(2011,12,29,0,0,0,0),      1,      UCAL_WALLTIME_NEXT_VALID,
   3585                                 CalFields(2011,12,31,0,0,0,0)},
   3586 
   3587 
   3588     {"Pacific/Apia",            CalFields(2011,12,31,12,0,0,0),     -1,     UCAL_WALLTIME_FIRST,
   3589                                 CalFields(2011,12,29,12,0,0,0)},
   3590 
   3591     {"Pacific/Apia",            CalFields(2011,12,31,12,0,0,0),     -1,     UCAL_WALLTIME_LAST,
   3592                                 CalFields(2011,12,29,12,0,0,0)},
   3593 
   3594     {"Pacific/Apia",            CalFields(2011,12,31,12,0,0,0),     -1,     UCAL_WALLTIME_NEXT_VALID,
   3595                                 CalFields(2011,12,29,12,0,0,0)},
   3596 
   3597 
   3598     // 30 minutes DST - Australia/Lord_Howe
   3599     {"Australia/Lord_Howe",     CalFields(2013,10,5,2,15,0,0),      1,      UCAL_WALLTIME_FIRST,
   3600                                 CalFields(2013,10,6,1,45,0,0)},
   3601 
   3602     {"Australia/Lord_Howe",     CalFields(2013,10,5,2,15,0,0),      1,      UCAL_WALLTIME_LAST,
   3603                                 CalFields(2013,10,6,2,45,0,0)},
   3604 
   3605     {"Australia/Lord_Howe",     CalFields(2013,10,5,2,15,0,0),      1,      UCAL_WALLTIME_NEXT_VALID,
   3606                                 CalFields(2013,10,6,2,30,0,0)},
   3607 
   3608     {NULL, CalFields(0,0,0,0,0,0,0), 0, UCAL_WALLTIME_LAST, CalFields(0,0,0,0,0,0,0)}
   3609 };
   3610 
   3611 void CalendarTest::TestAddAcrossZoneTransition() {
   3612     UErrorCode status = U_ZERO_ERROR;
   3613     GregorianCalendar cal(status);
   3614     TEST_CHECK_STATUS;
   3615 
   3616     for (int32_t i = 0; AAZTDATA[i].zone; i++) {
   3617         status = U_ZERO_ERROR;
   3618         TimeZone *tz = TimeZone::createTimeZone(AAZTDATA[i].zone);
   3619         cal.adoptTimeZone(tz);
   3620         cal.setSkippedWallTimeOption(AAZTDATA[i].skippedWTOpt);
   3621         AAZTDATA[i].base.setTo(cal);
   3622         cal.add(UCAL_DATE, AAZTDATA[i].deltaDays, status);
   3623         TEST_CHECK_STATUS;
   3624 
   3625         if (!AAZTDATA[i].expected.isEquivalentTo(cal, status)) {
   3626             CalFields res(cal, status);
   3627             TEST_CHECK_STATUS;
   3628             char buf[32];
   3629             const char *optDisp = AAZTDATA[i].skippedWTOpt == UCAL_WALLTIME_FIRST ? "FIRST" :
   3630                     AAZTDATA[i].skippedWTOpt == UCAL_WALLTIME_LAST ? "LAST" : "NEXT_VALID";
   3631             dataerrln(UnicodeString("Error: base:") + AAZTDATA[i].base.toString(buf, sizeof(buf)) + ", tz:" + AAZTDATA[i].zone
   3632                         + ", delta:" + AAZTDATA[i].deltaDays + " day(s), opt:" + optDisp
   3633                         + ", result:" + res.toString(buf, sizeof(buf))
   3634                         + " - expected:" + AAZTDATA[i].expected.toString(buf, sizeof(buf)));
   3635         }
   3636     }
   3637 }
   3638 
   3639 // Data in a separate file (Gregorian to Chinese lunar map)
   3640 #define INCLUDED_FROM_CALTEST_CPP
   3641 #include "caltestdata.h"
   3642 
   3643 void CalendarTest::TestChineseCalendarMapping() {
   3644     UErrorCode status = U_ZERO_ERROR;
   3645     LocalPointer<TimeZone> zone(TimeZone::createTimeZone(UnicodeString("China")));
   3646     Locale locEnCalGregory = Locale::createFromName("en@calendar=gregorian");
   3647     Locale locEnCalChinese = Locale::createFromName("en@calendar=chinese");
   3648     LocalPointer<Calendar>  calGregory(Calendar::createInstance(zone->clone(), locEnCalGregory, status));
   3649     LocalPointer<Calendar>  calChinese(Calendar::createInstance(zone.orphan(), locEnCalChinese, status));
   3650     if ( U_FAILURE(status) ) {
   3651         errln("Fail: Calendar::createInstance fails for en with calendar=gregorian or calendar=chinese: %s", u_errorName(status));
   3652     } else {
   3653         const GregoToLunar * mapPtr = gregoToLunar; // in "caltestdata.h" included above
   3654         calGregory->clear();
   3655         calChinese->clear();
   3656         for (; mapPtr->gyr != 0; mapPtr++) {
   3657             status = U_ZERO_ERROR;
   3658             calGregory->set(mapPtr->gyr, mapPtr->gmo - 1, mapPtr->gda, 8, 0);
   3659             UDate date = calGregory->getTime(status);
   3660             calChinese->setTime(date, status);
   3661             if ( U_FAILURE(status) ) {
   3662                 errln("Fail: for Gregorian %4d-%02d-%02d, calGregory->getTime or calChinese->setTime reports: %s",
   3663                         mapPtr->gyr, mapPtr->gmo, mapPtr->gda, u_errorName(status));
   3664                 continue;
   3665             }
   3666             int32_t era = calChinese->get(UCAL_ERA, status);
   3667             int32_t yr  = calChinese->get(UCAL_YEAR, status);
   3668             int32_t mo  = calChinese->get(UCAL_MONTH, status) + 1;
   3669             int32_t lp  = calChinese->get(UCAL_IS_LEAP_MONTH, status);
   3670             int32_t da  = calChinese->get(UCAL_DATE, status);
   3671             if ( U_FAILURE(status) ) {
   3672                 errln("Fail: for Gregorian %4d-%02d-%02d, calChinese->get (for era, yr, mo, leapmo, da) reports: %s",
   3673                         mapPtr->gyr, mapPtr->gmo, mapPtr->gda, u_errorName(status));
   3674                 continue;
   3675             }
   3676             if (yr != mapPtr->cyr || mo != mapPtr->cmo || lp != mapPtr->clp || da != mapPtr->cda) {
   3677                 errln("Fail: for Gregorian %4d-%02d-%02d, expected Chinese %2d-%02d(%d)-%02d, got %2d-%02d(%d)-%02d",
   3678                         mapPtr->gyr, mapPtr->gmo, mapPtr->gda, mapPtr->cyr, mapPtr->cmo, mapPtr->clp, mapPtr->cda, yr, mo, lp, da);
   3679                 continue;
   3680             }
   3681             // If Grego->Chinese worked, try reverse mapping
   3682             calChinese->set(UCAL_ERA, era);
   3683             calChinese->set(UCAL_YEAR, mapPtr->cyr);
   3684             calChinese->set(UCAL_MONTH, mapPtr->cmo - 1);
   3685             calChinese->set(UCAL_IS_LEAP_MONTH, mapPtr->clp);
   3686             calChinese->set(UCAL_DATE, mapPtr->cda);
   3687             calChinese->set(UCAL_HOUR_OF_DAY, 8);
   3688             date = calChinese->getTime(status);
   3689             calGregory->setTime(date, status);
   3690             if ( U_FAILURE(status) ) {
   3691                 errln("Fail: for Chinese %2d-%02d(%d)-%02d, calChinese->getTime or calGregory->setTime reports: %s",
   3692                         mapPtr->cyr, mapPtr->cmo, mapPtr->clp, mapPtr->cda, u_errorName(status));
   3693                 continue;
   3694             }
   3695             yr  = calGregory->get(UCAL_YEAR, status);
   3696             mo  = calGregory->get(UCAL_MONTH, status) + 1;
   3697             da  = calGregory->get(UCAL_DATE, status);
   3698             if ( U_FAILURE(status) ) {
   3699                 errln("Fail: for Chinese %2d-%02d(%d)-%02d, calGregory->get (for yr, mo, da) reports: %s",
   3700                         mapPtr->cyr, mapPtr->cmo, mapPtr->clp, mapPtr->cda, u_errorName(status));
   3701                 continue;
   3702             }
   3703             if (yr != mapPtr->gyr || mo != mapPtr->gmo || da != mapPtr->gda) {
   3704                 errln("Fail: for Chinese %2d-%02d(%d)-%02d, Gregorian %4d-%02d-%02d, got %4d-%02d-%02d",
   3705                         mapPtr->cyr, mapPtr->cmo, mapPtr->clp, mapPtr->cda, mapPtr->gyr, mapPtr->gmo, mapPtr->gda, yr, mo, da);
   3706                 continue;
   3707             }
   3708         }
   3709     }
   3710 }
   3711 
   3712 #endif /* #if !UCONFIG_NO_FORMATTING */
   3713 
   3714 //eof
   3715