Home | History | Annotate | Download | only in intltest
      1 /***********************************************************************
      2  * COPYRIGHT:
      3  * Copyright (c) 1997-2012, International Business Machines Corporation
      4  * and others. All Rights Reserved.
      5  ***********************************************************************/
      6 
      7 /* Test Internationalized Calendars for C++ */
      8 
      9 #include "unicode/utypes.h"
     10 #include "string.h"
     11 #include "unicode/locid.h"
     12 #include "japancal.h"
     13 
     14 #if !UCONFIG_NO_FORMATTING
     15 
     16 #include <stdio.h>
     17 #include "caltest.h"
     18 
     19 #define CHECK(status, msg) \
     20     if (U_FAILURE(status)) { \
     21       dataerrln((UnicodeString(u_errorName(status)) + UnicodeString(" : " ) )+ msg); \
     22         return; \
     23     }
     24 
     25 
     26 static UnicodeString escape( const UnicodeString&src)
     27 {
     28   UnicodeString dst;
     29     dst.remove();
     30     for (int32_t i = 0; i < src.length(); ++i) {
     31         UChar c = src[i];
     32         if(c < 0x0080)
     33             dst += c;
     34         else {
     35             dst += UnicodeString("[");
     36             char buf [8];
     37             sprintf(buf, "%#x", c);
     38             dst += UnicodeString(buf);
     39             dst += UnicodeString("]");
     40         }
     41     }
     42 
     43     return dst;
     44 }
     45 
     46 
     47 #include "incaltst.h"
     48 #include "unicode/gregocal.h"
     49 #include "unicode/smpdtfmt.h"
     50 #include "unicode/simpletz.h"
     51 
     52 // *****************************************************************************
     53 // class IntlCalendarTest
     54 // *****************************************************************************
     55 //--- move to CalendarTest?
     56 
     57 static const double JULIAN_EPOCH = -210866760000000.;
     58 
     59 
     60 // Turn this on to dump the calendar fields
     61 #define U_DEBUG_DUMPCALS
     62 
     63 
     64 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
     65 
     66 
     67 void IntlCalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
     68 {
     69     if (exec) logln("TestSuite IntlCalendarTest");
     70     switch (index) {
     71     CASE(0,TestTypes);
     72     CASE(1,TestGregorian);
     73     CASE(2,TestBuddhist);
     74     CASE(3,TestJapanese);
     75     CASE(4,TestBuddhistFormat);
     76     CASE(5,TestJapaneseFormat);
     77     CASE(6,TestJapanese3860);
     78     CASE(7,TestPersian);
     79     CASE(8,TestPersianFormat);
     80     CASE(9,TestTaiwan);
     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                             "buddhist",
    123                             "buddhist",
    124                             "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("Coudln'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 occured 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("Coudln'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 occured");
    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, heisei)
    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("Coudln't create en_US instance");
    637         } else {
    638             UErrorCode s2 = U_ZERO_ERROR;
    639             cal2->clear();
    640             UnicodeString samplestr("1.1.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.1.9 string");
    646             logln("*cal2 after 119 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, heisei)
    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("Coudln'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);
    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 = 235; //JapaneseCalendar::kCurrentEra;
    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 
    712 
    713 
    714 /**
    715  * Verify the Persian Calendar.
    716  */
    717 void IntlCalendarTest::TestPersian() {
    718     UDate timeA = Calendar::getNow();
    719 
    720     Calendar *cal;
    721     UErrorCode status = U_ZERO_ERROR;
    722     cal = Calendar::createInstance("fa_IR@calendar=persian", status);
    723     CHECK(status, UnicodeString("Creating fa_IR@calendar=persian calendar"));
    724     // Sanity check the calendar
    725     UDate timeB = Calendar::getNow();
    726     UDate timeCal = cal->getTime(status);
    727 
    728     if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
    729       errln((UnicodeString)"Error: Calendar time " + timeCal +
    730             " is not within sampled times [" + timeA + " to " + timeB + "]!");
    731     }
    732     // end sanity check
    733 
    734     // Test various dates to be sure of validity
    735     int32_t data[] = {
    736         1925, 4, 24, 1304, 2, 4,
    737         2011, 1, 11, 1389, 10, 21,
    738         1986, 2, 25, 1364, 12, 6,
    739         1934, 3, 14, 1312, 12, 23,
    740 
    741         2090, 3, 19, 1468, 12, 29,
    742         2007, 2, 22, 1385, 12, 3,
    743         1969, 12, 31, 1348, 10, 10,
    744         1945, 11, 12, 1324, 8, 21,
    745         1925, 3, 31, 1304, 1, 11,
    746 
    747         1996, 3, 19, 1374, 12, 29,
    748         1996, 3, 20, 1375, 1, 1,
    749         1997, 3, 20, 1375, 12, 30,
    750         1997, 3, 21, 1376, 1, 1,
    751 
    752         2008, 3, 19, 1386, 12, 29,
    753         2008, 3, 20, 1387, 1, 1,
    754         2004, 3, 19, 1382, 12, 29,
    755         2004, 3, 20, 1383, 1, 1,
    756 
    757         2006, 3, 20, 1384, 12, 29,
    758         2006, 3, 21, 1385, 1, 1,
    759 
    760         2005, 4, 20, 1384, 1, 31,
    761         2005, 4, 21, 1384, 2, 1,
    762         2005, 5, 21, 1384, 2, 31,
    763         2005, 5, 22, 1384, 3, 1,
    764         2005, 6, 21, 1384, 3, 31,
    765         2005, 6, 22, 1384, 4, 1,
    766         2005, 7, 22, 1384, 4, 31,
    767         2005, 7, 23, 1384, 5, 1,
    768         2005, 8, 22, 1384, 5, 31,
    769         2005, 8, 23, 1384, 6, 1,
    770         2005, 9, 22, 1384, 6, 31,
    771         2005, 9, 23, 1384, 7, 1,
    772         2005, 10, 22, 1384, 7, 30,
    773         2005, 10, 23, 1384, 8, 1,
    774         2005, 11, 21, 1384, 8, 30,
    775         2005, 11, 22, 1384, 9, 1,
    776         2005, 12, 21, 1384, 9, 30,
    777         2005, 12, 22, 1384, 10, 1,
    778         2006, 1, 20, 1384, 10, 30,
    779         2006, 1, 21, 1384, 11, 1,
    780         2006, 2, 19, 1384, 11, 30,
    781         2006, 2, 20, 1384, 12, 1,
    782         2006, 3, 20, 1384, 12, 29,
    783         2006, 3, 21, 1385, 1, 1,
    784 
    785         // The 2820-year cycle arithmetical algorithm would fail this one.
    786         2025, 3, 21, 1404, 1, 1,
    787 
    788         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    789     };
    790 
    791     Calendar *grego = Calendar::createInstance("fa_IR@calendar=gregorian", status);
    792     for (int32_t i=0; data[i]!=-1; ) {
    793         int32_t gregYear = data[i++];
    794         int32_t gregMonth = data[i++]-1;
    795         int32_t gregDay = data[i++];
    796         int32_t persYear = data[i++];
    797         int32_t persMonth = data[i++]-1;
    798         int32_t persDay = data[i++];
    799 
    800         // Test conversion from Persian dates
    801         grego->clear();
    802         grego->set(gregYear, gregMonth, gregDay);
    803 
    804         cal->clear();
    805         cal->set(persYear, persMonth, persDay);
    806 
    807         UDate persTime = cal->getTime(status);
    808         UDate gregTime = grego->getTime(status);
    809 
    810         if (persTime != gregTime) {
    811           errln(UnicodeString("Expected ") + gregTime + " but got " + persTime);
    812         }
    813 
    814         // Test conversion to Persian dates
    815         cal->clear();
    816         cal->setTime(gregTime, status);
    817 
    818         int32_t computedYear = cal->get(UCAL_YEAR, status);
    819         int32_t computedMonth = cal->get(UCAL_MONTH, status);
    820         int32_t computedDay = cal->get(UCAL_DATE, status);
    821 
    822         if ((persYear != computedYear) ||
    823             (persMonth != computedMonth) ||
    824             (persDay != computedDay)) {
    825           errln(UnicodeString("Expected ") + persYear + "/" + (persMonth+1) + "/" + persDay +
    826                 " but got " +  computedYear + "/" + (computedMonth+1) + "/" + computedDay);
    827         }
    828 
    829     }
    830 
    831     delete cal;
    832     delete grego;
    833 }
    834 
    835 void IntlCalendarTest::TestPersianFormat() {
    836     UErrorCode status = U_ZERO_ERROR;
    837     SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale(" en_US@calendar=persian"), status);
    838     CHECK(status, "creating date format instance");
    839     SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status);
    840     CHECK(status, "creating gregorian date format instance");
    841     UnicodeString gregorianDate("January 18, 2007 AD");
    842     UDate aDate = fmt2->parse(gregorianDate, status);
    843     if(!fmt) {
    844         errln("Coudln't create en_US instance");
    845     } else {
    846         UnicodeString str;
    847         fmt->format(aDate, str);
    848         logln(UnicodeString() + "as Persian Calendar: " + escape(str));
    849         UnicodeString expected("Dey 28, 1385 AP");
    850         if(str != expected) {
    851             errln("Expected " + escape(expected) + " but got " + escape(str));
    852         }
    853         UDate otherDate = fmt->parse(expected, status);
    854         if(otherDate != aDate) {
    855             UnicodeString str3;
    856             fmt->format(otherDate, str3);
    857             errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " +  otherDate + ", " + escape(str3));
    858         } else {
    859             logln("Parsed OK: " + expected);
    860         }
    861         // Two digit year parsing problem #4732
    862         fmt->applyPattern("yy-MM-dd");
    863         str.remove();
    864         fmt->format(aDate, str);
    865         expected.setTo("85-10-28");
    866         if(str != expected) {
    867             errln("Expected " + escape(expected) + " but got " + escape(str));
    868         }
    869         otherDate = fmt->parse(expected, status);
    870         if (otherDate != aDate) {
    871             errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate);
    872         } else {
    873             logln("Parsed OK: " + expected);
    874         }
    875         delete fmt;
    876     }
    877     delete fmt2;
    878 
    879     CHECK(status, "Error occured testing Persian Calendar in English ");
    880 }
    881 
    882 
    883 void IntlCalendarTest::simpleTest(const Locale& loc, const UnicodeString& expect, UDate expectDate, UErrorCode& status)
    884 {
    885     UnicodeString tmp;
    886     UDate         d;
    887     DateFormat *fmt0 = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull);
    888 
    889     logln("Try format/parse of " + (UnicodeString)loc.getName());
    890     DateFormat *fmt2 = DateFormat::createDateInstance(DateFormat::kFull, loc);
    891     if(fmt2) {
    892         fmt2->format(expectDate, tmp);
    893         logln(escape(tmp) + " ( in locale " + loc.getName() + ")");
    894         if(tmp != expect) {
    895             errln(UnicodeString("Failed to format " ) + loc.getName() + " expected " + escape(expect) + " got " + escape(tmp) );
    896         }
    897 
    898         d = fmt2->parse(expect,status);
    899         CHECK(status, "Error occured parsing " + UnicodeString(loc.getName()));
    900         if(d != expectDate) {
    901             fmt2->format(d,tmp);
    902             errln(UnicodeString("Failed to parse " ) + escape(expect) + ", " + loc.getName() + " expect " + (double)expectDate + " got " + (double)d  + " " + escape(tmp));
    903             logln( "wanted " + escape(fmt0->format(expectDate,tmp.remove())) + " but got " + escape(fmt0->format(d,tmp.remove())));
    904         }
    905         delete fmt2;
    906     } else {
    907         errln((UnicodeString)"Can't create " + loc.getName() + " date instance");
    908     }
    909     delete fmt0;
    910 }
    911 
    912 #undef CHECK
    913 
    914 #endif /* #if !UCONFIG_NO_FORMATTING */
    915 
    916 //eof
    917