Imported Upstream version 58.1
[platform/upstream/icu.git] / source / test / intltest / incaltst.cpp
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
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
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
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                             "buddhist",           
122                             "buddhist",           
123                             "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  */
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
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  */
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  */
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  */
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
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
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
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  */
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
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
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