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