Home | History | Annotate | Download | only in intltest
      1 // Copyright (C) 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-2014, International Business Machines Corporation
      6  * and others. All Rights Reserved.
      7  ***********************************************************************/
      8 
      9 /* Test Internationalized Calendars for C++ */
     10 
     11 #include "unicode/utypes.h"
     12 #include "string.h"
     13 #include "unicode/locid.h"
     14 #include "japancal.h"
     15 
     16 #if !UCONFIG_NO_FORMATTING
     17 
     18 #include <stdio.h>
     19 #include "caltest.h"
     20 
     21 #define CHECK(status, msg) \
     22     if (U_FAILURE(status)) { \
     23       dataerrln((UnicodeString(u_errorName(status)) + UnicodeString(" : " ) )+ msg); \
     24         return; \
     25     }
     26 
     27 
     28 static UnicodeString escape( const UnicodeString&src)
     29 {
     30   UnicodeString dst;
     31     dst.remove();
     32     for (int32_t i = 0; i < src.length(); ++i) {
     33         UChar c = src[i];
     34         if(c < 0x0080)
     35             dst += c;
     36         else {
     37             dst += UnicodeString("[");
     38             char buf [8];
     39             sprintf(buf, "%#x", c);
     40             dst += UnicodeString(buf);
     41             dst += UnicodeString("]");
     42         }
     43     }
     44 
     45     return dst;
     46 }
     47 
     48 
     49 #include "incaltst.h"
     50 #include "unicode/gregocal.h"
     51 #include "unicode/smpdtfmt.h"
     52 #include "unicode/simpletz.h"
     53 
     54 // *****************************************************************************
     55 // class IntlCalendarTest
     56 // *****************************************************************************
     57 //--- move to CalendarTest?
     58 
     59 // Turn this on to dump the calendar fields
     60 #define U_DEBUG_DUMPCALS
     61 
     62 
     63 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
     64 
     65 
     66 void IntlCalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
     67 {
     68     if (exec) logln("TestSuite IntlCalendarTest");
     69     switch (index) {
     70     CASE(0,TestTypes);
     71     CASE(1,TestGregorian);
     72     CASE(2,TestBuddhist);
     73     CASE(3,TestJapanese);
     74     CASE(4,TestBuddhistFormat);
     75     CASE(5,TestJapaneseFormat);
     76     CASE(6,TestJapanese3860);
     77     CASE(7,TestPersian);
     78     CASE(8,TestPersianFormat);
     79     CASE(9,TestTaiwan);
     80     default: name = ""; break;
     81     }
     82 }
     83 
     84 #undef CASE
     85 
     86 // ---------------------------------------------------------------------------------
     87 
     88 
     89 /**
     90  * Test various API methods for API completeness.
     91  */
     92 void
     93 IntlCalendarTest::TestTypes()
     94 {
     95   Calendar *c = NULL;
     96   UErrorCode status = U_ZERO_ERROR;
     97   int j;
     98   const char *locs [40] = { "en_US_VALLEYGIRL",
     99                             "en_US_VALLEYGIRL@collation=phonebook;calendar=japanese",
    100                             "en_US_VALLEYGIRL@collation=phonebook;calendar=gregorian",
    101                             "ja_JP@calendar=japanese",
    102                             "th_TH@calendar=buddhist",
    103                             "ja_JP_TRADITIONAL",
    104                             "th_TH_TRADITIONAL",
    105                             "th_TH_TRADITIONAL@calendar=gregorian",
    106                             "en_US",
    107                             "th_TH",    // Default calendar for th_TH is buddhist
    108                             "th",       // th's default region is TH and buddhist is used as default for TH
    109                             "en_TH",    // Default calendar for any locales with region TH is buddhist
    110                             "en-TH-u-ca-gregory",
    111                             NULL };
    112   const char *types[40] = { "gregorian",
    113                             "japanese",
    114                             "gregorian",
    115                             "japanese",
    116                             "buddhist",
    117                             "japanese",
    118                             "buddhist",
    119                             "gregorian",
    120                             "gregorian",
    121                             "gregorian",  // android-changed.  "buddhist",
    122                             "gregorian",  // android-changed.  "buddhist",
    123                             "gregorian",  // android-changed.  "buddhist",
    124                             "gregorian",
    125                             NULL };
    126 
    127   for(j=0;locs[j];j++) {
    128     logln(UnicodeString("Creating calendar of locale ")  + locs[j]);
    129     status = U_ZERO_ERROR;
    130     c = Calendar::createInstance(locs[j], status);
    131     CHECK(status, "creating '" + UnicodeString(locs[j]) + "' calendar");
    132     if(U_SUCCESS(status)) {
    133       logln(UnicodeString(" type is ") + c->getType());
    134       if(strcmp(c->getType(), types[j])) {
    135         dataerrln(UnicodeString(locs[j]) + UnicodeString("Calendar type ") + c->getType() + " instead of " + types[j]);
    136       }
    137     }
    138     delete c;
    139   }
    140 }
    141 
    142 
    143 
    144 /**
    145  * Run a test of a quasi-Gregorian calendar.  This is a calendar
    146  * that behaves like a Gregorian but has different year/era mappings.
    147  * The int[] data array should have the format:
    148  *
    149  * { era, year, gregorianYear, month, dayOfMonth, ...  ... , -1 }
    150  */
    151 void IntlCalendarTest::quasiGregorianTest(Calendar& cal, const Locale& gcl, const int32_t *data) {
    152   UErrorCode status = U_ZERO_ERROR;
    153   // As of JDK 1.4.1_01, using the Sun JDK GregorianCalendar as
    154   // a reference throws us off by one hour.  This is most likely
    155   // due to the JDK 1.4 incorporation of historical time zones.
    156   //java.util.Calendar grego = java.util.Calendar.getInstance();
    157   Calendar *grego = Calendar::createInstance(gcl, status);
    158   if (U_FAILURE(status)) {
    159     dataerrln("Error calling Calendar::createInstance");
    160     return;
    161   }
    162 
    163   int32_t tz1 = cal.get(UCAL_ZONE_OFFSET,status);
    164   int32_t tz2 = grego -> get (UCAL_ZONE_OFFSET, status);
    165   if(tz1 != tz2) {
    166     errln((UnicodeString)"cal's tz " + tz1 + " != grego's tz " + tz2);
    167   }
    168 
    169   for (int32_t i=0; data[i]!=-1; ) {
    170     int32_t era = data[i++];
    171     int32_t year = data[i++];
    172     int32_t gregorianYear = data[i++];
    173     int32_t month = data[i++];
    174     int32_t dayOfMonth = data[i++];
    175 
    176     grego->clear();
    177     grego->set(gregorianYear, month, dayOfMonth);
    178     UDate D = grego->getTime(status);
    179 
    180     cal.clear();
    181     cal.set(UCAL_ERA, era);
    182     cal.set(year, month, dayOfMonth);
    183     UDate d = cal.getTime(status);
    184 #ifdef U_DEBUG_DUMPCALS
    185     logln((UnicodeString)"cal  : " + CalendarTest::calToStr(cal));
    186     logln((UnicodeString)"grego: " + CalendarTest::calToStr(*grego));
    187 #endif
    188     if (d == D) {
    189       logln(UnicodeString("OK: ") + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
    190             " => " + d + " (" + UnicodeString(cal.getType()) + ")");
    191     } else {
    192       errln(UnicodeString("Fail: (fields to millis)") + era + ":" + year + "/" + (month+1) + "/" + dayOfMonth +
    193             " => " + d + ", expected " + D + " (" + UnicodeString(cal.getType()) + "Off by: " + (d-D));
    194     }
    195 
    196     // Now, set the gregorian millis on the other calendar
    197     cal.clear();
    198     cal.setTime(D, status);
    199     int e = cal.get(UCAL_ERA, status);
    200     int y = cal.get(UCAL_YEAR, status);
    201 #ifdef U_DEBUG_DUMPCALS
    202     logln((UnicodeString)"cal  : " + CalendarTest::calToStr(cal));
    203     logln((UnicodeString)"grego: " + CalendarTest::calToStr(*grego));
    204 #endif
    205     if (y == year && e == era) {
    206       logln((UnicodeString)"OK: " + D + " => " + cal.get(UCAL_ERA, status) + ":" +
    207             cal.get(UCAL_YEAR, status) + "/" +
    208             (cal.get(UCAL_MONTH, status)+1) + "/" + cal.get(UCAL_DATE, status) +  " (" + UnicodeString(cal.getType()) + ")");
    209     } else {
    210       errln((UnicodeString)"Fail: (millis to fields)" + D + " => " + cal.get(UCAL_ERA, status) + ":" +
    211             cal.get(UCAL_YEAR, status) + "/" +
    212             (cal.get(UCAL_MONTH, status)+1) + "/" + cal.get(UCAL_DATE, status) +
    213             ", expected " + era + ":" + year + "/" + (month+1) + "/" +
    214             dayOfMonth +  " (" + UnicodeString(cal.getType()));
    215     }
    216   }
    217   delete grego;
    218   CHECK(status, "err during quasiGregorianTest()");
    219 }
    220 
    221 // Verify that Gregorian works like Gregorian
    222 void IntlCalendarTest::TestGregorian() {
    223     UDate timeA = Calendar::getNow();
    224     int32_t data[] = {
    225         GregorianCalendar::AD, 1868, 1868, UCAL_SEPTEMBER, 8,
    226         GregorianCalendar::AD, 1868, 1868, UCAL_SEPTEMBER, 9,
    227         GregorianCalendar::AD, 1869, 1869, UCAL_JUNE, 4,
    228         GregorianCalendar::AD, 1912, 1912, UCAL_JULY, 29,
    229         GregorianCalendar::AD, 1912, 1912, UCAL_JULY, 30,
    230         GregorianCalendar::AD, 1912, 1912, UCAL_AUGUST, 1,
    231         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    232     };
    233 
    234     Calendar *cal;
    235     UErrorCode status = U_ZERO_ERROR;
    236     cal = Calendar::createInstance(/*"de_DE", */ status);
    237     CHECK(status, UnicodeString("Creating de_CH calendar"));
    238     // Sanity check the calendar
    239     UDate timeB = Calendar::getNow();
    240     UDate timeCal = cal->getTime(status);
    241 
    242     if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
    243       errln((UnicodeString)"Error: Calendar time " + timeCal +
    244             " is not within sampled times [" + timeA + " to " + timeB + "]!");
    245     }
    246     // end sanity check
    247 
    248     // Note, the following is a good way to test the sanity of the constructed calendars,
    249     // using Collation as a delay-loop:
    250     //
    251     // $ intltest  format/IntlCalendarTest  collate/G7CollationTest format/IntlCalendarTest
    252 
    253     quasiGregorianTest(*cal,Locale("fr_FR"),data);
    254     delete cal;
    255 }
    256 
    257 /**
    258  * Verify that BuddhistCalendar shifts years to Buddhist Era but otherwise
    259  * behaves like GregorianCalendar.
    260  */
    261 void IntlCalendarTest::TestBuddhist() {
    262     // BE 2542 == 1999 CE
    263     UDate timeA = Calendar::getNow();
    264 
    265     int32_t data[] = {
    266         0,           // B. era   [928479600000]
    267         2542,        // B. year
    268         1999,        // G. year
    269         UCAL_JUNE,   // month
    270         4,           // day
    271 
    272         0,           // B. era   [-79204842000000]
    273         3,           // B. year
    274         -540,        // G. year
    275         UCAL_FEBRUARY, // month
    276         12,          // day
    277 
    278         0,           // test month calculation:  4795 BE = 4252 AD is a leap year, but 4795 AD is not.
    279         4795,        // BE [72018057600000]
    280         4252,        // AD
    281         UCAL_FEBRUARY,
    282         29,
    283 
    284         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    285     };
    286     Calendar *cal;
    287     UErrorCode status = U_ZERO_ERROR;
    288     cal = Calendar::createInstance("th_TH@calendar=buddhist", status);
    289     CHECK(status, UnicodeString("Creating th_TH@calendar=buddhist calendar"));
    290 
    291     // Sanity check the calendar
    292     UDate timeB = Calendar::getNow();
    293     UDate timeCal = cal->getTime(status);
    294 
    295     if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
    296       errln((UnicodeString)"Error: Calendar time " + timeCal +
    297             " is not within sampled times [" + timeA + " to " + timeB + "]!");
    298     }
    299     // end sanity check
    300 
    301 
    302     quasiGregorianTest(*cal,Locale("th_TH@calendar=gregorian"),data);
    303     delete cal;
    304 }
    305 
    306 
    307 /**
    308  * Verify that TaiWanCalendar shifts years to Minguo Era but otherwise
    309  * behaves like GregorianCalendar.
    310  */
    311 void IntlCalendarTest::TestTaiwan() {
    312     // MG 1 == 1912 AD
    313     UDate timeA = Calendar::getNow();
    314 
    315     // TODO port these to the data items
    316     int32_t data[] = {
    317         1,           // B. era   [928479600000]
    318         1,        // B. year
    319         1912,        // G. year
    320         UCAL_JUNE,   // month
    321         4,           // day
    322 
    323         1,           // B. era   [-79204842000000]
    324         3,           // B. year
    325         1914,        // G. year
    326         UCAL_FEBRUARY, // month
    327         12,          // day
    328 
    329         1,           // B. era   [-79204842000000]
    330         96,           // B. year
    331         2007,        // G. year
    332         UCAL_FEBRUARY, // month
    333         12,          // day
    334 
    335         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    336     };
    337     Calendar *cal;
    338     UErrorCode status = U_ZERO_ERROR;
    339     cal = Calendar::createInstance("en_US@calendar=roc", status);
    340     CHECK(status, UnicodeString("Creating en_US@calendar=roc calendar"));
    341 
    342     // Sanity check the calendar
    343     UDate timeB = Calendar::getNow();
    344     UDate timeCal = cal->getTime(status);
    345 
    346     if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
    347       errln((UnicodeString)"Error: Calendar time " + timeCal +
    348             " is not within sampled times [" + timeA + " to " + timeB + "]!");
    349     }
    350     // end sanity check
    351 
    352 
    353     quasiGregorianTest(*cal,Locale("en_US"),data);
    354     delete cal;
    355 }
    356 
    357 
    358 
    359 /**
    360  * Verify that JapaneseCalendar shifts years to Japanese Eras but otherwise
    361  * behaves like GregorianCalendar.
    362  */
    363 void IntlCalendarTest::TestJapanese() {
    364     UDate timeA = Calendar::getNow();
    365 
    366     /* Sorry.. japancal.h is private! */
    367 #define JapaneseCalendar_MEIJI  232
    368 #define JapaneseCalendar_TAISHO 233
    369 #define JapaneseCalendar_SHOWA  234
    370 #define JapaneseCalendar_HEISEI 235
    371 
    372     // BE 2542 == 1999 CE
    373     int32_t data[] = {
    374         //       Jera         Jyr  Gyear   m             d
    375         JapaneseCalendar_MEIJI, 1, 1868, UCAL_SEPTEMBER, 8,
    376         JapaneseCalendar_MEIJI, 1, 1868, UCAL_SEPTEMBER, 9,
    377         JapaneseCalendar_MEIJI, 2, 1869, UCAL_JUNE, 4,
    378         JapaneseCalendar_MEIJI, 45, 1912, UCAL_JULY, 29,
    379         JapaneseCalendar_TAISHO, 1, 1912, UCAL_JULY, 30,
    380         JapaneseCalendar_TAISHO, 1, 1912, UCAL_AUGUST, 1,
    381 
    382         // new tests (not in java)
    383         JapaneseCalendar_SHOWA,     64,   1989,  UCAL_JANUARY, 7,  // Test current era transition (different code path than others)
    384         JapaneseCalendar_HEISEI,    1,   1989,  UCAL_JANUARY, 8,
    385         JapaneseCalendar_HEISEI,    1,   1989,  UCAL_JANUARY, 9,
    386         JapaneseCalendar_HEISEI,    1,   1989,  UCAL_DECEMBER, 20,
    387         JapaneseCalendar_HEISEI,  15,  2003,  UCAL_MAY, 22,
    388         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    389     };
    390 
    391     Calendar *cal;
    392     UErrorCode status = U_ZERO_ERROR;
    393     cal = Calendar::createInstance("ja_JP@calendar=japanese", status);
    394     CHECK(status, UnicodeString("Creating ja_JP@calendar=japanese calendar"));
    395     // Sanity check the calendar
    396     UDate timeB = Calendar::getNow();
    397     UDate timeCal = cal->getTime(status);
    398 
    399     if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
    400       errln((UnicodeString)"Error: Calendar time " + timeCal +
    401             " is not within sampled times [" + timeA + " to " + timeB + "]!");
    402     }
    403     // end sanity check
    404     quasiGregorianTest(*cal,Locale("ja_JP"),data);
    405     delete cal;
    406 }
    407 
    408 
    409 
    410 void IntlCalendarTest::TestBuddhistFormat() {
    411     UErrorCode status = U_ZERO_ERROR;
    412 
    413     // Test simple parse/format with adopt
    414 
    415     // First, a contrived english test..
    416     UDate aDate = 999932400000.0;
    417     SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=buddhist"), status);
    418     CHECK(status, "creating date format instance");
    419     SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status);
    420     CHECK(status, "creating gregorian date format instance");
    421     if(!fmt) {
    422         errln("Coudln't create en_US instance");
    423     } else {
    424         UnicodeString str;
    425         fmt2->format(aDate, str);
    426         logln(UnicodeString() + "Test Date: " + str);
    427         str.remove();
    428         fmt->format(aDate, str);
    429         logln(UnicodeString() + "as Buddhist Calendar: " + escape(str));
    430         UnicodeString expected("September 8, 2544 BE");
    431         if(str != expected) {
    432             errln("Expected " + escape(expected) + " but got " + escape(str));
    433         }
    434         UDate otherDate = fmt->parse(expected, status);
    435         if(otherDate != aDate) {
    436             UnicodeString str3;
    437             fmt->format(otherDate, str3);
    438             errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " +  otherDate + ", " + escape(str3));
    439         } else {
    440             logln("Parsed OK: " + expected);
    441         }
    442         delete fmt;
    443     }
    444     delete fmt2;
    445 
    446     CHECK(status, "Error occured testing Buddhist Calendar in English ");
    447 
    448     status = U_ZERO_ERROR;
    449     // Now, try in Thai
    450     {
    451         UnicodeString expect = CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
    452             " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e1e.\\u0e28. 2544");
    453         UDate         expectDate = 999932400000.0;
    454         Locale        loc("th_TH_TRADITIONAL"); // legacy
    455 
    456         simpleTest(loc, expect, expectDate, status);
    457     }
    458     status = U_ZERO_ERROR;
    459     {
    460         UnicodeString expect = CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
    461             " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e1e.\\u0e28. 2544");
    462         UDate         expectDate = 999932400000.0;
    463         Locale        loc("th_TH@calendar=buddhist");
    464 
    465         simpleTest(loc, expect, expectDate, status);
    466     }
    467     status = U_ZERO_ERROR;
    468     {
    469         UnicodeString expect = CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
    470             " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e04.\\u0e28. 2001");
    471         UDate         expectDate = 999932400000.0;
    472         Locale        loc("th_TH@calendar=gregorian");
    473 
    474         simpleTest(loc, expect, expectDate, status);
    475     }
    476     status = U_ZERO_ERROR;
    477     {
    478         UnicodeString expect = CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
    479             " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e04.\\u0e28. 2001");
    480         UDate         expectDate = 999932400000.0;
    481         Locale        loc("th_TH_TRADITIONAL@calendar=gregorian");
    482 
    483         simpleTest(loc, expect, expectDate, status);
    484     }
    485 }
    486 
    487 // TaiwanFormat has been moved to testdata/format.txt
    488 
    489 
    490 void IntlCalendarTest::TestJapaneseFormat() {
    491     Calendar *cal;
    492     UErrorCode status = U_ZERO_ERROR;
    493     cal = Calendar::createInstance("ja_JP_TRADITIONAL", status);
    494     CHECK(status, UnicodeString("Creating ja_JP_TRADITIONAL calendar"));
    495 
    496     Calendar *cal2 = cal->clone();
    497     delete cal;
    498     cal = NULL;
    499 
    500     // Test simple parse/format with adopt
    501 
    502     UDate aDate = 999932400000.0;
    503     SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yy G"), Locale("en_US@calendar=japanese"), status);
    504     SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status);
    505     CHECK(status, "creating date format instance");
    506     if(!fmt) {
    507         errln("Coudln't create en_US instance");
    508     } else {
    509         UnicodeString str;
    510         fmt2->format(aDate, str);
    511         logln(UnicodeString() + "Test Date: " + str);
    512         str.remove();
    513         fmt->format(aDate, str);
    514         logln(UnicodeString() + "as Japanese Calendar: " + str);
    515         UnicodeString expected("September 8, 13 Heisei");
    516         if(str != expected) {
    517             errln("Expected " + expected + " but got " + str);
    518         }
    519         UDate otherDate = fmt->parse(expected, status);
    520         if(otherDate != aDate) {
    521             UnicodeString str3;
    522             ParsePosition pp;
    523             fmt->parse(expected, *cal2, pp);
    524             fmt->format(otherDate, str3);
    525             errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " +  " = " +   otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) );
    526 
    527         } else {
    528             logln("Parsed OK: " + expected);
    529         }
    530         delete fmt;
    531     }
    532 
    533     // Test parse with incomplete information
    534     fmt = new SimpleDateFormat(UnicodeString("G y"), Locale("en_US@calendar=japanese"), status);
    535     aDate = -3197117222000.0;
    536     CHECK(status, "creating date format instance");
    537     if(!fmt) {
    538         errln("Coudln't create en_US instance");
    539     } else {
    540         UnicodeString str;
    541         fmt2->format(aDate, str);
    542         logln(UnicodeString() + "Test Date: " + str);
    543         str.remove();
    544         fmt->format(aDate, str);
    545         logln(UnicodeString() + "as Japanese Calendar: " + str);
    546         UnicodeString expected("Meiji 1");
    547         if(str != expected) {
    548             errln("Expected " + expected + " but got " + str);
    549         }
    550         UDate otherDate = fmt->parse(expected, status);
    551         if(otherDate != aDate) {
    552             UnicodeString str3;
    553             ParsePosition pp;
    554             fmt->parse(expected, *cal2, pp);
    555             fmt->format(otherDate, str3);
    556             errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " +  " = " +
    557                 otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) );
    558         } else {
    559             logln("Parsed OK: " + expected);
    560         }
    561         delete fmt;
    562     }
    563 
    564     delete cal2;
    565     delete fmt2;
    566     CHECK(status, "Error occured");
    567 
    568     // Now, try in Japanese
    569     {
    570         UnicodeString expect = CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5\\u571f\\u66dc\\u65e5");
    571         UDate         expectDate = 999932400000.0; // Testing a recent date
    572         Locale        loc("ja_JP@calendar=japanese");
    573 
    574         status = U_ZERO_ERROR;
    575         simpleTest(loc, expect, expectDate, status);
    576     }
    577     {
    578         UnicodeString expect = CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5\\u571f\\u66dc\\u65e5");
    579         UDate         expectDate = 999932400000.0; // Testing a recent date
    580         Locale        loc("ja_JP_TRADITIONAL"); // legacy
    581 
    582         status = U_ZERO_ERROR;
    583         simpleTest(loc, expect, expectDate, status);
    584     }
    585     {
    586         UnicodeString expect = CharsToUnicodeString("\\u5b89\\u6c385\\u5e747\\u67084\\u65e5\\u6728\\u66dc\\u65e5");
    587         UDate         expectDate = -6106032422000.0; // 1776-07-04T00:00:00Z-075258
    588         Locale        loc("ja_JP@calendar=japanese");
    589 
    590         status = U_ZERO_ERROR;
    591         simpleTest(loc, expect, expectDate, status);
    592 
    593     }
    594     {   // Jitterbug 1869 - this is an ambiguous era. (Showa 64 = Jan 6 1989, but Showa could be 2 other eras) )
    595         UnicodeString expect = CharsToUnicodeString("\\u662d\\u548c64\\u5e741\\u67086\\u65e5\\u91d1\\u66dc\\u65e5");
    596         UDate         expectDate = 600076800000.0;
    597         Locale        loc("ja_JP@calendar=japanese");
    598 
    599         status = U_ZERO_ERROR;
    600         simpleTest(loc, expect, expectDate, status);
    601 
    602     }
    603     {   // This Feb 29th falls on a leap year by gregorian year, but not by Japanese year.
    604         UnicodeString expect = CharsToUnicodeString("\\u5EB7\\u6B632\\u5e742\\u670829\\u65e5\\u65e5\\u66dc\\u65e5");
    605         UDate         expectDate =  -16214400422000.0;  // 1456-03-09T00:00Z-075258
    606         Locale        loc("ja_JP@calendar=japanese");
    607 
    608         status = U_ZERO_ERROR;
    609         simpleTest(loc, expect, expectDate, status);
    610 
    611     }
    612 }
    613 
    614 void IntlCalendarTest::TestJapanese3860()
    615 {
    616     Calendar *cal;
    617     UErrorCode status = U_ZERO_ERROR;
    618     cal = Calendar::createInstance("ja_JP@calendar=japanese", status);
    619     CHECK(status, UnicodeString("Creating ja_JP@calendar=japanese calendar"));
    620     Calendar *cal2 = cal->clone();
    621     SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("HH:mm:ss.S MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status);
    622     UnicodeString str;
    623 
    624 
    625     {
    626         // Test simple parse/format with adopt
    627         UDate aDate = 0;
    628 
    629         // Test parse with missing era (should default to current era, heisei)
    630         // Test parse with incomplete information
    631         logln("Testing parse w/ missing era...");
    632         SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("y.M.d"), Locale("ja_JP@calendar=japanese"), status);
    633         CHECK(status, "creating date format instance");
    634         if(!fmt) {
    635             errln("Coudln't create en_US instance");
    636         } else {
    637             UErrorCode s2 = U_ZERO_ERROR;
    638             cal2->clear();
    639             UnicodeString samplestr("1.1.9");
    640             logln(UnicodeString() + "Test Year: " + samplestr);
    641             aDate = fmt->parse(samplestr, s2);
    642             ParsePosition pp=0;
    643             fmt->parse(samplestr, *cal2, pp);
    644             CHECK(s2, "parsing the 1.1.9 string");
    645             logln("*cal2 after 119 parse:");
    646             str.remove();
    647             fmt2->format(aDate, str);
    648             logln(UnicodeString() + "as Gregorian Calendar: " + str);
    649 
    650             cal2->setTime(aDate, s2);
    651             int32_t gotYear = cal2->get(UCAL_YEAR, s2);
    652             int32_t gotEra = cal2->get(UCAL_ERA, s2);
    653             int32_t expectYear = 1;
    654             int32_t expectEra = JapaneseCalendar::getCurrentEra();
    655             if((gotYear!=1) || (gotEra != expectEra)) {
    656                 errln(UnicodeString("parse "+samplestr+" of 'y.m.d' as Japanese Calendar, expected year ") + expectYear +
    657                     UnicodeString(" and era ") + expectEra +", but got year " + gotYear + " and era " + gotEra + " (Gregorian:" + str +")");
    658             } else {
    659                 logln(UnicodeString() + " year: " + gotYear + ", era: " + gotEra);
    660             }
    661             delete fmt;
    662         }
    663     }
    664 
    665     {
    666         // Test simple parse/format with adopt
    667         UDate aDate = 0;
    668 
    669         // Test parse with missing era (should default to current era, heisei)
    670         // Test parse with incomplete information
    671         logln("Testing parse w/ just year...");
    672         SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("y"), Locale("ja_JP@calendar=japanese"), status);
    673         CHECK(status, "creating date format instance");
    674         if(!fmt) {
    675             errln("Coudln't create en_US instance");
    676         } else {
    677             UErrorCode s2 = U_ZERO_ERROR;
    678             cal2->clear();
    679             UnicodeString samplestr("1");
    680             logln(UnicodeString() + "Test Year: " + samplestr);
    681             aDate = fmt->parse(samplestr, s2);
    682             ParsePosition pp=0;
    683             fmt->parse(samplestr, *cal2, pp);
    684             CHECK(s2, "parsing the 1 string");
    685             logln("*cal2 after 1 parse:");
    686             str.remove();
    687             fmt2->format(aDate, str);
    688             logln(UnicodeString() + "as Gregorian Calendar: " + str);
    689 
    690             cal2->setTime(aDate, s2);
    691             int32_t gotYear = cal2->get(UCAL_YEAR, s2);
    692             int32_t gotEra = cal2->get(UCAL_ERA, s2);
    693             int32_t expectYear = 1;
    694             int32_t expectEra = 235; //JapaneseCalendar::kCurrentEra;
    695             if((gotYear!=1) || (gotEra != expectEra)) {
    696                 errln(UnicodeString("parse "+samplestr+" of 'y' as Japanese Calendar, expected year ") + expectYear +
    697                     UnicodeString(" and era ") + expectEra +", but got year " + gotYear + " and era " + gotEra + " (Gregorian:" + str +")");
    698             } else {
    699                 logln(UnicodeString() + " year: " + gotYear + ", era: " + gotEra);
    700             }
    701             delete fmt;
    702         }
    703     }
    704 
    705     delete cal2;
    706     delete cal;
    707     delete fmt2;
    708 }
    709 
    710 
    711 
    712 
    713 /**
    714  * Verify the Persian Calendar.
    715  */
    716 void IntlCalendarTest::TestPersian() {
    717     UDate timeA = Calendar::getNow();
    718 
    719     Calendar *cal;
    720     UErrorCode status = U_ZERO_ERROR;
    721     cal = Calendar::createInstance("fa_IR@calendar=persian", status);
    722     CHECK(status, UnicodeString("Creating fa_IR@calendar=persian calendar"));
    723     // Sanity check the calendar
    724     UDate timeB = Calendar::getNow();
    725     UDate timeCal = cal->getTime(status);
    726 
    727     if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
    728       errln((UnicodeString)"Error: Calendar time " + timeCal +
    729             " is not within sampled times [" + timeA + " to " + timeB + "]!");
    730     }
    731     // end sanity check
    732 
    733     // Test various dates to be sure of validity
    734     int32_t data[] = {
    735         1925, 4, 24, 1304, 2, 4,
    736         2011, 1, 11, 1389, 10, 21,
    737         1986, 2, 25, 1364, 12, 6,
    738         1934, 3, 14, 1312, 12, 23,
    739 
    740         2090, 3, 19, 1468, 12, 29,
    741         2007, 2, 22, 1385, 12, 3,
    742         1969, 12, 31, 1348, 10, 10,
    743         1945, 11, 12, 1324, 8, 21,
    744         1925, 3, 31, 1304, 1, 11,
    745 
    746         1996, 3, 19, 1374, 12, 29,
    747         1996, 3, 20, 1375, 1, 1,
    748         1997, 3, 20, 1375, 12, 30,
    749         1997, 3, 21, 1376, 1, 1,
    750 
    751         2008, 3, 19, 1386, 12, 29,
    752         2008, 3, 20, 1387, 1, 1,
    753         2004, 3, 19, 1382, 12, 29,
    754         2004, 3, 20, 1383, 1, 1,
    755 
    756         2006, 3, 20, 1384, 12, 29,
    757         2006, 3, 21, 1385, 1, 1,
    758 
    759         2005, 4, 20, 1384, 1, 31,
    760         2005, 4, 21, 1384, 2, 1,
    761         2005, 5, 21, 1384, 2, 31,
    762         2005, 5, 22, 1384, 3, 1,
    763         2005, 6, 21, 1384, 3, 31,
    764         2005, 6, 22, 1384, 4, 1,
    765         2005, 7, 22, 1384, 4, 31,
    766         2005, 7, 23, 1384, 5, 1,
    767         2005, 8, 22, 1384, 5, 31,
    768         2005, 8, 23, 1384, 6, 1,
    769         2005, 9, 22, 1384, 6, 31,
    770         2005, 9, 23, 1384, 7, 1,
    771         2005, 10, 22, 1384, 7, 30,
    772         2005, 10, 23, 1384, 8, 1,
    773         2005, 11, 21, 1384, 8, 30,
    774         2005, 11, 22, 1384, 9, 1,
    775         2005, 12, 21, 1384, 9, 30,
    776         2005, 12, 22, 1384, 10, 1,
    777         2006, 1, 20, 1384, 10, 30,
    778         2006, 1, 21, 1384, 11, 1,
    779         2006, 2, 19, 1384, 11, 30,
    780         2006, 2, 20, 1384, 12, 1,
    781         2006, 3, 20, 1384, 12, 29,
    782         2006, 3, 21, 1385, 1, 1,
    783 
    784         // The 2820-year cycle arithmetical algorithm would fail this one.
    785         2025, 3, 21, 1404, 1, 1,
    786 
    787         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    788     };
    789 
    790     Calendar *grego = Calendar::createInstance("fa_IR@calendar=gregorian", status);
    791     for (int32_t i=0; data[i]!=-1; ) {
    792         int32_t gregYear = data[i++];
    793         int32_t gregMonth = data[i++]-1;
    794         int32_t gregDay = data[i++];
    795         int32_t persYear = data[i++];
    796         int32_t persMonth = data[i++]-1;
    797         int32_t persDay = data[i++];
    798 
    799         // Test conversion from Persian dates
    800         grego->clear();
    801         grego->set(gregYear, gregMonth, gregDay);
    802 
    803         cal->clear();
    804         cal->set(persYear, persMonth, persDay);
    805 
    806         UDate persTime = cal->getTime(status);
    807         UDate gregTime = grego->getTime(status);
    808 
    809         if (persTime != gregTime) {
    810           errln(UnicodeString("Expected ") + gregTime + " but got " + persTime);
    811         }
    812 
    813         // Test conversion to Persian dates
    814         cal->clear();
    815         cal->setTime(gregTime, status);
    816 
    817         int32_t computedYear = cal->get(UCAL_YEAR, status);
    818         int32_t computedMonth = cal->get(UCAL_MONTH, status);
    819         int32_t computedDay = cal->get(UCAL_DATE, status);
    820 
    821         if ((persYear != computedYear) ||
    822             (persMonth != computedMonth) ||
    823             (persDay != computedDay)) {
    824           errln(UnicodeString("Expected ") + persYear + "/" + (persMonth+1) + "/" + persDay +
    825                 " but got " +  computedYear + "/" + (computedMonth+1) + "/" + computedDay);
    826         }
    827 
    828     }
    829 
    830     delete cal;
    831     delete grego;
    832 }
    833 
    834 void IntlCalendarTest::TestPersianFormat() {
    835     UErrorCode status = U_ZERO_ERROR;
    836     SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale(" en_US@calendar=persian"), status);
    837     CHECK(status, "creating date format instance");
    838     SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status);
    839     CHECK(status, "creating gregorian date format instance");
    840     UnicodeString gregorianDate("January 18, 2007 AD");
    841     UDate aDate = fmt2->parse(gregorianDate, status);
    842     if(!fmt) {
    843         errln("Coudln't create en_US instance");
    844     } else {
    845         UnicodeString str;
    846         fmt->format(aDate, str);
    847         logln(UnicodeString() + "as Persian Calendar: " + escape(str));
    848         UnicodeString expected("Dey 28, 1385 AP");
    849         if(str != expected) {
    850             errln("Expected " + escape(expected) + " but got " + escape(str));
    851         }
    852         UDate otherDate = fmt->parse(expected, status);
    853         if(otherDate != aDate) {
    854             UnicodeString str3;
    855             fmt->format(otherDate, str3);
    856             errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " +  otherDate + ", " + escape(str3));
    857         } else {
    858             logln("Parsed OK: " + expected);
    859         }
    860         // Two digit year parsing problem #4732
    861         fmt->applyPattern("yy-MM-dd");
    862         str.remove();
    863         fmt->format(aDate, str);
    864         expected.setTo("85-10-28");
    865         if(str != expected) {
    866             errln("Expected " + escape(expected) + " but got " + escape(str));
    867         }
    868         otherDate = fmt->parse(expected, status);
    869         if (otherDate != aDate) {
    870             errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate);
    871         } else {
    872             logln("Parsed OK: " + expected);
    873         }
    874         delete fmt;
    875     }
    876     delete fmt2;
    877 
    878     CHECK(status, "Error occured testing Persian Calendar in English ");
    879 }
    880 
    881 
    882 void IntlCalendarTest::simpleTest(const Locale& loc, const UnicodeString& expect, UDate expectDate, UErrorCode& status)
    883 {
    884     UnicodeString tmp;
    885     UDate         d;
    886     DateFormat *fmt0 = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull);
    887 
    888     logln("Try format/parse of " + (UnicodeString)loc.getName());
    889     DateFormat *fmt2 = DateFormat::createDateInstance(DateFormat::kFull, loc);
    890     if(fmt2) {
    891         fmt2->format(expectDate, tmp);
    892         logln(escape(tmp) + " ( in locale " + loc.getName() + ")");
    893         if(tmp != expect) {
    894             errln(UnicodeString("Failed to format " ) + loc.getName() + " expected " + escape(expect) + " got " + escape(tmp) );
    895         }
    896 
    897         d = fmt2->parse(expect,status);
    898         CHECK(status, "Error occured parsing " + UnicodeString(loc.getName()));
    899         if(d != expectDate) {
    900             fmt2->format(d,tmp);
    901             errln(UnicodeString("Failed to parse " ) + escape(expect) + ", " + loc.getName() + " expect " + (double)expectDate + " got " + (double)d  + " " + escape(tmp));
    902             logln( "wanted " + escape(fmt0->format(expectDate,tmp.remove())) + " but got " + escape(fmt0->format(d,tmp.remove())));
    903         }
    904         delete fmt2;
    905     } else {
    906         errln((UnicodeString)"Can't create " + loc.getName() + " date instance");
    907     }
    908     delete fmt0;
    909 }
    910 
    911 #undef CHECK
    912 
    913 #endif /* #if !UCONFIG_NO_FORMATTING */
    914 
    915 //eof
    916