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