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