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