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