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