1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /***********************************************************************
5 * Copyright (c) 1997-2014, International Business Machines Corporation
6 * and others. All Rights Reserved.
7 ***********************************************************************/
9 /* Test Internationalized Calendars for C++ */
11 #include "unicode/utypes.h"
13 #include "unicode/locid.h"
15 #include "unicode/localpointer.h"
16 #include "unicode/datefmt.h"
17 #include "unicode/smpdtfmt.h"
18 #include "unicode/dtptngen.h"
20 #if !UCONFIG_NO_FORMATTING
25 #define CHECK(status, msg) UPRV_BLOCK_MACRO_BEGIN { \
26 if (U_FAILURE(status)) { \
27 dataerrln((UnicodeString(u_errorName(status)) + UnicodeString(" : " ) )+ msg); \
30 } UPRV_BLOCK_MACRO_END
33 static UnicodeString
escape( const UnicodeString
&src
)
37 for (int32_t i
= 0; i
< src
.length(); ++i
) {
42 dst
+= UnicodeString("[");
44 sprintf(buf
, "%#x", c
);
45 dst
+= UnicodeString(buf
);
46 dst
+= UnicodeString("]");
55 #include "unicode/gregocal.h"
56 #include "unicode/smpdtfmt.h"
57 #include "unicode/simpletz.h"
59 // *****************************************************************************
60 // class IntlCalendarTest
61 // *****************************************************************************
62 //--- move to CalendarTest?
64 // Turn this on to dump the calendar fields
65 #define U_DEBUG_DUMPCALS
68 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
71 void IntlCalendarTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
73 if (exec
) logln("TestSuite IntlCalendarTest");
76 CASE(1,TestGregorian
);
79 CASE(4,TestBuddhistFormat
);
80 CASE(5,TestJapaneseFormat
);
81 CASE(6,TestJapanese3860
);
82 CASE(7,TestForceGannenNumbering
);
84 CASE(9,TestPersianFormat
);
86 default: name
= ""; break;
92 // ---------------------------------------------------------------------------------
96 * Test various API methods for API completeness.
99 IntlCalendarTest::TestTypes()
102 UErrorCode status
= U_ZERO_ERROR
;
104 const char *locs
[40] = { "en_US_VALLEYGIRL",
105 "en_US_VALLEYGIRL@collation=phonebook;calendar=japanese",
106 "en_US_VALLEYGIRL@collation=phonebook;calendar=gregorian",
107 "ja_JP@calendar=japanese",
108 "th_TH@calendar=buddhist",
110 "th_TH_TRADITIONAL@calendar=gregorian",
112 "th_TH", // Default calendar for th_TH is buddhist
113 "th", // th's default region is TH and buddhist is used as default for TH
114 "en_TH", // Default calendar for any locales with region TH is buddhist
115 "en-TH-u-ca-gregory",
117 const char *types
[40] = { "gregorian",
131 for(j
=0;locs
[j
];j
++) {
132 logln(UnicodeString("Creating calendar of locale ") + locs
[j
]);
133 status
= U_ZERO_ERROR
;
134 c
= Calendar::createInstance(locs
[j
], status
);
135 CHECK(status
, "creating '" + UnicodeString(locs
[j
]) + "' calendar");
136 if(U_SUCCESS(status
)) {
137 logln(UnicodeString(" type is ") + c
->getType());
138 if(strcmp(c
->getType(), types
[j
])) {
139 dataerrln(UnicodeString(locs
[j
]) + UnicodeString("Calendar type ") + c
->getType() + " instead of " + types
[j
]);
149 * Run a test of a quasi-Gregorian calendar. This is a calendar
150 * that behaves like a Gregorian but has different year/era mappings.
151 * The int[] data array should have the format:
153 * { era, year, gregorianYear, month, dayOfMonth, ... ... , -1 }
155 void IntlCalendarTest::quasiGregorianTest(Calendar
& cal
, const Locale
& gcl
, const int32_t *data
) {
156 UErrorCode status
= U_ZERO_ERROR
;
157 // As of JDK 1.4.1_01, using the Sun JDK GregorianCalendar as
158 // a reference throws us off by one hour. This is most likely
159 // due to the JDK 1.4 incorporation of historical time zones.
160 //java.util.Calendar grego = java.util.Calendar.getInstance();
161 Calendar
*grego
= Calendar::createInstance(gcl
, status
);
162 if (U_FAILURE(status
)) {
163 dataerrln("Error calling Calendar::createInstance");
167 int32_t tz1
= cal
.get(UCAL_ZONE_OFFSET
,status
);
168 int32_t tz2
= grego
-> get (UCAL_ZONE_OFFSET
, status
);
170 errln((UnicodeString
)"cal's tz " + tz1
+ " != grego's tz " + tz2
);
173 for (int32_t i
=0; data
[i
]!=-1; ) {
174 int32_t era
= data
[i
++];
175 int32_t year
= data
[i
++];
176 int32_t gregorianYear
= data
[i
++];
177 int32_t month
= data
[i
++];
178 int32_t dayOfMonth
= data
[i
++];
181 grego
->set(gregorianYear
, month
, dayOfMonth
);
182 UDate D
= grego
->getTime(status
);
185 cal
.set(UCAL_ERA
, era
);
186 cal
.set(year
, month
, dayOfMonth
);
187 UDate d
= cal
.getTime(status
);
188 #ifdef U_DEBUG_DUMPCALS
189 logln((UnicodeString
)"cal : " + CalendarTest::calToStr(cal
));
190 logln((UnicodeString
)"grego: " + CalendarTest::calToStr(*grego
));
193 logln(UnicodeString("OK: ") + era
+ ":" + year
+ "/" + (month
+1) + "/" + dayOfMonth
+
194 " => " + d
+ " (" + UnicodeString(cal
.getType()) + ")");
196 errln(UnicodeString("Fail: (fields to millis)") + era
+ ":" + year
+ "/" + (month
+1) + "/" + dayOfMonth
+
197 " => " + d
+ ", expected " + D
+ " (" + UnicodeString(cal
.getType()) + "Off by: " + (d
-D
));
200 // Now, set the gregorian millis on the other calendar
202 cal
.setTime(D
, status
);
203 int e
= cal
.get(UCAL_ERA
, status
);
204 int y
= cal
.get(UCAL_YEAR
, status
);
205 #ifdef U_DEBUG_DUMPCALS
206 logln((UnicodeString
)"cal : " + CalendarTest::calToStr(cal
));
207 logln((UnicodeString
)"grego: " + CalendarTest::calToStr(*grego
));
209 if (y
== year
&& e
== era
) {
210 logln((UnicodeString
)"OK: " + D
+ " => " + cal
.get(UCAL_ERA
, status
) + ":" +
211 cal
.get(UCAL_YEAR
, status
) + "/" +
212 (cal
.get(UCAL_MONTH
, status
)+1) + "/" + cal
.get(UCAL_DATE
, status
) + " (" + UnicodeString(cal
.getType()) + ")");
214 errln((UnicodeString
)"Fail: (millis to fields)" + D
+ " => " + cal
.get(UCAL_ERA
, status
) + ":" +
215 cal
.get(UCAL_YEAR
, status
) + "/" +
216 (cal
.get(UCAL_MONTH
, status
)+1) + "/" + cal
.get(UCAL_DATE
, status
) +
217 ", expected " + era
+ ":" + year
+ "/" + (month
+1) + "/" +
218 dayOfMonth
+ " (" + UnicodeString(cal
.getType()));
222 CHECK(status
, "err during quasiGregorianTest()");
225 // Verify that Gregorian works like Gregorian
226 void IntlCalendarTest::TestGregorian() {
227 UDate timeA
= Calendar::getNow();
229 GregorianCalendar::AD
, 1868, 1868, UCAL_SEPTEMBER
, 8,
230 GregorianCalendar::AD
, 1868, 1868, UCAL_SEPTEMBER
, 9,
231 GregorianCalendar::AD
, 1869, 1869, UCAL_JUNE
, 4,
232 GregorianCalendar::AD
, 1912, 1912, UCAL_JULY
, 29,
233 GregorianCalendar::AD
, 1912, 1912, UCAL_JULY
, 30,
234 GregorianCalendar::AD
, 1912, 1912, UCAL_AUGUST
, 1,
235 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
239 UErrorCode status
= U_ZERO_ERROR
;
240 cal
= Calendar::createInstance(/*"de_DE", */ status
);
241 CHECK(status
, UnicodeString("Creating de_CH calendar"));
242 // Sanity check the calendar
243 UDate timeB
= Calendar::getNow();
244 UDate timeCal
= cal
->getTime(status
);
246 if(!(timeA
<= timeCal
) || !(timeCal
<= timeB
)) {
247 errln((UnicodeString
)"Error: Calendar time " + timeCal
+
248 " is not within sampled times [" + timeA
+ " to " + timeB
+ "]!");
252 // Note, the following is a good way to test the sanity of the constructed calendars,
253 // using Collation as a delay-loop:
255 // $ intltest format/IntlCalendarTest collate/G7CollationTest format/IntlCalendarTest
257 quasiGregorianTest(*cal
,Locale("fr_FR"),data
);
262 * Verify that BuddhistCalendar shifts years to Buddhist Era but otherwise
263 * behaves like GregorianCalendar.
265 void IntlCalendarTest::TestBuddhist() {
266 // BE 2542 == 1999 CE
267 UDate timeA
= Calendar::getNow();
270 0, // B. era [928479600000]
276 0, // B. era [-79204842000000]
279 UCAL_FEBRUARY
, // month
282 0, // test month calculation: 4795 BE = 4252 AD is a leap year, but 4795 AD is not.
283 4795, // BE [72018057600000]
288 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
291 UErrorCode status
= U_ZERO_ERROR
;
292 cal
= Calendar::createInstance("th_TH@calendar=buddhist", status
);
293 CHECK(status
, UnicodeString("Creating th_TH@calendar=buddhist calendar"));
295 // Sanity check the calendar
296 UDate timeB
= Calendar::getNow();
297 UDate timeCal
= cal
->getTime(status
);
299 if(!(timeA
<= timeCal
) || !(timeCal
<= timeB
)) {
300 errln((UnicodeString
)"Error: Calendar time " + timeCal
+
301 " is not within sampled times [" + timeA
+ " to " + timeB
+ "]!");
306 quasiGregorianTest(*cal
,Locale("th_TH@calendar=gregorian"),data
);
312 * Verify that TaiWanCalendar shifts years to Minguo Era but otherwise
313 * behaves like GregorianCalendar.
315 void IntlCalendarTest::TestTaiwan() {
317 UDate timeA
= Calendar::getNow();
319 // TODO port these to the data items
321 1, // B. era [928479600000]
327 1, // B. era [-79204842000000]
330 UCAL_FEBRUARY
, // month
333 1, // B. era [-79204842000000]
336 UCAL_FEBRUARY
, // month
339 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
342 UErrorCode status
= U_ZERO_ERROR
;
343 cal
= Calendar::createInstance("en_US@calendar=roc", status
);
344 CHECK(status
, UnicodeString("Creating en_US@calendar=roc calendar"));
346 // Sanity check the calendar
347 UDate timeB
= Calendar::getNow();
348 UDate timeCal
= cal
->getTime(status
);
350 if(!(timeA
<= timeCal
) || !(timeCal
<= timeB
)) {
351 errln((UnicodeString
)"Error: Calendar time " + timeCal
+
352 " is not within sampled times [" + timeA
+ " to " + timeB
+ "]!");
357 quasiGregorianTest(*cal
,Locale("en_US"),data
);
364 * Verify that JapaneseCalendar shifts years to Japanese Eras but otherwise
365 * behaves like GregorianCalendar.
367 void IntlCalendarTest::TestJapanese() {
368 UDate timeA
= Calendar::getNow();
370 /* Sorry.. japancal.h is private! */
371 #define JapaneseCalendar_MEIJI 232
372 #define JapaneseCalendar_TAISHO 233
373 #define JapaneseCalendar_SHOWA 234
374 #define JapaneseCalendar_HEISEI 235
376 // BE 2542 == 1999 CE
378 // Jera Jyr Gyear m d
379 JapaneseCalendar_MEIJI
, 1, 1868, UCAL_SEPTEMBER
, 8,
380 JapaneseCalendar_MEIJI
, 1, 1868, UCAL_SEPTEMBER
, 9,
381 JapaneseCalendar_MEIJI
, 2, 1869, UCAL_JUNE
, 4,
382 JapaneseCalendar_MEIJI
, 45, 1912, UCAL_JULY
, 29,
383 JapaneseCalendar_TAISHO
, 1, 1912, UCAL_JULY
, 30,
384 JapaneseCalendar_TAISHO
, 1, 1912, UCAL_AUGUST
, 1,
386 // new tests (not in java)
387 JapaneseCalendar_SHOWA
, 64, 1989, UCAL_JANUARY
, 7, // Test current era transition (different code path than others)
388 JapaneseCalendar_HEISEI
, 1, 1989, UCAL_JANUARY
, 8,
389 JapaneseCalendar_HEISEI
, 1, 1989, UCAL_JANUARY
, 9,
390 JapaneseCalendar_HEISEI
, 1, 1989, UCAL_DECEMBER
, 20,
391 JapaneseCalendar_HEISEI
, 15, 2003, UCAL_MAY
, 22,
392 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
396 UErrorCode status
= U_ZERO_ERROR
;
397 cal
= Calendar::createInstance("ja_JP@calendar=japanese", status
);
398 CHECK(status
, UnicodeString("Creating ja_JP@calendar=japanese calendar"));
399 // Sanity check the calendar
400 UDate timeB
= Calendar::getNow();
401 UDate timeCal
= cal
->getTime(status
);
403 if(!(timeA
<= timeCal
) || !(timeCal
<= timeB
)) {
404 errln((UnicodeString
)"Error: Calendar time " + timeCal
+
405 " is not within sampled times [" + timeA
+ " to " + timeB
+ "]!");
408 quasiGregorianTest(*cal
,Locale("ja_JP"),data
);
414 void IntlCalendarTest::TestBuddhistFormat() {
415 UErrorCode status
= U_ZERO_ERROR
;
417 // Test simple parse/format with adopt
419 // First, a contrived English test..
420 UDate aDate
= 999932400000.0;
421 SimpleDateFormat
fmt(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=buddhist"), status
);
422 CHECK(status
, "creating date format instance");
423 SimpleDateFormat
fmt2(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status
);
424 CHECK(status
, "creating gregorian date format instance");
426 fmt2
.format(aDate
, str
);
427 logln(UnicodeString() + "Test Date: " + str
);
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
));
435 UDate otherDate
= fmt
.parse(expected
, status
);
436 if(otherDate
!= aDate
) {
438 fmt
.format(otherDate
, str3
);
439 errln("Parse incorrect of " + escape(expected
) + " - wanted " + aDate
+ " but got " + otherDate
+ ", " + escape(str3
));
441 logln("Parsed OK: " + expected
);
444 CHECK(status
, "Error occurred testing Buddhist Calendar in English ");
446 status
= U_ZERO_ERROR
;
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
454 simpleTest(loc
, expect
, expectDate
, status
);
456 status
= U_ZERO_ERROR
;
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");
463 simpleTest(loc
, expect
, expectDate
, status
);
465 status
= U_ZERO_ERROR
;
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");
472 simpleTest(loc
, expect
, expectDate
, status
);
474 status
= U_ZERO_ERROR
;
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");
481 simpleTest(loc
, expect
, expectDate
, status
);
485 // TaiwanFormat has been moved to testdata/format.txt
488 void IntlCalendarTest::TestJapaneseFormat() {
489 LocalPointer
<Calendar
> cal
;
490 UErrorCode status
= U_ZERO_ERROR
;
491 cal
.adoptInstead(Calendar::createInstance("ja_JP@calendar=japanese", status
));
492 CHECK(status
, UnicodeString("Creating ja_JP@calendar=japanese calendar"));
494 LocalPointer
<Calendar
> cal2(cal
->clone());
495 cal
.adoptInstead(nullptr);
497 // Test simple parse/format with adopt
499 UDate aDate
= 999932400000.0;
500 SimpleDateFormat
fmt(UnicodeString("MMMM d, yy G"), Locale("en_US@calendar=japanese"), status
);
501 SimpleDateFormat
fmt2(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status
);
502 CHECK(status
, "creating date format instance");
504 fmt2
.format(aDate
, str
);
505 logln(UnicodeString() + "Test Date: " + str
);
507 fmt
.format(aDate
, str
);
508 logln(UnicodeString() + "as Japanese Calendar: " + str
);
509 UnicodeString
expected("September 8, 13 Heisei");
510 if(str
!= expected
) {
511 errln("Expected " + expected
+ " but got " + str
);
513 UDate otherDate
= fmt
.parse(expected
, status
);
514 if(otherDate
!= aDate
) {
517 fmt
.parse(expected
, *cal2
, pp
);
518 fmt
.format(otherDate
, str3
);
519 errln("Parse incorrect of " + expected
+ " - wanted " + aDate
+ " but got " + " = " + otherDate
+ ", " + str3
+ " = " + CalendarTest::calToStr(*cal2
) );
522 logln("Parsed OK: " + expected
);
525 // Test parse with incomplete information
526 SimpleDateFormat
fmti(UnicodeString("G y"), Locale("en_US@calendar=japanese"), status
);
527 aDate
= -3197117222000.0;
528 CHECK(status
, "creating date format instance");
530 fmt2
.format(aDate
, str
);
531 logln(UnicodeString() + "Test Date: " + str
);
533 fmti
.format(aDate
, str
);
534 logln(UnicodeString() + "as Japanese Calendar: " + str
);
535 expected
= u
"Meiji 1";
536 if(str
!= expected
) {
537 errln("Expected " + expected
+ " but got " + str
);
539 otherDate
= fmti
.parse(expected
, status
);
540 if(otherDate
!= aDate
) {
543 fmti
.parse(expected
, *cal2
, pp
);
544 fmti
.format(otherDate
, str3
);
545 errln("Parse incorrect of " + expected
+ " - wanted " + aDate
+ " but got " + " = " +
546 otherDate
+ ", " + str3
+ " = " + CalendarTest::calToStr(*cal2
) );
548 logln("Parsed OK: " + expected
);
551 CHECK(status
, "Error occurred");
553 // Now, try in Japanese
555 UnicodeString expect
= CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5 \\u571f\\u66dc\\u65e5");
556 UDate expectDate
= 999932400000.0; // Testing a recent date
557 Locale
loc("ja_JP@calendar=japanese");
559 status
= U_ZERO_ERROR
;
560 simpleTest(loc
, expect
, expectDate
, status
);
563 UnicodeString expect
= CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5 \\u571f\\u66dc\\u65e5");
564 UDate expectDate
= 999932400000.0; // Testing a recent date
565 Locale
loc("ja_JP@calendar=japanese");
567 status
= U_ZERO_ERROR
;
568 simpleTest(loc
, expect
, expectDate
, status
);
571 UnicodeString expect
= CharsToUnicodeString("\\u5b89\\u6c385\\u5e747\\u67084\\u65e5 \\u6728\\u66dc\\u65e5");
572 UDate expectDate
= -6106032422000.0; // 1776-07-04T00:00:00Z-075258
573 Locale
loc("ja_JP@calendar=japanese");
575 status
= U_ZERO_ERROR
;
576 simpleTest(loc
, expect
, expectDate
, status
);
579 { // Jitterbug 1869 - this is an ambiguous era. (Showa 64 = Jan 6 1989, but Showa could be 2 other eras) )
580 UnicodeString expect
= CharsToUnicodeString("\\u662d\\u548c64\\u5e741\\u67086\\u65e5 \\u91d1\\u66dc\\u65e5");
581 UDate expectDate
= 600076800000.0;
582 Locale
loc("ja_JP@calendar=japanese");
584 status
= U_ZERO_ERROR
;
585 simpleTest(loc
, expect
, expectDate
, status
);
588 { // 1989 Jan 9 Monday = Heisei 1; full is Gy年M月d日EEEE => 平成元年1月9日月曜日
589 UnicodeString expect
= CharsToUnicodeString("\\u5E73\\u6210\\u5143\\u5E741\\u67089\\u65E5 \\u6708\\u66DC\\u65E5");
590 UDate expectDate
= 600336000000.0;
591 Locale
loc("ja_JP@calendar=japanese");
593 status
= U_ZERO_ERROR
;
594 simpleTest(loc
, expect
, expectDate
, status
);
597 { // This Feb 29th falls on a leap year by gregorian year, but not by Japanese year.
598 UnicodeString expect
= CharsToUnicodeString("\\u5EB7\\u6B632\\u5e742\\u670829\\u65e5 \\u65e5\\u66dc\\u65e5");
599 UDate expectDate
= -16214400422000.0; // 1456-03-09T00:00Z-075258
600 Locale
loc("ja_JP@calendar=japanese");
602 status
= U_ZERO_ERROR
;
603 simpleTest(loc
, expect
, expectDate
, status
);
608 void IntlCalendarTest::TestJapanese3860()
610 LocalPointer
<Calendar
> cal
;
611 UErrorCode status
= U_ZERO_ERROR
;
612 cal
.adoptInstead(Calendar::createInstance("ja_JP@calendar=japanese", status
));
613 CHECK(status
, UnicodeString("Creating ja_JP@calendar=japanese calendar"));
614 LocalPointer
<Calendar
> cal2(cal
->clone());
615 SimpleDateFormat
fmt2(UnicodeString("HH:mm:ss.S MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status
);
619 // Test simple parse/format with adopt
622 // Test parse with missing era (should default to current era, heisei)
623 // Test parse with incomplete information
624 logln("Testing parse w/ missing era...");
625 SimpleDateFormat
fmt(UnicodeString("y/M/d"), Locale("ja_JP@calendar=japanese"), status
);
626 CHECK(status
, "creating date format instance");
627 UErrorCode s2
= U_ZERO_ERROR
;
629 UnicodeString
samplestr("1/5/9");
630 logln(UnicodeString() + "Test Year: " + samplestr
);
631 aDate
= fmt
.parse(samplestr
, s2
);
633 fmt
.parse(samplestr
, *cal2
, pp
);
634 CHECK(s2
, "parsing the 1/5/9 string");
635 logln("*cal2 after 159 parse:");
637 fmt2
.format(aDate
, str
);
638 logln(UnicodeString() + "as Gregorian Calendar: " + str
);
640 cal2
->setTime(aDate
, s2
);
641 int32_t gotYear
= cal2
->get(UCAL_YEAR
, s2
);
642 int32_t gotEra
= cal2
->get(UCAL_ERA
, s2
);
643 int32_t expectYear
= 1;
644 int32_t expectEra
= JapaneseCalendar::getCurrentEra();
645 if((gotYear
!=1) || (gotEra
!= expectEra
)) {
646 errln(UnicodeString("parse "+samplestr
+" of 'y/M/d' as Japanese Calendar, expected year ") + expectYear
+
647 UnicodeString(" and era ") + expectEra
+", but got year " + gotYear
+ " and era " + gotEra
+ " (Gregorian:" + str
+")");
649 logln(UnicodeString() + " year: " + gotYear
+ ", era: " + gotEra
);
654 // Test simple parse/format with adopt
657 // Test parse with missing era (should default to current era, heisei)
658 // Test parse with incomplete information
659 logln("Testing parse w/ just year...");
660 SimpleDateFormat
fmt(UnicodeString("y"), Locale("ja_JP@calendar=japanese"), status
);
661 CHECK(status
, "creating date format instance");
662 UErrorCode s2
= U_ZERO_ERROR
;
664 UnicodeString
samplestr("1");
665 logln(UnicodeString() + "Test Year: " + samplestr
);
666 aDate
= fmt
.parse(samplestr
, s2
);
668 fmt
.parse(samplestr
, *cal2
, pp
);
669 CHECK(s2
, "parsing the 1 string");
670 logln("*cal2 after 1 parse:");
672 fmt2
.format(aDate
, str
);
673 logln(UnicodeString() + "as Gregorian Calendar: " + str
);
675 cal2
->setTime(aDate
, s2
);
676 int32_t gotYear
= cal2
->get(UCAL_YEAR
, s2
);
677 int32_t gotEra
= cal2
->get(UCAL_ERA
, s2
);
678 int32_t expectYear
= 1;
679 int32_t expectEra
= JapaneseCalendar::getCurrentEra();
680 if((gotYear
!=1) || (gotEra
!= expectEra
)) {
681 errln(UnicodeString("parse "+samplestr
+" of 'y' as Japanese Calendar, expected year ") + expectYear
+
682 UnicodeString(" and era ") + expectEra
+", but got year " + gotYear
+ " and era " + gotEra
+ " (Gregorian:" + str
+")");
684 logln(UnicodeString() + " year: " + gotYear
+ ", era: " + gotEra
);
689 void IntlCalendarTest::TestForceGannenNumbering()
692 const char* locID
= "ja_JP@calendar=japanese";
694 UDate refDate
= 600336000000.0; // 1989 Jan 9 Monday = Heisei 1
695 UnicodeString
patText(u
"Gy年M月d日",-1);
696 UnicodeString
patNumr(u
"GGGGGy/MM/dd",-1);
697 UnicodeString
skelText(u
"yMMMM",-1);
699 // Test Gannen year forcing
700 status
= U_ZERO_ERROR
;
701 LocalPointer
<SimpleDateFormat
> testFmt1(new SimpleDateFormat(patText
, loc
, status
));
702 LocalPointer
<SimpleDateFormat
> testFmt2(new SimpleDateFormat(patNumr
, loc
, status
));
703 if (U_FAILURE(status
)) {
704 dataerrln("Fail in new SimpleDateFormat locale %s: %s", locID
, u_errorName(status
));
706 UnicodeString testString1
, testString2
;
707 testString1
= testFmt1
->format(refDate
, testString1
);
708 if (testString1
.length() < 3 || testString1
.charAt(2) != 0x5143) {
709 errln(UnicodeString("Formatting year 1 in created text style, got " + testString1
+ " but expected 3rd char to be 0x5143"));
711 testString2
= testFmt2
->format(refDate
, testString2
);
712 if (testString2
.length() < 2 || testString2
.charAt(1) != 0x0031) {
713 errln(UnicodeString("Formatting year 1 in created numeric style, got " + testString2
+ " but expected 2nd char to be 1"));
715 // Now switch the patterns and verify that Gannen use follows the pattern
716 testFmt1
->applyPattern(patNumr
);
717 testString1
.remove();
718 testString1
= testFmt1
->format(refDate
, testString1
);
719 if (testString1
.length() < 2 || testString1
.charAt(1) != 0x0031) {
720 errln(UnicodeString("Formatting year 1 in applied numeric style, got " + testString1
+ " but expected 2nd char to be 1"));
722 testFmt2
->applyPattern(patText
);
723 testString2
.remove();
724 testString2
= testFmt2
->format(refDate
, testString2
);
725 if (testString2
.length() < 3 || testString2
.charAt(2) != 0x5143) {
726 errln(UnicodeString("Formatting year 1 in applied text style, got " + testString2
+ " but expected 3rd char to be 0x5143"));
730 // Test disabling of Gannen year forcing
731 status
= U_ZERO_ERROR
;
732 LocalPointer
<DateTimePatternGenerator
> dtpgen(DateTimePatternGenerator::createInstance(loc
, status
));
733 if (U_FAILURE(status
)) {
734 dataerrln("Fail in DateTimePatternGenerator::createInstance locale %s: %s", locID
, u_errorName(status
));
736 UnicodeString pattern
= dtpgen
->getBestPattern(skelText
, status
);
737 if (U_FAILURE(status
)) {
738 dataerrln("Fail in DateTimePatternGenerator::getBestPattern locale %s: %s", locID
, u_errorName(status
));
740 // Use override string of ""
741 LocalPointer
<SimpleDateFormat
> testFmt3(new SimpleDateFormat(pattern
, UnicodeString(""), loc
, status
));
742 if (U_FAILURE(status
)) {
743 dataerrln("Fail in new SimpleDateFormat locale %s: %s", locID
, u_errorName(status
));
745 UnicodeString testString3
;
746 testString3
= testFmt3
->format(refDate
, testString3
);
747 if (testString3
.length() < 3 || testString3
.charAt(2) != 0x0031) {
748 errln(UnicodeString("Formatting year 1 with Gannen disabled, got " + testString3
+ " but expected 3rd char to be 1"));
756 * Verify the Persian Calendar.
758 void IntlCalendarTest::TestPersian() {
759 UDate timeA
= Calendar::getNow();
762 UErrorCode status
= U_ZERO_ERROR
;
763 cal
= Calendar::createInstance("fa_IR@calendar=persian", status
);
764 CHECK(status
, UnicodeString("Creating fa_IR@calendar=persian calendar"));
765 // Sanity check the calendar
766 UDate timeB
= Calendar::getNow();
767 UDate timeCal
= cal
->getTime(status
);
769 if(!(timeA
<= timeCal
) || !(timeCal
<= timeB
)) {
770 errln((UnicodeString
)"Error: Calendar time " + timeCal
+
771 " is not within sampled times [" + timeA
+ " to " + timeB
+ "]!");
775 // Test various dates to be sure of validity
777 1925, 4, 24, 1304, 2, 4,
778 2011, 1, 11, 1389, 10, 21,
779 1986, 2, 25, 1364, 12, 6,
780 1934, 3, 14, 1312, 12, 23,
782 2090, 3, 19, 1468, 12, 29,
783 2007, 2, 22, 1385, 12, 3,
784 1969, 12, 31, 1348, 10, 10,
785 1945, 11, 12, 1324, 8, 21,
786 1925, 3, 31, 1304, 1, 11,
788 1996, 3, 19, 1374, 12, 29,
789 1996, 3, 20, 1375, 1, 1,
790 1997, 3, 20, 1375, 12, 30,
791 1997, 3, 21, 1376, 1, 1,
793 2008, 3, 19, 1386, 12, 29,
794 2008, 3, 20, 1387, 1, 1,
795 2004, 3, 19, 1382, 12, 29,
796 2004, 3, 20, 1383, 1, 1,
798 2006, 3, 20, 1384, 12, 29,
799 2006, 3, 21, 1385, 1, 1,
801 2005, 4, 20, 1384, 1, 31,
802 2005, 4, 21, 1384, 2, 1,
803 2005, 5, 21, 1384, 2, 31,
804 2005, 5, 22, 1384, 3, 1,
805 2005, 6, 21, 1384, 3, 31,
806 2005, 6, 22, 1384, 4, 1,
807 2005, 7, 22, 1384, 4, 31,
808 2005, 7, 23, 1384, 5, 1,
809 2005, 8, 22, 1384, 5, 31,
810 2005, 8, 23, 1384, 6, 1,
811 2005, 9, 22, 1384, 6, 31,
812 2005, 9, 23, 1384, 7, 1,
813 2005, 10, 22, 1384, 7, 30,
814 2005, 10, 23, 1384, 8, 1,
815 2005, 11, 21, 1384, 8, 30,
816 2005, 11, 22, 1384, 9, 1,
817 2005, 12, 21, 1384, 9, 30,
818 2005, 12, 22, 1384, 10, 1,
819 2006, 1, 20, 1384, 10, 30,
820 2006, 1, 21, 1384, 11, 1,
821 2006, 2, 19, 1384, 11, 30,
822 2006, 2, 20, 1384, 12, 1,
823 2006, 3, 20, 1384, 12, 29,
824 2006, 3, 21, 1385, 1, 1,
826 // The 2820-year cycle arithmetical algorithm would fail this one.
827 2025, 3, 21, 1404, 1, 1,
829 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
832 Calendar
*grego
= Calendar::createInstance("fa_IR@calendar=gregorian", status
);
833 for (int32_t i
=0; data
[i
]!=-1; ) {
834 int32_t gregYear
= data
[i
++];
835 int32_t gregMonth
= data
[i
++]-1;
836 int32_t gregDay
= data
[i
++];
837 int32_t persYear
= data
[i
++];
838 int32_t persMonth
= data
[i
++]-1;
839 int32_t persDay
= data
[i
++];
841 // Test conversion from Persian dates
843 grego
->set(gregYear
, gregMonth
, gregDay
);
846 cal
->set(persYear
, persMonth
, persDay
);
848 UDate persTime
= cal
->getTime(status
);
849 UDate gregTime
= grego
->getTime(status
);
851 if (persTime
!= gregTime
) {
852 errln(UnicodeString("Expected ") + gregTime
+ " but got " + persTime
);
855 // Test conversion to Persian dates
857 cal
->setTime(gregTime
, status
);
859 int32_t computedYear
= cal
->get(UCAL_YEAR
, status
);
860 int32_t computedMonth
= cal
->get(UCAL_MONTH
, status
);
861 int32_t computedDay
= cal
->get(UCAL_DATE
, status
);
863 if ((persYear
!= computedYear
) ||
864 (persMonth
!= computedMonth
) ||
865 (persDay
!= computedDay
)) {
866 errln(UnicodeString("Expected ") + persYear
+ "/" + (persMonth
+1) + "/" + persDay
+
867 " but got " + computedYear
+ "/" + (computedMonth
+1) + "/" + computedDay
);
876 void IntlCalendarTest::TestPersianFormat() {
877 UErrorCode status
= U_ZERO_ERROR
;
878 SimpleDateFormat
fmt(UnicodeString("MMMM d, yyyy G"), Locale(" en_US@calendar=persian"), status
);
879 CHECK(status
, "creating date format instance");
880 SimpleDateFormat
fmt2(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status
);
881 CHECK(status
, "creating gregorian date format instance");
882 UnicodeString
gregorianDate("January 18, 2007 AD");
883 UDate aDate
= fmt2
.parse(gregorianDate
, status
);
885 fmt
.format(aDate
, str
);
886 logln(UnicodeString() + "as Persian Calendar: " + escape(str
));
887 UnicodeString
expected("Dey 28, 1385 AP");
888 if(str
!= expected
) {
889 errln("Expected " + escape(expected
) + " but got " + escape(str
));
891 UDate otherDate
= fmt
.parse(expected
, status
);
892 if(otherDate
!= aDate
) {
894 fmt
.format(otherDate
, str3
);
895 errln("Parse incorrect of " + escape(expected
) + " - wanted " + aDate
+ " but got " + otherDate
+ ", " + escape(str3
));
897 logln("Parsed OK: " + expected
);
899 // Two digit year parsing problem #4732
900 fmt
.applyPattern("yy-MM-dd");
902 fmt
.format(aDate
, str
);
903 expected
.setTo("85-10-28");
904 if(str
!= expected
) {
905 errln("Expected " + escape(expected
) + " but got " + escape(str
));
907 otherDate
= fmt
.parse(expected
, status
);
908 if (otherDate
!= aDate
) {
909 errln("Parse incorrect of " + escape(expected
) + " - wanted " + aDate
+ " but got " + otherDate
);
911 logln("Parsed OK: " + expected
);
914 CHECK(status
, "Error occured testing Persian Calendar in English ");
918 void IntlCalendarTest::simpleTest(const Locale
& loc
, const UnicodeString
& expect
, UDate expectDate
, UErrorCode
& status
)
922 DateFormat
*fmt0
= DateFormat::createDateTimeInstance(DateFormat::kFull
, DateFormat::kFull
);
924 logln("Try format/parse of " + (UnicodeString
)loc
.getName());
925 DateFormat
*fmt2
= DateFormat::createDateInstance(DateFormat::kFull
, loc
);
927 fmt2
->format(expectDate
, tmp
);
928 logln(escape(tmp
) + " ( in locale " + loc
.getName() + ")");
930 errln(UnicodeString("Failed to format " ) + loc
.getName() + " expected " + escape(expect
) + " got " + escape(tmp
) );
933 d
= fmt2
->parse(expect
,status
);
934 CHECK(status
, "Error occurred parsing " + UnicodeString(loc
.getName()));
935 if(d
!= expectDate
) {
937 errln(UnicodeString("Failed to parse " ) + escape(expect
) + ", " + loc
.getName() + " expect " + (double)expectDate
+ " got " + (double)d
+ " " + escape(tmp
));
938 logln( "wanted " + escape(fmt0
->format(expectDate
,tmp
.remove())) + " but got " + escape(fmt0
->format(d
,tmp
.remove())));
942 errln((UnicodeString
)"Can't create " + loc
.getName() + " date instance");
949 #endif /* #if !UCONFIG_NO_FORMATTING */