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