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