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