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 "buddhist",
147 "buddhist",
148 "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 Locale loc("th_TH_TRADITIONAL"); // legacy
474
475 simpleTest(loc, expect, expectDate, status);
476 }
477 status = U_ZERO_ERROR;
478 {
479 UnicodeString expect = CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
480 " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e1e.\\u0e28. 2544");
481 UDate expectDate = 999932400000.0;
482 Locale loc("th_TH@calendar=buddhist");
483
484 simpleTest(loc, expect, expectDate, status);
485 }
486 status = U_ZERO_ERROR;
487 {
488 UnicodeString expect = CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
489 " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e04.\\u0e28. 2001");
490 UDate expectDate = 999932400000.0;
491 Locale loc("th_TH@calendar=gregorian");
492
493 simpleTest(loc, expect, expectDate, status);
494 }
495 status = U_ZERO_ERROR;
496 {
497 UnicodeString expect = CharsToUnicodeString("\\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48"
498 " 8 \\u0E01\\u0E31\\u0e19\\u0e22\\u0e32\\u0e22\\u0e19 \\u0e04.\\u0e28. 2001");
499 UDate expectDate = 999932400000.0;
500 Locale loc("th_TH_TRADITIONAL@calendar=gregorian");
501
502 simpleTest(loc, expect, expectDate, status);
503 }
504 }
505
506 // TaiwanFormat has been moved to testdata/format.txt
507
508
TestJapaneseFormat()509 void IntlCalendarTest::TestJapaneseFormat() {
510 LocalPointer<Calendar> cal;
511 UErrorCode status = U_ZERO_ERROR;
512 cal.adoptInstead(Calendar::createInstance("ja_JP@calendar=japanese", status));
513 CHECK(status, UnicodeString("Creating ja_JP@calendar=japanese calendar"));
514
515 LocalPointer<Calendar> cal2(cal->clone());
516 cal.adoptInstead(nullptr);
517
518 // Test simple parse/format with adopt
519
520 UDate aDate = 999932400000.0;
521 SimpleDateFormat fmt(UnicodeString("MMMM d, yy G"), Locale("en_US@calendar=japanese"), status);
522 SimpleDateFormat fmt2(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status);
523 CHECK(status, "creating date format instance");
524 UnicodeString str;
525 fmt2.format(aDate, str);
526 logln(UnicodeString() + "Test Date: " + str);
527 str.remove();
528 fmt.format(aDate, str);
529 logln(UnicodeString() + "as Japanese Calendar: " + str);
530 UnicodeString expected("September 8, 13 Heisei");
531 if(str != expected) {
532 errln("Expected " + expected + " but got " + str);
533 }
534 UDate otherDate = fmt.parse(expected, status);
535 if(otherDate != aDate) {
536 UnicodeString str3;
537 ParsePosition pp;
538 fmt.parse(expected, *cal2, pp);
539 fmt.format(otherDate, str3);
540 errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " + otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) );
541
542 } else {
543 logln("Parsed OK: " + expected);
544 }
545
546 // Test parse with incomplete information
547 SimpleDateFormat fmti(UnicodeString("G y"), Locale("en_US@calendar=japanese"), status);
548 aDate = -3197117222000.0;
549 CHECK(status, "creating date format instance");
550 str.remove();
551 fmt2.format(aDate, str);
552 logln(UnicodeString() + "Test Date: " + str);
553 str.remove();
554 fmti.format(aDate, str);
555 logln(UnicodeString() + "as Japanese Calendar: " + str);
556 expected = u"Meiji 1";
557 if(str != expected) {
558 errln("Expected " + expected + " but got " + str);
559 }
560 otherDate = fmti.parse(expected, status);
561 if(otherDate != aDate) {
562 UnicodeString str3;
563 ParsePosition pp;
564 fmti.parse(expected, *cal2, pp);
565 fmti.format(otherDate, str3);
566 errln("Parse incorrect of " + expected + " - wanted " + aDate + " but got " + " = " +
567 otherDate + ", " + str3 + " = " + CalendarTest::calToStr(*cal2) );
568 } else {
569 logln("Parsed OK: " + expected);
570 }
571
572 CHECK(status, "Error occurred");
573
574 // Now, try in Japanese
575 {
576 UnicodeString expect = CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5\\u571f\\u66dc\\u65e5");
577 UDate expectDate = 999932400000.0; // Testing a recent date
578 Locale loc("ja_JP@calendar=japanese");
579
580 status = U_ZERO_ERROR;
581 simpleTest(loc, expect, expectDate, status);
582 }
583 {
584 UnicodeString expect = CharsToUnicodeString("\\u5e73\\u621013\\u5e749\\u67088\\u65e5\\u571f\\u66dc\\u65e5");
585 UDate expectDate = 999932400000.0; // Testing a recent date
586 Locale loc("ja_JP@calendar=japanese");
587
588 status = U_ZERO_ERROR;
589 simpleTest(loc, expect, expectDate, status);
590 }
591 {
592 UnicodeString expect = CharsToUnicodeString("\\u5b89\\u6c385\\u5e747\\u67084\\u65e5\\u6728\\u66dc\\u65e5");
593 UDate expectDate = -6106032422000.0; // 1776-07-04T00:00:00Z-075258
594 Locale loc("ja_JP@calendar=japanese");
595
596 status = U_ZERO_ERROR;
597 simpleTest(loc, expect, expectDate, status);
598
599 }
600 { // Jitterbug 1869 - this is an ambiguous era. (Showa 64 = Jan 6 1989, but Showa could be 2 other eras) )
601 UnicodeString expect = CharsToUnicodeString("\\u662d\\u548c64\\u5e741\\u67086\\u65e5\\u91d1\\u66dc\\u65e5");
602 UDate expectDate = 600076800000.0;
603 Locale loc("ja_JP@calendar=japanese");
604
605 status = U_ZERO_ERROR;
606 simpleTest(loc, expect, expectDate, status);
607
608 }
609 { // 1989 Jan 9 Monday = Heisei 1; full is Gy年M月d日EEEE => 平成元年1月9日月曜日
610 UnicodeString expect = CharsToUnicodeString("\\u5E73\\u6210\\u5143\\u5E741\\u67089\\u65E5\\u6708\\u66DC\\u65E5");
611 UDate expectDate = 600336000000.0;
612 Locale loc("ja_JP@calendar=japanese");
613
614 status = U_ZERO_ERROR;
615 simpleTest(loc, expect, expectDate, status);
616
617 }
618 { // This Feb 29th falls on a leap year by gregorian year, but not by Japanese year.
619 UnicodeString expect = CharsToUnicodeString("\\u5EB7\\u6B632\\u5e742\\u670829\\u65e5\\u65e5\\u66dc\\u65e5");
620 UDate expectDate = -16214400422000.0; // 1456-03-09T00:00Z-075258
621 Locale loc("ja_JP@calendar=japanese");
622
623 status = U_ZERO_ERROR;
624 simpleTest(loc, expect, expectDate, status);
625
626 }
627 }
628
TestJapanese3860()629 void IntlCalendarTest::TestJapanese3860()
630 {
631 LocalPointer<Calendar> cal;
632 UErrorCode status = U_ZERO_ERROR;
633 cal.adoptInstead(Calendar::createInstance("ja_JP@calendar=japanese", status));
634 CHECK(status, UnicodeString("Creating ja_JP@calendar=japanese calendar"));
635 LocalPointer<Calendar> cal2(cal->clone());
636 SimpleDateFormat fmt2(UnicodeString("HH:mm:ss.S MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status);
637 UnicodeString str;
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(UnicodeString("y/M/d"), Locale("ja_JP@calendar=japanese"), status);
647 CHECK(status, "creating date format instance");
648 UErrorCode s2 = U_ZERO_ERROR;
649 cal2->clear();
650 UnicodeString samplestr("1/5/9");
651 logln(UnicodeString() + "Test Year: " + samplestr);
652 aDate = fmt.parse(samplestr, s2);
653 ParsePosition pp=0;
654 fmt.parse(samplestr, *cal2, pp);
655 CHECK(s2, "parsing the 1/5/9 string");
656 logln("*cal2 after 159 parse:");
657 str.remove();
658 fmt2.format(aDate, str);
659 logln(UnicodeString() + "as Gregorian Calendar: " + str);
660
661 cal2->setTime(aDate, s2);
662 int32_t gotYear = cal2->get(UCAL_YEAR, s2);
663 int32_t gotEra = cal2->get(UCAL_ERA, s2);
664 int32_t expectYear = 1;
665 int32_t expectEra = JapaneseCalendar::getCurrentEra();
666 if((gotYear!=1) || (gotEra != expectEra)) {
667 errln(UnicodeString("parse "+samplestr+" of 'y/M/d' as Japanese Calendar, expected year ") + expectYear +
668 UnicodeString(" and era ") + expectEra +", but got year " + gotYear + " and era " + gotEra + " (Gregorian:" + str +")");
669 } else {
670 logln(UnicodeString() + " year: " + gotYear + ", era: " + gotEra);
671 }
672 }
673
674 {
675 // Test simple parse/format with adopt
676 UDate aDate = 0;
677
678 // Test parse with missing era (should default to current era, heisei)
679 // Test parse with incomplete information
680 logln("Testing parse w/ just year...");
681 SimpleDateFormat fmt(UnicodeString("y"), Locale("ja_JP@calendar=japanese"), status);
682 CHECK(status, "creating date format instance");
683 UErrorCode s2 = U_ZERO_ERROR;
684 cal2->clear();
685 UnicodeString samplestr("1");
686 logln(UnicodeString() + "Test Year: " + samplestr);
687 aDate = fmt.parse(samplestr, s2);
688 ParsePosition pp=0;
689 fmt.parse(samplestr, *cal2, pp);
690 CHECK(s2, "parsing the 1 string");
691 logln("*cal2 after 1 parse:");
692 str.remove();
693 fmt2.format(aDate, str);
694 logln(UnicodeString() + "as Gregorian Calendar: " + str);
695
696 cal2->setTime(aDate, s2);
697 int32_t gotYear = cal2->get(UCAL_YEAR, s2);
698 int32_t gotEra = cal2->get(UCAL_ERA, s2);
699 int32_t expectYear = 1;
700 int32_t expectEra = JapaneseCalendar::getCurrentEra();
701 if((gotYear!=1) || (gotEra != expectEra)) {
702 errln(UnicodeString("parse "+samplestr+" of 'y' as Japanese Calendar, expected year ") + expectYear +
703 UnicodeString(" and era ") + expectEra +", but got year " + gotYear + " and era " + gotEra + " (Gregorian:" + str +")");
704 } else {
705 logln(UnicodeString() + " year: " + gotYear + ", era: " + gotEra);
706 }
707 }
708 }
709
TestForceGannenNumbering()710 void IntlCalendarTest::TestForceGannenNumbering()
711 {
712 UErrorCode status;
713 const char* locID = "ja_JP@calendar=japanese";
714 Locale loc(locID);
715 UDate refDate = 600336000000.0; // 1989 Jan 9 Monday = Heisei 1
716 UnicodeString patText(u"Gy年M月d日",-1);
717 UnicodeString patNumr(u"GGGGGy/MM/dd",-1);
718 UnicodeString skelText(u"yMMMM",-1);
719
720 // Test Gannen year forcing
721 status = U_ZERO_ERROR;
722 LocalPointer<SimpleDateFormat> testFmt1(new SimpleDateFormat(patText, loc, status));
723 LocalPointer<SimpleDateFormat> testFmt2(new SimpleDateFormat(patNumr, loc, status));
724 if (U_FAILURE(status)) {
725 dataerrln("Fail in new SimpleDateFormat locale %s: %s", locID, u_errorName(status));
726 } else {
727 UnicodeString testString1, testString2;
728 testString1 = testFmt1->format(refDate, testString1);
729 if (testString1.length() < 3 || testString1.charAt(2) != 0x5143) {
730 errln(UnicodeString("Formatting year 1 in created text style, got " + testString1 + " but expected 3rd char to be 0x5143"));
731 }
732 testString2 = testFmt2->format(refDate, testString2);
733 if (testString2.length() < 2 || testString2.charAt(1) != 0x0031) {
734 errln(UnicodeString("Formatting year 1 in created numeric style, got " + testString2 + " but expected 2nd char to be 1"));
735 }
736 // Now switch the patterns and verify that Gannen use follows the pattern
737 testFmt1->applyPattern(patNumr);
738 testString1.remove();
739 testString1 = testFmt1->format(refDate, testString1);
740 if (testString1.length() < 2 || testString1.charAt(1) != 0x0031) {
741 errln(UnicodeString("Formatting year 1 in applied numeric style, got " + testString1 + " but expected 2nd char to be 1"));
742 }
743 testFmt2->applyPattern(patText);
744 testString2.remove();
745 testString2 = testFmt2->format(refDate, testString2);
746 if (testString2.length() < 3 || testString2.charAt(2) != 0x5143) {
747 errln(UnicodeString("Formatting year 1 in applied text style, got " + testString2 + " but expected 3rd char to be 0x5143"));
748 }
749 }
750
751 // Test disabling of Gannen year forcing
752 status = U_ZERO_ERROR;
753 LocalPointer<DateTimePatternGenerator> dtpgen(DateTimePatternGenerator::createInstance(loc, status));
754 if (U_FAILURE(status)) {
755 dataerrln("Fail in DateTimePatternGenerator::createInstance locale %s: %s", locID, u_errorName(status));
756 } else {
757 UnicodeString pattern = dtpgen->getBestPattern(skelText, status);
758 if (U_FAILURE(status)) {
759 dataerrln("Fail in DateTimePatternGenerator::getBestPattern locale %s: %s", locID, u_errorName(status));
760 } else {
761 // Use override string of ""
762 LocalPointer<SimpleDateFormat> testFmt3(new SimpleDateFormat(pattern, UnicodeString(""), loc, status));
763 if (U_FAILURE(status)) {
764 dataerrln("Fail in new SimpleDateFormat locale %s: %s", locID, u_errorName(status));
765 } else {
766 UnicodeString testString3;
767 testString3 = testFmt3->format(refDate, testString3);
768 if (testString3.length() < 3 || testString3.charAt(2) != 0x0031) {
769 errln(UnicodeString("Formatting year 1 with Gannen disabled, got " + testString3 + " but expected 3rd char to be 1"));
770 }
771 }
772 }
773 }
774 }
775
776 /**
777 * Verify the Persian Calendar.
778 */
TestPersian()779 void IntlCalendarTest::TestPersian() {
780 UDate timeA = Calendar::getNow();
781
782 Calendar *cal;
783 UErrorCode status = U_ZERO_ERROR;
784 cal = Calendar::createInstance("fa_IR@calendar=persian", status);
785 CHECK(status, UnicodeString("Creating fa_IR@calendar=persian calendar"));
786 // Sanity check the calendar
787 UDate timeB = Calendar::getNow();
788 UDate timeCal = cal->getTime(status);
789
790 if(!(timeA <= timeCal) || !(timeCal <= timeB)) {
791 errln((UnicodeString)"Error: Calendar time " + timeCal +
792 " is not within sampled times [" + timeA + " to " + timeB + "]!");
793 }
794 // end sanity check
795
796 // Test various dates to be sure of validity
797 int32_t data[] = {
798 1925, 4, 24, 1304, 2, 4,
799 2011, 1, 11, 1389, 10, 21,
800 1986, 2, 25, 1364, 12, 6,
801 1934, 3, 14, 1312, 12, 23,
802
803 2090, 3, 19, 1468, 12, 29,
804 2007, 2, 22, 1385, 12, 3,
805 1969, 12, 31, 1348, 10, 10,
806 1945, 11, 12, 1324, 8, 21,
807 1925, 3, 31, 1304, 1, 11,
808
809 1996, 3, 19, 1374, 12, 29,
810 1996, 3, 20, 1375, 1, 1,
811 1997, 3, 20, 1375, 12, 30,
812 1997, 3, 21, 1376, 1, 1,
813
814 2008, 3, 19, 1386, 12, 29,
815 2008, 3, 20, 1387, 1, 1,
816 2004, 3, 19, 1382, 12, 29,
817 2004, 3, 20, 1383, 1, 1,
818
819 2006, 3, 20, 1384, 12, 29,
820 2006, 3, 21, 1385, 1, 1,
821
822 2005, 4, 20, 1384, 1, 31,
823 2005, 4, 21, 1384, 2, 1,
824 2005, 5, 21, 1384, 2, 31,
825 2005, 5, 22, 1384, 3, 1,
826 2005, 6, 21, 1384, 3, 31,
827 2005, 6, 22, 1384, 4, 1,
828 2005, 7, 22, 1384, 4, 31,
829 2005, 7, 23, 1384, 5, 1,
830 2005, 8, 22, 1384, 5, 31,
831 2005, 8, 23, 1384, 6, 1,
832 2005, 9, 22, 1384, 6, 31,
833 2005, 9, 23, 1384, 7, 1,
834 2005, 10, 22, 1384, 7, 30,
835 2005, 10, 23, 1384, 8, 1,
836 2005, 11, 21, 1384, 8, 30,
837 2005, 11, 22, 1384, 9, 1,
838 2005, 12, 21, 1384, 9, 30,
839 2005, 12, 22, 1384, 10, 1,
840 2006, 1, 20, 1384, 10, 30,
841 2006, 1, 21, 1384, 11, 1,
842 2006, 2, 19, 1384, 11, 30,
843 2006, 2, 20, 1384, 12, 1,
844 2006, 3, 20, 1384, 12, 29,
845 2006, 3, 21, 1385, 1, 1,
846
847 // The 2820-year cycle arithmetical algorithm would fail this one.
848 2025, 3, 21, 1404, 1, 1,
849
850 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1
851 };
852
853 Calendar *grego = Calendar::createInstance("fa_IR@calendar=gregorian", status);
854 for (int32_t i=0; data[i]!=-1; ) {
855 int32_t gregYear = data[i++];
856 int32_t gregMonth = data[i++]-1;
857 int32_t gregDay = data[i++];
858 int32_t persYear = data[i++];
859 int32_t persMonth = data[i++]-1;
860 int32_t persDay = data[i++];
861
862 // Test conversion from Persian dates
863 grego->clear();
864 grego->set(gregYear, gregMonth, gregDay);
865
866 cal->clear();
867 cal->set(persYear, persMonth, persDay);
868
869 UDate persTime = cal->getTime(status);
870 UDate gregTime = grego->getTime(status);
871
872 if (persTime != gregTime) {
873 errln(UnicodeString("Expected ") + gregTime + " but got " + persTime);
874 }
875
876 // Test conversion to Persian dates
877 cal->clear();
878 cal->setTime(gregTime, status);
879
880 int32_t computedYear = cal->get(UCAL_YEAR, status);
881 int32_t computedMonth = cal->get(UCAL_MONTH, status);
882 int32_t computedDay = cal->get(UCAL_DATE, status);
883
884 if ((persYear != computedYear) ||
885 (persMonth != computedMonth) ||
886 (persDay != computedDay)) {
887 errln(UnicodeString("Expected ") + persYear + "/" + (persMonth+1) + "/" + persDay +
888 " but got " + computedYear + "/" + (computedMonth+1) + "/" + computedDay);
889 }
890
891 }
892
893 delete cal;
894 delete grego;
895 }
896
TestPersianFormat()897 void IntlCalendarTest::TestPersianFormat() {
898 UErrorCode status = U_ZERO_ERROR;
899 SimpleDateFormat fmt(UnicodeString("MMMM d, yyyy G"), Locale(" en_US@calendar=persian"), status);
900 CHECK(status, "creating date format instance");
901 SimpleDateFormat fmt2(UnicodeString("MMMM d, yyyy G"), Locale("en_US@calendar=gregorian"), status);
902 CHECK(status, "creating gregorian date format instance");
903 UnicodeString gregorianDate("January 18, 2007 AD");
904 UDate aDate = fmt2.parse(gregorianDate, status);
905 UnicodeString str;
906 fmt.format(aDate, str);
907 logln(UnicodeString() + "as Persian Calendar: " + escape(str));
908 UnicodeString expected("Dey 28, 1385 AP");
909 if(str != expected) {
910 errln("Expected " + escape(expected) + " but got " + escape(str));
911 }
912 UDate otherDate = fmt.parse(expected, status);
913 if(otherDate != aDate) {
914 UnicodeString str3;
915 fmt.format(otherDate, str3);
916 errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate + ", " + escape(str3));
917 } else {
918 logln("Parsed OK: " + expected);
919 }
920 // Two digit year parsing problem #4732
921 fmt.applyPattern("yy-MM-dd");
922 str.remove();
923 fmt.format(aDate, str);
924 expected.setTo("85-10-28");
925 if(str != expected) {
926 errln("Expected " + escape(expected) + " but got " + escape(str));
927 }
928 otherDate = fmt.parse(expected, status);
929 if (otherDate != aDate) {
930 errln("Parse incorrect of " + escape(expected) + " - wanted " + aDate + " but got " + otherDate);
931 } else {
932 logln("Parsed OK: " + expected);
933 }
934
935 CHECK(status, "Error occurred testing Persian Calendar in English ");
936 }
937
TestConsistencyGregorian()938 void IntlCalendarTest::TestConsistencyGregorian() {
939 checkConsistency("en@calendar=gregorian");
940 }
TestConsistencyIndian()941 void IntlCalendarTest::TestConsistencyIndian() {
942 checkConsistency("en@calendar=indian");
943 }
TestConsistencyHebrew()944 void IntlCalendarTest::TestConsistencyHebrew() {
945 checkConsistency("en@calendar=hebrew");
946 }
TestConsistencyIslamic()947 void IntlCalendarTest::TestConsistencyIslamic() {
948 checkConsistency("en@calendar=islamic");
949 }
TestConsistencyIslamicRGSA()950 void IntlCalendarTest::TestConsistencyIslamicRGSA() {
951 checkConsistency("en@calendar=islamic-rgsa");
952 }
TestConsistencyIslamicTBLA()953 void IntlCalendarTest::TestConsistencyIslamicTBLA() {
954 checkConsistency("en@calendar=islamic-tbla");
955 }
TestConsistencyIslamicUmalqura()956 void IntlCalendarTest::TestConsistencyIslamicUmalqura() {
957 checkConsistency("en@calendar=islamic-umalqura");
958 }
TestConsistencyIslamicCivil()959 void IntlCalendarTest::TestConsistencyIslamicCivil() {
960 checkConsistency("en@calendar=islamic-civil");
961 }
TestConsistencyCoptic()962 void IntlCalendarTest::TestConsistencyCoptic() {
963 checkConsistency("en@calendar=coptic");
964 }
TestConsistencyEthiopic()965 void IntlCalendarTest::TestConsistencyEthiopic() {
966 checkConsistency("en@calendar=ethiopic");
967 }
TestConsistencyROC()968 void IntlCalendarTest::TestConsistencyROC() {
969 checkConsistency("en@calendar=roc");
970 }
TestConsistencyChinese()971 void IntlCalendarTest::TestConsistencyChinese() {
972 checkConsistency("en@calendar=chinese");
973 }
TestConsistencyDangi()974 void IntlCalendarTest::TestConsistencyDangi() {
975 checkConsistency("en@calendar=dangi");
976 }
TestConsistencyPersian()977 void IntlCalendarTest::TestConsistencyPersian() {
978 checkConsistency("en@calendar=persian");
979 }
TestConsistencyBuddhist()980 void IntlCalendarTest::TestConsistencyBuddhist() {
981 checkConsistency("en@calendar=buddhist");
982 }
TestConsistencyJapanese()983 void IntlCalendarTest::TestConsistencyJapanese() {
984 checkConsistency("en@calendar=japanese");
985 }
TestConsistencyEthiopicAmeteAlem()986 void IntlCalendarTest::TestConsistencyEthiopicAmeteAlem() {
987 checkConsistency("en@calendar=ethiopic-amete-alem");
988 }
checkConsistency(const char * locale)989 void IntlCalendarTest::checkConsistency(const char* locale) {
990 // Check 2.5 years in quick mode and 8000 years in exhaustive mode.
991 int32_t numOfDaysToTest = static_cast<int32_t>((quick ? 2.5 : 8000) * 365);
992 constexpr int32_t msInADay = 1000*60*60*24;
993 std::string msg("TestConsistency");
994 IcuTestErrorCode status(*this, (msg + locale).c_str());
995 // g is just for debugging messages.
996 std::unique_ptr<Calendar> g(Calendar::createInstance("en", status));
997 g->setTimeZone(*(TimeZone::getGMT()));
998 std::unique_ptr<Calendar> base(Calendar::createInstance(locale, status));
999 if (status.errIfFailureAndReset("Cannot create calendar %s", locale)) {
1000 return;
1001 }
1002 UDate test = Calendar::getNow();
1003 base->setTimeZone(*(TimeZone::getGMT()));
1004 int32_t j;
1005 int lastDay = 1;
1006 std::unique_ptr<Calendar> r(base->clone());
1007 for (j = 0; j < numOfDaysToTest; j++, test -= msInADay) {
1008 status.errIfFailureAndReset();
1009 g->setTime(test, status);
1010 if (status.errIfFailureAndReset("Cannot set time")) {
1011 return;
1012 }
1013 base->clear();
1014 base->setTime(test, status);
1015 if (status.errIfFailureAndReset("Cannot set time")) {
1016 return;
1017 }
1018 // First, we verify the date from base is decrease one day from the
1019 // last day unless the last day is 1.
1020 int32_t cday = base->get(UCAL_DATE, status);
1021 if (U_FAILURE(status)) {
1022 UErrorCode localStatus = U_ZERO_ERROR;
1023 if (status.errIfFailureAndReset(
1024 "Cannot get the %dth date for %f %d %d/%d/%d\n",
1025 j,
1026 test,
1027 g->get(UCAL_ERA, localStatus),
1028 g->get(UCAL_YEAR, localStatus),
1029 (g->get(UCAL_MONTH, localStatus) + 1),
1030 g->get(UCAL_DATE, localStatus))) {
1031 return;
1032 }
1033 }
1034 if (lastDay == 1) {
1035 lastDay = cday;
1036 } else {
1037 if (cday != lastDay-1) {
1038 // Ignore if it is the last day before Gregorian Calendar switch on
1039 // 1582 Oct 4
1040 if (g->get(UCAL_YEAR, status) == 1582 &&
1041 (g->get(UCAL_MONTH, status) + 1) == 10 &&
1042 g->get(UCAL_DATE, status) == 4) {
1043 lastDay = 5;
1044 } else {
1045 errln((UnicodeString)
1046 "Day is not one less from previous date for "
1047 "Gregorian(e=" + g->get(UCAL_ERA, status) + " " +
1048 g->get(UCAL_YEAR, status) + "/" +
1049 (g->get(UCAL_MONTH, status) + 1) + "/" +
1050 g->get(UCAL_DATE, status) + ") " + locale + "(" +
1051 base->get(UCAL_ERA, status) + " " +
1052 base->get(UCAL_YEAR, status) + "/" +
1053 (base->get(UCAL_MONTH, status) + 1 ) + "/" +
1054 base->get(UCAL_DATE, status) + ")");
1055 status.errIfFailureAndReset();
1056 return;
1057 }
1058 }
1059 lastDay--;
1060 }
1061 // Second, we verify the month is in reasonale range.
1062 int32_t cmonth = base->get(UCAL_MONTH, status);
1063 if (cmonth < 0 || cmonth > 13) {
1064 errln((UnicodeString)
1065 "Month is out of range Gregorian(e=" +
1066 g->get(UCAL_ERA, status) + " " +
1067 g->get(UCAL_YEAR, status) + "/" +
1068 (g->get(UCAL_MONTH, status) + 1) + "/" +
1069 g->get(UCAL_DATE, status) + ") " + locale + "(" +
1070 base->get(UCAL_ERA, status) + " " +
1071 base->get(UCAL_YEAR, status) + "/" +
1072 (base->get(UCAL_MONTH, status) + 1 ) + "/" +
1073 base->get(UCAL_DATE, status) + ")");
1074 status.errIfFailureAndReset();
1075 return;
1076 }
1077 // Third, we verify the set function can round trip the time back.
1078 r->clear();
1079 for (int32_t f = 0; f < UCAL_FIELD_COUNT; f++) {
1080 UCalendarDateFields ut = (UCalendarDateFields)f;
1081 r->set(ut, base->get(ut, status));
1082 }
1083 UDate result = r->getTime(status);
1084 if (status.errIfFailureAndReset("Cannot get time %s", locale)) {
1085 return;
1086 }
1087 if (test != result) {
1088 errln((UnicodeString)"Round trip conversion produces different "
1089 "time from " + test + " to " + result + " delta: " +
1090 (result - test) +
1091 " Gregorian(e=" + g->get(UCAL_ERA, status) + " " +
1092 g->get(UCAL_YEAR, status) + "/" +
1093 (g->get(UCAL_MONTH, status) + 1) + "/" +
1094 g->get(UCAL_DATE, status) + ") ");
1095 status.errIfFailureAndReset();
1096 return;
1097 }
1098 }
1099 status.errIfFailureAndReset();
1100 }
1101
simpleTest(const Locale & loc,const UnicodeString & expect,UDate expectDate,UErrorCode & status)1102 void IntlCalendarTest::simpleTest(const Locale& loc, const UnicodeString& expect, UDate expectDate, UErrorCode& status)
1103 {
1104 UnicodeString tmp;
1105 UDate d;
1106 DateFormat *fmt0 = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull);
1107
1108 logln("Try format/parse of " + (UnicodeString)loc.getName());
1109 DateFormat *fmt2 = DateFormat::createDateInstance(DateFormat::kFull, loc);
1110 if(fmt2) {
1111 fmt2->format(expectDate, tmp);
1112 logln(escape(tmp) + " ( in locale " + loc.getName() + ")");
1113 if(tmp != expect) {
1114 errln(UnicodeString("Failed to format " ) + loc.getName() + " expected " + escape(expect) + " got " + escape(tmp) );
1115 }
1116
1117 d = fmt2->parse(expect,status);
1118 CHECK(status, "Error occurred parsing " + UnicodeString(loc.getName()));
1119 if(d != expectDate) {
1120 fmt2->format(d,tmp);
1121 errln(UnicodeString("Failed to parse " ) + escape(expect) + ", " + loc.getName() + " expect " + (double)expectDate + " got " + (double)d + " " + escape(tmp));
1122 logln( "wanted " + escape(fmt0->format(expectDate,tmp.remove())) + " but got " + escape(fmt0->format(d,tmp.remove())));
1123 }
1124 delete fmt2;
1125 } else {
1126 errln((UnicodeString)"Can't create " + loc.getName() + " date instance");
1127 }
1128 delete fmt0;
1129 }
1130
TestBug21043Indian()1131 void IntlCalendarTest::TestBug21043Indian() {
1132 IcuTestErrorCode status(*this, "TestBug21043Indian");
1133 std::unique_ptr<Calendar> cal(
1134 Calendar::createInstance("en@calendar=indian", status));
1135 std::unique_ptr<Calendar> g(
1136 Calendar::createInstance("en@calendar=gregorian", status));
1137 // set to 10 BC
1138 g->set(UCAL_ERA, 0);
1139 g->set(UCAL_YEAR, 10);
1140 g->set(UCAL_MONTH, 1);
1141 g->set(UCAL_DATE, 1);
1142 cal->setTime(g->getTime(status), status);
1143 int32_t m = cal->get(UCAL_MONTH, status);
1144 if (m < 0 || m > 11) {
1145 errln(
1146 u"Month should be between 0 and 11 in India calendar");
1147 }
1148 }
1149
TestBug21044Hebrew()1150 void IntlCalendarTest::TestBug21044Hebrew() {
1151 IcuTestErrorCode status(*this, "TestBug21044Hebrew");
1152 std::unique_ptr<Calendar> cal(
1153 Calendar::createInstance("en@calendar=hebrew", status));
1154 std::unique_ptr<Calendar> g(
1155 Calendar::createInstance("en@calendar=gregorian", status));
1156 // set to 3771/10/27 BC which is before 3760 BC.
1157 g->set(UCAL_ERA, 0);
1158 g->set(UCAL_YEAR, 3771);
1159 g->set(UCAL_MONTH, 9);
1160 g->set(UCAL_DATE, 27);
1161 cal->setTime(g->getTime(status), status);
1162
1163 if (status.errIfFailureAndReset(
1164 "Cannot set date. Got error %s", u_errorName(status))) {
1165 return;
1166 }
1167 int32_t y = cal->get(UCAL_YEAR, status);
1168 int32_t m = cal->get(UCAL_MONTH, status);
1169 int32_t d = cal->get(UCAL_DATE, status);
1170 if (status.errIfFailureAndReset(
1171 "Cannot get date. Got error %s", u_errorName(status))) {
1172 return;
1173 }
1174 if (y > 0 || m < 0 || m > 12 || d < 0 || d > 32) {
1175 errln((UnicodeString)"Out of rage!\nYear " + y + " should be " +
1176 "negative number before 1AD.\nMonth " + m + " should " +
1177 "be between 0 and 12 in Hebrew calendar.\nDate " + d +
1178 " should be between 0 and 32 in Islamic calendar.");
1179 }
1180 }
1181
TestBug21045Islamic()1182 void IntlCalendarTest::TestBug21045Islamic() {
1183 IcuTestErrorCode status(*this, "TestBug21045Islamic");
1184 std::unique_ptr<Calendar> cal(
1185 Calendar::createInstance("en@calendar=islamic", status));
1186 std::unique_ptr<Calendar> g(
1187 Calendar::createInstance("en@calendar=gregorian", status));
1188 // set to 500 AD before 622 AD.
1189 g->set(UCAL_ERA, 1);
1190 g->set(UCAL_YEAR, 500);
1191 g->set(UCAL_MONTH, 1);
1192 g->set(UCAL_DATE, 1);
1193 cal->setTime(g->getTime(status), status);
1194 int32_t m = cal->get(UCAL_MONTH, status);
1195 if (m < 0 || m > 11) {
1196 errln(u"Month should be between 1 and 12 in Islamic calendar");
1197 }
1198 }
1199
TestBug21046IslamicUmalqura()1200 void IntlCalendarTest::TestBug21046IslamicUmalqura() {
1201 IcuTestErrorCode status(*this, "TestBug21046IslamicUmalqura");
1202 std::unique_ptr<Calendar> cal(
1203 Calendar::createInstance("en@calendar=islamic-umalqura", status));
1204 std::unique_ptr<Calendar> g(
1205 Calendar::createInstance("en@calendar=gregorian", status));
1206 // set to 195366 BC
1207 g->set(UCAL_ERA, 0);
1208 g->set(UCAL_YEAR, 195366);
1209 g->set(UCAL_MONTH, 1);
1210 g->set(UCAL_DATE, 1);
1211 cal->setTime(g->getTime(status), status);
1212 int32_t y = cal->get(UCAL_YEAR, status);
1213 int32_t m = cal->get(UCAL_MONTH, status);
1214 int32_t d = cal->get(UCAL_DATE, status);
1215 if (y > 0 || m < 0 || m > 11 || d < 0 || d > 32) {
1216 errln((UnicodeString)"Out of rage!\nYear " + y + " should be " +
1217 "negative number before 1AD.\nMonth " + m + " should " +
1218 "be between 0 and 11 in Islamic calendar.\nDate " + d +
1219 " should be between 0 and 32 in Islamic calendar.");
1220 }
1221 }
1222 #undef CHECK
1223
1224 #endif /* #if !UCONFIG_NO_FORMATTING */
1225
1226 //eof
1227