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