]>
git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/incaltst.cpp
1 /***********************************************************************
3 * Copyright (c) 1997-2004, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 ***********************************************************************/
7 /* Test Internationalized Calendars for C++ */
9 #include "unicode/utypes.h"
11 #include "unicode/locid.h"
13 #if !UCONFIG_NO_FORMATTING
18 #define CHECK(status, msg) \
19 if (U_FAILURE(status)) { \
20 errln((UnicodeString(u_errorName(status)) + UnicodeString(" : " ) )+ msg); \
25 static UnicodeString
escape( const UnicodeString
&src
)
29 for (int32_t i
= 0; i
< src
.length(); ++i
) {
34 dst
+= UnicodeString("[");
36 sprintf(buf
, "%#x", c
);
37 dst
+= UnicodeString(buf
);
38 dst
+= UnicodeString("]");
47 #include "unicode/gregocal.h"
48 #include "unicode/smpdtfmt.h"
49 #include "unicode/simpletz.h"
51 // *****************************************************************************
52 // class IntlCalendarTest
53 // *****************************************************************************
54 //--- move to CalendarTest?
56 static const double JULIAN_EPOCH
= -210866760000000.;
59 // Turn this on to dump the calendar fields
60 #define U_DEBUG_DUMPCALS
63 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
66 void IntlCalendarTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
68 if (exec
) logln("TestSuite IntlCalendarTest");
71 CASE(1,TestGregorian
);
74 CASE(4,TestBuddhistFormat
);
75 CASE(5,TestJapaneseFormat
);
76 default: name
= ""; break;
82 // ---------------------------------------------------------------------------------
86 * Test various API methods for API completeness.
89 IntlCalendarTest::TestTypes()
92 UErrorCode status
= U_ZERO_ERROR
;
94 const char *locs
[40] = { "en_US_VALLEYGIRL",
95 "en_US_VALLEYGIRL@collation=phonebook;calendar=japanese",
96 "en_US_VALLEYGIRL@collation=phonebook;calendar=gregorian",
97 "ja_JP@calendar=japanese",
98 "th_TH@calendar=buddhist",
101 "th_TH_TRADITIONAL@calendar=gregorian",
103 const char *types
[40] = { "gregorian",
113 for(j
=0;locs
[j
];j
++) {
114 logln(UnicodeString("Creating calendar of locale ") + locs
[j
]);
115 status
= U_ZERO_ERROR
;
116 c
= Calendar::createInstance(locs
[j
], status
);
117 CHECK(status
, "creating '" + UnicodeString(locs
[j
]) + "' calendar");
118 if(U_SUCCESS(status
)) {
119 logln(UnicodeString(" type is ") + c
->getType());
120 if(strcmp(c
->getType(), types
[j
])) {
121 errln(UnicodeString(locs
[j
]) + UnicodeString("Calendar type ") + c
->getType() + " instead of " + types
[j
]);
131 * Run a test of a quasi-Gregorian calendar. This is a calendar
132 * that behaves like a Gregorian but has different year/era mappings.
133 * The int[] data array should have the format:
135 * { era, year, gregorianYear, month, dayOfMonth, ... ... , -1 }
137 void IntlCalendarTest::quasiGregorianTest(Calendar
& cal
, const Locale
& gcl
, const int32_t *data
) {
138 UErrorCode status
= U_ZERO_ERROR
;
139 // As of JDK 1.4.1_01, using the Sun JDK GregorianCalendar as
140 // a reference throws us off by one hour. This is most likely
141 // due to the JDK 1.4 incorporation of historical time zones.
142 //java.util.Calendar grego = java.util.Calendar.getInstance();
143 Calendar
*grego
= Calendar::createInstance(gcl
, status
);
145 int32_t tz1
= cal
.get(UCAL_ZONE_OFFSET
,status
);
146 int32_t tz2
= grego
-> get (UCAL_ZONE_OFFSET
, status
);
148 errln((UnicodeString
)"cal's tz " + tz1
+ " != grego's tz " + tz2
);
151 for (int32_t i
=0; data
[i
]!=-1; ) {
152 int32_t era
= data
[i
++];
153 int32_t year
= data
[i
++];
154 int32_t gregorianYear
= data
[i
++];
155 int32_t month
= data
[i
++];
156 int32_t dayOfMonth
= data
[i
++];
159 grego
->set(gregorianYear
, month
, dayOfMonth
);
160 UDate D
= grego
->getTime(status
);
163 cal
.set(UCAL_ERA
, era
);
164 cal
.set(year
, month
, dayOfMonth
);
165 UDate d
= cal
.getTime(status
);
166 #ifdef U_DEBUG_DUMPCALS
167 logln((UnicodeString
)"cal : " + CalendarTest::calToStr(cal
));
168 logln((UnicodeString
)"grego: " + CalendarTest::calToStr(*grego
));
171 logln(UnicodeString("OK: ") + era
+ ":" + year
+ "/" + (month
+1) + "/" + dayOfMonth
+
172 " => " + d
+ " (" + UnicodeString(cal
.getType()) + ")");
174 errln(UnicodeString("Fail: (fields to millis)") + era
+ ":" + year
+ "/" + (month
+1) + "/" + dayOfMonth
+
175 " => " + d
+ ", expected " + D
+ " (" + UnicodeString(cal
.getType()) + "Off by: " + (d
-D
));
178 // Now, set the gregorian millis on the other calendar
180 cal
.setTime(D
, status
);
181 int e
= cal
.get(UCAL_ERA
, status
);
182 int y
= cal
.get(UCAL_YEAR
, status
);
183 #ifdef U_DEBUG_DUMPCALS
184 logln((UnicodeString
)"cal : " + CalendarTest::calToStr(cal
));
185 logln((UnicodeString
)"grego: " + CalendarTest::calToStr(*grego
));
187 if (y
== year
&& e
== era
) {
188 logln((UnicodeString
)"OK: " + D
+ " => " + cal
.get(UCAL_ERA
, status
) + ":" +
189 cal
.get(UCAL_YEAR
, status
) + "/" +
190 (cal
.get(UCAL_MONTH
, status
)+1) + "/" + cal
.get(UCAL_DATE
, status
) + " (" + UnicodeString(cal
.getType()) + ")");
192 errln((UnicodeString
)"Fail: (millis to fields)" + D
+ " => " + cal
.get(UCAL_ERA
, status
) + ":" +
193 cal
.get(UCAL_YEAR
, status
) + "/" +
194 (cal
.get(UCAL_MONTH
, status
)+1) + "/" + cal
.get(UCAL_DATE
, status
) +
195 ", expected " + era
+ ":" + year
+ "/" + (month
+1) + "/" +
196 dayOfMonth
+ " (" + UnicodeString(cal
.getType()));
200 CHECK(status
, "err during quasiGregorianTest()");
203 // Verify that Gregorian works like Gregorian
204 void IntlCalendarTest::TestGregorian() {
205 UDate timeA
= Calendar::getNow();
207 GregorianCalendar::AD
, 1868, 1868, UCAL_SEPTEMBER
, 8,
208 GregorianCalendar::AD
, 1868, 1868, UCAL_SEPTEMBER
, 9,
209 GregorianCalendar::AD
, 1869, 1869, UCAL_JUNE
, 4,
210 GregorianCalendar::AD
, 1912, 1912, UCAL_JULY
, 29,
211 GregorianCalendar::AD
, 1912, 1912, UCAL_JULY
, 30,
212 GregorianCalendar::AD
, 1912, 1912, UCAL_AUGUST
, 1,
213 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
217 UErrorCode status
= U_ZERO_ERROR
;
218 cal
= Calendar::createInstance(/*"de_DE", */ status
);
219 CHECK(status
, UnicodeString("Creating de_CH calendar"));
220 // Sanity check the calendar
221 UDate timeB
= Calendar::getNow();
222 UDate timeCal
= cal
->getTime(status
);
224 if(!(timeA
<= timeCal
) || !(timeCal
<= timeB
)) {
225 errln((UnicodeString
)"Error: Calendar time " + timeCal
+
226 " is not within sampled times [" + timeA
+ " to " + timeB
+ "]!");
230 // Note, the following is a good way to test the sanity of the constructed calendars,
231 // using Collation as a delay-loop:
233 // $ intltest format/IntlCalendarTest collate/G7CollationTest format/IntlCalendarTest
235 quasiGregorianTest(*cal
,Locale("fr_FR"),data
);
240 * Verify that BuddhistCalendar shifts years to Buddhist Era but otherwise
241 * behaves like GregorianCalendar.
243 void IntlCalendarTest::TestBuddhist() {
244 // BE 2542 == 1999 CE
245 UDate timeA
= Calendar::getNow();
248 0, // B. era [928479600000]
254 0, // B. era [-79204842000000]
257 UCAL_FEBRUARY
, // month
260 0, // test month calculation: 4795 BE = 4252 AD is a leap year, but 4795 AD is not.
261 4795, // BE [72018057600000]
266 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
269 UErrorCode status
= U_ZERO_ERROR
;
270 cal
= Calendar::createInstance("th_TH@calendar=buddhist", status
);
271 CHECK(status
, UnicodeString("Creating th_TH@calendar=buddhist calendar"));
273 // Sanity check the calendar
274 UDate timeB
= Calendar::getNow();
275 UDate timeCal
= cal
->getTime(status
);
277 if(!(timeA
<= timeCal
) || !(timeCal
<= timeB
)) {
278 errln((UnicodeString
)"Error: Calendar time " + timeCal
+
279 " is not within sampled times [" + timeA
+ " to " + timeB
+ "]!");
284 quasiGregorianTest(*cal
,Locale("th_TH"),data
);
289 * Verify that JapaneseCalendar shifts years to Japanese Eras but otherwise
290 * behaves like GregorianCalendar.
292 void IntlCalendarTest::TestJapanese() {
293 UDate timeA
= Calendar::getNow();
295 /* Sorry.. japancal.h is private! */
296 #define JapaneseCalendar_MEIJI 232
297 #define JapaneseCalendar_TAISHO 233
298 #define JapaneseCalendar_SHOWA 234
299 #define JapaneseCalendar_HEISEI 235
301 // BE 2542 == 1999 CE
303 // Jera Jyr Gyear m d
304 JapaneseCalendar_MEIJI
, 1, 1868, UCAL_SEPTEMBER
, 8,
305 JapaneseCalendar_MEIJI
, 1, 1868, UCAL_SEPTEMBER
, 9,
306 JapaneseCalendar_MEIJI
, 2, 1869, UCAL_JUNE
, 4,
307 JapaneseCalendar_MEIJI
, 45, 1912, UCAL_JULY
, 29,
308 JapaneseCalendar_TAISHO
, 1, 1912, UCAL_JULY
, 30,
309 JapaneseCalendar_TAISHO
, 1, 1912, UCAL_AUGUST
, 1,
311 // new tests (not in java)
312 JapaneseCalendar_SHOWA
, 64, 1989, UCAL_JANUARY
, 7, // Test current era transition (different code path than others)
313 JapaneseCalendar_HEISEI
, 1, 1989, UCAL_JANUARY
, 8,
314 JapaneseCalendar_HEISEI
, 1, 1989, UCAL_JANUARY
, 9,
315 JapaneseCalendar_HEISEI
, 1, 1989, UCAL_DECEMBER
, 20,
316 JapaneseCalendar_HEISEI
, 15, 2003, UCAL_MAY
, 22,
317 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
321 UErrorCode status
= U_ZERO_ERROR
;
322 cal
= Calendar::createInstance("ja_JP@calendar=japanese", status
);
323 CHECK(status
, UnicodeString("Creating ja_JP@calendar=japanese calendar"));
324 // Sanity check the calendar
325 UDate timeB
= Calendar::getNow();
326 UDate timeCal
= cal
->getTime(status
);
328 if(!(timeA
<= timeCal
) || !(timeCal
<= timeB
)) {
329 errln((UnicodeString
)"Error: Calendar time " + timeCal
+
330 " is not within sampled times [" + timeA
+ " to " + timeB
+ "]!");
333 quasiGregorianTest(*cal
,Locale("ja_JP"),data
);
337 void IntlCalendarTest::TestBuddhistFormat() {
338 UErrorCode status
= U_ZERO_ERROR
;
340 // Test simple parse/format with adopt
342 // First, a contrived english test..
343 UDate aDate
= 999932400000.0;
344 SimpleDateFormat
*fmt
= new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=buddhist"), status
);
345 CHECK(status
, "creating date format instance");
346 SimpleDateFormat
*fmt2
= new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status
);
347 CHECK(status
, "creating gregorian date format instance");
349 errln("Coudln't create en_US instance");
352 fmt2
->format(aDate
, str
);
353 logln(UnicodeString() + "Test Date: " + str
);
355 fmt
->format(aDate
, str
);
356 logln(UnicodeString() + "as Buddhist Calendar: " + escape(str
));
357 UnicodeString
expected("September 8, 2544 BE");
358 if(str
!= expected
) {
359 errln("Expected " + escape(expected
) + " but got " + escape(str
));
361 UDate otherDate
= fmt
->parse(expected
, status
);
362 if(otherDate
!= aDate
) {
364 fmt
->format(otherDate
, str3
);
365 errln("Parse incorrect of " + escape(expected
) + " - wanted " + aDate
+ " but got " + otherDate
+ ", " + escape(str3
));
367 logln("Parsed OK: " + expected
);
373 CHECK(status
, "Error occured testing Buddhist Calendar in English ");
375 status
= U_ZERO_ERROR
;
378 UnicodeString expect
= CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
379 " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e1e.\\u0e28. 2544");
380 UDate expectDate
= 999932400000.0;
381 Locale
loc("th_TH_TRADITIONAL"); // legacy
383 simpleTest(loc
, expect
, expectDate
, status
);
385 status
= U_ZERO_ERROR
;
387 UnicodeString expect
= CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
388 " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e1e.\\u0e28. 2544");
389 UDate expectDate
= 999932400000.0;
390 Locale
loc("th_TH@calendar=buddhist");
392 simpleTest(loc
, expect
, expectDate
, status
);
394 status
= U_ZERO_ERROR
;
396 UnicodeString expect
= CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
397 " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e04.\\u0e28. 2001");
398 UDate expectDate
= 999932400000.0;
399 Locale
loc("th_TH@calendar=gregorian");
401 simpleTest(loc
, expect
, expectDate
, status
);
403 status
= U_ZERO_ERROR
;
405 UnicodeString expect
= CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
406 " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e04.\\u0e28. 2001");
407 UDate expectDate
= 999932400000.0;
408 Locale
loc("th_TH_TRADITIONAL@calendar=gregorian");
410 simpleTest(loc
, expect
, expectDate
, status
);
415 void IntlCalendarTest::TestJapaneseFormat() {
417 UErrorCode status
= U_ZERO_ERROR
;
418 cal
= Calendar::createInstance("ja_JP_TRADITIONAL", status
);
419 CHECK(status
, UnicodeString("Creating ja_JP_TRADITIONAL calendar"));
421 Calendar
*cal2
= cal
->clone();
425 // Test simple parse/format with adopt
427 UDate aDate
= 999932400000.0;
428 SimpleDateFormat
*fmt
= new SimpleDateFormat(UnicodeString("MMMM d, yy G"), Locale("en_US@calendar=japanese"), status
);
429 SimpleDateFormat
*fmt2
= new SimpleDateFormat(UnicodeString("MMMM d, yy G"), Locale("en_US@calendar=gregorian"), status
);
430 CHECK(status
, "creating date format instance");
432 errln("Coudln't create en_US instance");
435 fmt2
->format(aDate
, str
);
436 logln(UnicodeString() + "Test Date: " + str
);
438 fmt
->format(aDate
, str
);
439 logln(UnicodeString() + "as Japanese Calendar: " + str
);
440 UnicodeString
expected("September 8, 13 Heisei");
441 if(str
!= expected
) {
442 errln("Expected " + expected
+ " but got " + str
);
444 UDate otherDate
= fmt
->parse(expected
, status
);
445 if(otherDate
!= aDate
) {
448 fmt
->parse(expected
, *cal2
, pp
);
449 fmt
->format(otherDate
, str3
);
450 errln("Parse incorrect of " + expected
+ " - wanted " + aDate
+ " but got " + " = " + otherDate
+ ", " + str3
+ " = " + CalendarTest::calToStr(*cal2
) );
453 logln("Parsed OK: " + expected
);
458 // Test parse with incomplete information
459 fmt
= new SimpleDateFormat(UnicodeString("G y"), Locale("en_US@calendar=japanese"), status
);
460 aDate
= -3197120400000.;
461 CHECK(status
, "creating date format instance");
463 errln("Coudln't create en_US instance");
466 fmt2
->format(aDate
, str
);
467 logln(UnicodeString() + "Test Date: " + str
);
469 fmt
->format(aDate
, str
);
470 logln(UnicodeString() + "as Japanese Calendar: " + str
);
471 UnicodeString
expected("Meiji 1");
472 if(str
!= expected
) {
473 errln("Expected " + expected
+ " but got " + str
);
475 UDate otherDate
= fmt
->parse(expected
, status
);
476 if(otherDate
!= aDate
) {
479 fmt
->parse(expected
, *cal2
, pp
);
480 fmt
->format(otherDate
, str3
);
481 errln("Parse incorrect of " + expected
+ " - wanted " + aDate
+ " but got " + " = " +
482 otherDate
+ ", " + str3
+ " = " + CalendarTest::calToStr(*cal2
) );
484 logln("Parsed OK: " + expected
);
491 CHECK(status
, "Error occured");
493 // Now, try in Japanese
495 UnicodeString expect
= CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5\\u571f\\u66dc\\u65e5");
496 UDate expectDate
= 999932400000.0; // Testing a recent date
497 Locale
loc("ja_JP@calendar=japanese");
499 status
= U_ZERO_ERROR
;
500 simpleTest(loc
, expect
, expectDate
, status
);
503 UnicodeString expect
= CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5\\u571f\\u66dc\\u65e5");
504 UDate expectDate
= 999932400000.0; // Testing a recent date
505 Locale
loc("ja_JP_TRADITIONAL"); // legacy
507 status
= U_ZERO_ERROR
;
508 simpleTest(loc
, expect
, expectDate
, status
);
511 UnicodeString expect
= CharsToUnicodeString("\\u5b89\\u6c385\\u5e747\\u67084\\u65e5\\u6728\\u66dc\\u65e5");
512 UDate expectDate
= -6106035600000.0;
513 Locale
loc("ja_JP@calendar=japanese");
515 status
= U_ZERO_ERROR
;
516 simpleTest(loc
, expect
, expectDate
, status
);
519 { // Jitterbug 1869 - this is an ambiguous era. (Showa 64 = Jan 6 1989, but Showa could be 2 other eras) )
520 UnicodeString expect
= CharsToUnicodeString("\\u662d\\u548c64\\u5e741\\u67086\\u65e5\\u91d1\\u66dc\\u65e5");
521 UDate expectDate
= 600076800000.0;
522 Locale
loc("ja_JP@calendar=japanese");
524 status
= U_ZERO_ERROR
;
525 simpleTest(loc
, expect
, expectDate
, status
);
528 { // This Feb 29th falls on a leap year by gregorian year, but not by Japanese year.
529 UnicodeString expect
= CharsToUnicodeString("\\u5EB7\\u6B632\\u5e742\\u670829\\u65e5\\u65e5\\u66dc\\u65e5");
530 // Add -1:00 to the following for historical TZ - aliu
531 UDate expectDate
= -16214403600000.0; // courtesy of date format round trip test
532 Locale
loc("ja_JP@calendar=japanese");
534 status
= U_ZERO_ERROR
;
535 simpleTest(loc
, expect
, expectDate
, status
);
540 void IntlCalendarTest::simpleTest(const Locale
& loc
, const UnicodeString
& expect
, UDate expectDate
, UErrorCode
& status
)
544 DateFormat
*fmt0
= DateFormat::createDateTimeInstance(DateFormat::kFull
, DateFormat::kFull
);
546 logln("Try format/parse of " + (UnicodeString
)loc
.getName());
547 DateFormat
*fmt2
= DateFormat::createDateInstance(DateFormat::kFull
, loc
);
549 fmt2
->format(expectDate
, tmp
);
550 logln(escape(tmp
) + " ( in locale " + loc
.getName() + ")");
552 errln(UnicodeString("Failed to format " ) + loc
.getName() + " expected " + escape(expect
) + " got " + escape(tmp
) );
555 d
= fmt2
->parse(expect
,status
);
556 CHECK(status
, "Error occured parsing " + UnicodeString(loc
.getName()));
557 if(d
!= expectDate
) {
559 errln(UnicodeString("Failed to parse " ) + escape(expect
) + ", " + loc
.getName() + " expect " + (double)expectDate
+ " got " + (double)d
+ " " + escape(tmp
));
560 logln( "wanted " + escape(fmt0
->format(expectDate
,tmp
.remove())) + " but got " + escape(fmt0
->format(d
,tmp
.remove())));
564 errln((UnicodeString
)"Can't create " + loc
.getName() + " date instance");
571 #endif /* #if !UCONFIG_NO_FORMATTING */