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