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-2016, International Business Machines Corporation
6 * and others. All Rights Reserved.
7 ************************************************************************/
8#include "unicode/utypes.h"
9
10#if !UCONFIG_NO_FORMATTING
11
12#include "caltest.h"
13#include "unicode/dtfmtsym.h"
14#include "unicode/gregocal.h"
15#include "unicode/localpointer.h"
16#include "hebrwcal.h"
17#include "unicode/smpdtfmt.h"
18#include "unicode/simpletz.h"
19#include "dbgutil.h"
20#include "unicode/udat.h"
21#include "unicode/ustring.h"
22#include "cstring.h"
23#include "unicode/localpointer.h"
24#include "islamcal.h"
25
26#define mkcstr(U) u_austrcpy(calloc(8, u_strlen(U) + 1), U)
27
28#define TEST_CHECK_STATUS { \
29    if (U_FAILURE(status)) { \
30        if (status == U_MISSING_RESOURCE_ERROR) { \
31            dataerrln("%s:%d: Test failure.  status=%s", __FILE__, __LINE__, u_errorName(status)); \
32        } else { \
33            errln("%s:%d: Test failure.  status=%s", __FILE__, __LINE__, u_errorName(status)); \
34        } return;}}
35
36#define TEST_CHECK_STATUS_LOCALE(testlocale) { \
37    if (U_FAILURE(status)) { \
38        if (status == U_MISSING_RESOURCE_ERROR) { \
39            dataerrln("%s:%d: Test failure, locale %s.  status=%s", __FILE__, __LINE__, testlocale, u_errorName(status)); \
40        } else { \
41            errln("%s:%d: Test failure, locale %s.  status=%s", __FILE__, __LINE__, testlocale, u_errorName(status)); \
42        } return;}}
43
44#define TEST_ASSERT(expr) {if ((expr)==FALSE) {errln("%s:%d: Test failure \n", __FILE__, __LINE__);};}
45
46// *****************************************************************************
47// class CalendarTest
48// *****************************************************************************
49
50UnicodeString CalendarTest::calToStr(const Calendar & cal)
51{
52  UnicodeString out;
53  UErrorCode status = U_ZERO_ERROR;
54  int i;
55  UDate d;
56  for(i = 0;i<UCAL_FIELD_COUNT;i++) {
57    out += (UnicodeString("") + fieldName((UCalendarDateFields)i) + "=" +  cal.get((UCalendarDateFields)i, status) + UnicodeString(" "));
58  }
59  out += "[" + UnicodeString(cal.getType()) + "]";
60
61  if(cal.inDaylightTime(status)) {
62    out += UnicodeString(" (in DST), zone=");
63  }
64  else {
65    out += UnicodeString(", zone=");
66  }
67
68  UnicodeString str2;
69  out += cal.getTimeZone().getDisplayName(str2);
70  d = cal.getTime(status);
71  out += UnicodeString(" :","") + d;
72
73  return out;
74}
75
76void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
77{
78    if (exec) logln("TestSuite TestCalendar");
79    switch (index) {
80        case 0:
81            name = "TestDOW943";
82            if (exec) {
83                logln("TestDOW943---"); logln("");
84                TestDOW943();
85            }
86            break;
87        case 1:
88            name = "TestClonesUnique908";
89            if (exec) {
90                logln("TestClonesUnique908---"); logln("");
91                TestClonesUnique908();
92            }
93            break;
94        case 2:
95            name = "TestGregorianChange768";
96            if (exec) {
97                logln("TestGregorianChange768---"); logln("");
98                TestGregorianChange768();
99            }
100            break;
101        case 3:
102            name = "TestDisambiguation765";
103            if (exec) {
104                logln("TestDisambiguation765---"); logln("");
105                TestDisambiguation765();
106            }
107            break;
108        case 4:
109            name = "TestGMTvsLocal4064654";
110            if (exec) {
111                logln("TestGMTvsLocal4064654---"); logln("");
112                TestGMTvsLocal4064654();
113            }
114            break;
115        case 5:
116            name = "TestAddSetOrder621";
117            if (exec) {
118                logln("TestAddSetOrder621---"); logln("");
119                TestAddSetOrder621();
120            }
121            break;
122        case 6:
123            name = "TestAdd520";
124            if (exec) {
125                logln("TestAdd520---"); logln("");
126                TestAdd520();
127            }
128            break;
129        case 7:
130            name = "TestFieldSet4781";
131            if (exec) {
132                logln("TestFieldSet4781---"); logln("");
133                TestFieldSet4781();
134            }
135            break;
136        case 8:
137            name = "TestSerialize337";
138            if (exec) {
139                logln("TestSerialize337---"); logln("");
140            //  TestSerialize337();
141            }
142            break;
143        case 9:
144            name = "TestSecondsZero121";
145            if (exec) {
146                logln("TestSecondsZero121---"); logln("");
147                TestSecondsZero121();
148            }
149            break;
150        case 10:
151            name = "TestAddSetGet0610";
152            if (exec) {
153                logln("TestAddSetGet0610---"); logln("");
154                TestAddSetGet0610();
155            }
156            break;
157        case 11:
158            name = "TestFields060";
159            if (exec) {
160                logln("TestFields060---"); logln("");
161                TestFields060();
162            }
163            break;
164        case 12:
165            name = "TestEpochStartFields";
166            if (exec) {
167                logln("TestEpochStartFields---"); logln("");
168                TestEpochStartFields();
169            }
170            break;
171        case 13:
172            name = "TestDOWProgression";
173            if (exec) {
174                logln("TestDOWProgression---"); logln("");
175                TestDOWProgression();
176            }
177            break;
178        case 14:
179            name = "TestGenericAPI";
180            if (exec) {
181                logln("TestGenericAPI---"); logln("");
182                TestGenericAPI();
183            }
184            break;
185        case 15:
186            name = "TestAddRollExtensive";
187            if (exec) {
188                logln("TestAddRollExtensive---"); logln("");
189                TestAddRollExtensive();
190            }
191            break;
192        case 16:
193            name = "TestDOW_LOCALandYEAR_WOY";
194            if (exec) {
195                logln("TestDOW_LOCALandYEAR_WOY---"); logln("");
196                TestDOW_LOCALandYEAR_WOY();
197            }
198            break;
199        case 17:
200            name = "TestWOY";
201            if (exec) {
202                logln("TestWOY---"); logln("");
203                TestWOY();
204            }
205            break;
206        case 18:
207            name = "TestRog";
208            if (exec) {
209                logln("TestRog---"); logln("");
210                TestRog();
211            }
212            break;
213        case 19:
214           name = "TestYWOY";
215            if (exec) {
216                logln("TestYWOY---"); logln("");
217                TestYWOY();
218            }
219            break;
220        case 20:
221          name = "TestJD";
222          if(exec) {
223            logln("TestJD---"); logln("");
224            TestJD();
225          }
226          break;
227        case 21:
228          name = "TestDebug";
229          if(exec) {
230            logln("TestDebug---"); logln("");
231            TestDebug();
232          }
233          break;
234        case 22:
235          name = "Test6703";
236          if(exec) {
237            logln("Test6703---"); logln("");
238            Test6703();
239          }
240          break;
241        case 23:
242          name = "Test3785";
243          if(exec) {
244            logln("Test3785---"); logln("");
245            Test3785();
246          }
247          break;
248        case 24:
249          name = "Test1624";
250          if(exec) {
251            logln("Test1624---"); logln("");
252            Test1624();
253          }
254          break;
255        case 25:
256          name = "TestTimeStamp";
257          if(exec) {
258            logln("TestTimeStamp---"); logln("");
259            TestTimeStamp();
260          }
261          break;
262        case 26:
263          name = "TestISO8601";
264          if(exec) {
265            logln("TestISO8601---"); logln("");
266            TestISO8601();
267          }
268          break;
269        case 27:
270          name = "TestAmbiguousWallTimeAPIs";
271          if(exec) {
272            logln("TestAmbiguousWallTimeAPIs---"); logln("");
273            TestAmbiguousWallTimeAPIs();
274          }
275          break;
276        case 28:
277          name = "TestRepeatedWallTime";
278          if(exec) {
279            logln("TestRepeatedWallTime---"); logln("");
280            TestRepeatedWallTime();
281          }
282          break;
283        case 29:
284          name = "TestSkippedWallTime";
285          if(exec) {
286            logln("TestSkippedWallTime---"); logln("");
287            TestSkippedWallTime();
288          }
289          break;
290        case 30:
291          name = "TestCloneLocale";
292          if(exec) {
293            logln("TestCloneLocale---"); logln("");
294            TestCloneLocale();
295          }
296          break;
297        case 31:
298          name = "TestIslamicUmAlQura";
299          if(exec) {
300            logln("TestIslamicUmAlQura---"); logln("");
301            TestIslamicUmAlQura();
302          }
303          break;
304        case 32:
305          name = "TestIslamicTabularDates";
306          if(exec) {
307            logln("TestIslamicTabularDates---"); logln("");
308            TestIslamicTabularDates();
309          }
310          break;
311        case 33:
312          name = "TestHebrewMonthValidation";
313          if(exec) {
314            logln("TestHebrewMonthValidation---"); logln("");
315            TestHebrewMonthValidation();
316          }
317          break;
318        case 34:
319          name = "TestWeekData";
320          if(exec) {
321            logln("TestWeekData---"); logln("");
322            TestWeekData();
323          }
324          break;
325        case 35:
326          name = "TestAddAcrossZoneTransition";
327          if(exec) {
328            logln("TestAddAcrossZoneTransition---"); logln("");
329            TestAddAcrossZoneTransition();
330          }
331          break;
332        case 36:
333          name = "TestChineseCalendarMapping";
334          if(exec) {
335            logln("TestChineseCalendarMapping---"); logln("");
336            TestChineseCalendarMapping();
337          }
338          break;
339        default: name = ""; break;
340    }
341}
342
343// ---------------------------------------------------------------------------------
344
345UnicodeString CalendarTest::fieldName(UCalendarDateFields f) {
346    switch (f) {
347#define FIELD_NAME_STR(x) case x: return (#x+5)
348      FIELD_NAME_STR( UCAL_ERA );
349      FIELD_NAME_STR( UCAL_YEAR );
350      FIELD_NAME_STR( UCAL_MONTH );
351      FIELD_NAME_STR( UCAL_WEEK_OF_YEAR );
352      FIELD_NAME_STR( UCAL_WEEK_OF_MONTH );
353      FIELD_NAME_STR( UCAL_DATE );
354      FIELD_NAME_STR( UCAL_DAY_OF_YEAR );
355      FIELD_NAME_STR( UCAL_DAY_OF_WEEK );
356      FIELD_NAME_STR( UCAL_DAY_OF_WEEK_IN_MONTH );
357      FIELD_NAME_STR( UCAL_AM_PM );
358      FIELD_NAME_STR( UCAL_HOUR );
359      FIELD_NAME_STR( UCAL_HOUR_OF_DAY );
360      FIELD_NAME_STR( UCAL_MINUTE );
361      FIELD_NAME_STR( UCAL_SECOND );
362      FIELD_NAME_STR( UCAL_MILLISECOND );
363      FIELD_NAME_STR( UCAL_ZONE_OFFSET );
364      FIELD_NAME_STR( UCAL_DST_OFFSET );
365      FIELD_NAME_STR( UCAL_YEAR_WOY );
366      FIELD_NAME_STR( UCAL_DOW_LOCAL );
367      FIELD_NAME_STR( UCAL_EXTENDED_YEAR );
368      FIELD_NAME_STR( UCAL_JULIAN_DAY );
369      FIELD_NAME_STR( UCAL_MILLISECONDS_IN_DAY );
370#undef FIELD_NAME_STR
371    default:
372        return UnicodeString("") + ((int32_t)f);
373    }
374}
375
376/**
377 * Test various API methods for API completeness.
378 */
379void
380CalendarTest::TestGenericAPI()
381{
382    UErrorCode status = U_ZERO_ERROR;
383    UDate d;
384    UnicodeString str;
385    UBool eq = FALSE,b4 = FALSE,af = FALSE;
386
387    UDate when = date(90, UCAL_APRIL, 15);
388
389    UnicodeString tzid("TestZone");
390    int32_t tzoffset = 123400;
391
392    SimpleTimeZone *zone = new SimpleTimeZone(tzoffset, tzid);
393    Calendar *cal = Calendar::createInstance(zone->clone(), status);
394    if (failure(status, "Calendar::createInstance #1", TRUE)) return;
395
396    if (*zone != cal->getTimeZone()) errln("FAIL: Calendar::getTimeZone failed");
397
398    Calendar *cal2 = Calendar::createInstance(cal->getTimeZone(), status);
399    if (failure(status, "Calendar::createInstance #2")) return;
400    cal->setTime(when, status);
401    cal2->setTime(when, status);
402    if (failure(status, "Calendar::setTime")) return;
403
404    if (!(*cal == *cal2)) errln("FAIL: Calendar::operator== failed");
405    if ((*cal != *cal2))  errln("FAIL: Calendar::operator!= failed");
406    if (!cal->equals(*cal2, status) ||
407        cal->before(*cal2, status) ||
408        cal->after(*cal2, status) ||
409        U_FAILURE(status)) errln("FAIL: equals/before/after failed");
410
411    logln(UnicodeString("cal=")  +cal->getTime(status)  + UnicodeString(calToStr(*cal)));
412    logln(UnicodeString("cal2=")  +cal2->getTime(status)  + UnicodeString(calToStr(*cal2)));
413    logln("cal2->setTime(when+1000)");
414    cal2->setTime(when + 1000, status);
415    logln(UnicodeString("cal2=")  +cal2->getTime(status)  + UnicodeString(calToStr(*cal2)));
416
417    if (failure(status, "Calendar::setTime")) return;
418    if (cal->equals(*cal2, status) ||
419        cal2->before(*cal, status) ||
420        cal->after(*cal2, status) ||
421        U_FAILURE(status)) errln("FAIL: equals/before/after failed after setTime(+1000)");
422
423    logln("cal->roll(UCAL_SECOND)");
424    cal->roll(UCAL_SECOND, (UBool) TRUE, status);
425    logln(UnicodeString("cal=")  +cal->getTime(status)  + UnicodeString(calToStr(*cal)));
426    cal->roll(UCAL_SECOND, (int32_t)0, status);
427    logln(UnicodeString("cal=")  +cal->getTime(status)  + UnicodeString(calToStr(*cal)));
428    if (failure(status, "Calendar::roll")) return;
429
430    if (!(eq=cal->equals(*cal2, status)) ||
431        (b4=cal->before(*cal2, status)) ||
432        (af=cal->after(*cal2, status)) ||
433        U_FAILURE(status)) {
434      errln("FAIL: equals[%c]/before[%c]/after[%c] failed after roll 1 second [should be T/F/F]",
435            eq?'T':'F',
436            b4?'T':'F',
437            af?'T':'F');
438      logln(UnicodeString("cal=")  +cal->getTime(status)  + UnicodeString(calToStr(*cal)));
439      logln(UnicodeString("cal2=")  +cal2->getTime(status)  + UnicodeString(calToStr(*cal2)));
440    }
441
442    // Roll back to January
443    cal->roll(UCAL_MONTH, (int32_t)(1 + UCAL_DECEMBER - cal->get(UCAL_MONTH, status)), status);
444    if (failure(status, "Calendar::roll")) return;
445    if (cal->equals(*cal2, status) ||
446        cal2->before(*cal, status) ||
447        cal->after(*cal2, status) ||
448        U_FAILURE(status)) errln("FAIL: equals/before/after failed after rollback to January");
449
450    TimeZone *z = cal->orphanTimeZone();
451    if (z->getID(str) != tzid ||
452        z->getRawOffset() != tzoffset)
453        errln("FAIL: orphanTimeZone failed");
454
455    int32_t i;
456    for (i=0; i<2; ++i)
457    {
458        UBool lenient = ( i > 0 );
459        cal->setLenient(lenient);
460        if (lenient != cal->isLenient()) errln("FAIL: setLenient/isLenient failed");
461        // Later: Check for lenient behavior
462    }
463
464    for (i=UCAL_SUNDAY; i<=UCAL_SATURDAY; ++i)
465    {
466        cal->setFirstDayOfWeek((UCalendarDaysOfWeek)i);
467        if (cal->getFirstDayOfWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
468        UErrorCode aStatus = U_ZERO_ERROR;
469        if (cal->getFirstDayOfWeek(aStatus) != i || U_FAILURE(aStatus)) errln("FAIL: getFirstDayOfWeek(status) failed");
470    }
471
472    for (i=1; i<=7; ++i)
473    {
474        cal->setMinimalDaysInFirstWeek((uint8_t)i);
475        if (cal->getMinimalDaysInFirstWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
476    }
477
478    for (i=0; i<UCAL_FIELD_COUNT; ++i)
479    {
480        if (cal->getMinimum((UCalendarDateFields)i) > cal->getGreatestMinimum((UCalendarDateFields)i))
481            errln(UnicodeString("FAIL: getMinimum larger than getGreatestMinimum for field ") + i);
482        if (cal->getLeastMaximum((UCalendarDateFields)i) > cal->getMaximum((UCalendarDateFields)i))
483            errln(UnicodeString("FAIL: getLeastMaximum larger than getMaximum for field ") + i);
484        if (cal->getMinimum((UCalendarDateFields)i) >= cal->getMaximum((UCalendarDateFields)i))
485            errln(UnicodeString("FAIL: getMinimum not less than getMaximum for field ") + i);
486    }
487
488    cal->adoptTimeZone(TimeZone::createDefault());
489    cal->clear();
490    cal->set(1984, 5, 24);
491    if (cal->getTime(status) != date(84, 5, 24) || U_FAILURE(status))
492        errln("FAIL: Calendar::set(3 args) failed");
493
494    cal->clear();
495    cal->set(1985, 3, 2, 11, 49);
496    if (cal->getTime(status) != date(85, 3, 2, 11, 49) || U_FAILURE(status))
497        errln("FAIL: Calendar::set(5 args) failed");
498
499    cal->clear();
500    cal->set(1995, 9, 12, 1, 39, 55);
501    if (cal->getTime(status) != date(95, 9, 12, 1, 39, 55) || U_FAILURE(status))
502        errln("FAIL: Calendar::set(6 args) failed");
503
504    cal->getTime(status);
505    if (failure(status, "Calendar::getTime")) return;
506    for (i=0; i<UCAL_FIELD_COUNT; ++i)
507    {
508        switch(i) {
509            case UCAL_YEAR: case UCAL_MONTH: case UCAL_DATE:
510            case UCAL_HOUR_OF_DAY: case UCAL_MINUTE: case UCAL_SECOND:
511            case UCAL_EXTENDED_YEAR:
512              if (!cal->isSet((UCalendarDateFields)i)) errln("FAIL: Calendar::isSet F, should be T " + fieldName((UCalendarDateFields)i));
513                break;
514            default:
515              if (cal->isSet((UCalendarDateFields)i)) errln("FAIL: Calendar::isSet = T, should be F  " + fieldName((UCalendarDateFields)i));
516        }
517        cal->clear((UCalendarDateFields)i);
518        if (cal->isSet((UCalendarDateFields)i)) errln("FAIL: Calendar::clear/isSet failed " + fieldName((UCalendarDateFields)i));
519    }
520
521    if(cal->getActualMinimum(Calendar::SECOND, status) != 0){
522        errln("Calendar is suppose to return 0 for getActualMinimum");
523    }
524
525    Calendar *cal3 = Calendar::createInstance(status);
526    cal3->roll(Calendar::SECOND, (int32_t)0, status);
527    if (failure(status, "Calendar::roll(EDateFields, int32_t, UErrorCode)")) return;
528
529    delete cal;
530    delete cal2;
531    delete cal3;
532
533    int32_t count;
534    const Locale* loc = Calendar::getAvailableLocales(count);
535    if (count < 1 || loc == 0)
536    {
537        dataerrln("FAIL: getAvailableLocales failed");
538    }
539    else
540    {
541        for (i=0; i<count; ++i)
542        {
543            cal = Calendar::createInstance(loc[i], status);
544            if (U_FAILURE(status)) {
545                errcheckln(status, UnicodeString("FAIL: Calendar::createInstance #3, locale ") +  loc[i].getName() + " , error " + u_errorName(status));
546                return;
547            }
548            delete cal;
549        }
550    }
551
552    cal = Calendar::createInstance(TimeZone::createDefault(), Locale::getEnglish(), status);
553    if (failure(status, "Calendar::createInstance #4")) return;
554    delete cal;
555
556    cal = Calendar::createInstance(*zone, Locale::getEnglish(), status);
557    if (failure(status, "Calendar::createInstance #5")) return;
558    delete cal;
559
560    GregorianCalendar *gc = new GregorianCalendar(*zone, status);
561    if (failure(status, "new GregorianCalendar")) return;
562    delete gc;
563
564    gc = new GregorianCalendar(Locale::getEnglish(), status);
565    if (failure(status, "new GregorianCalendar")) return;
566    delete gc;
567
568    gc = new GregorianCalendar(Locale::getEnglish(), status);
569    delete gc;
570
571    gc = new GregorianCalendar(*zone, Locale::getEnglish(), status);
572    if (failure(status, "new GregorianCalendar")) return;
573    delete gc;
574
575    gc = new GregorianCalendar(zone, status);
576    if (failure(status, "new GregorianCalendar")) return;
577    delete gc;
578
579    gc = new GregorianCalendar(1998, 10, 14, 21, 43, status);
580    if (gc->getTime(status) != (d =date(98, 10, 14, 21, 43) )|| U_FAILURE(status))
581      errln("FAIL: new GregorianCalendar(ymdhm) failed with " + UnicodeString(u_errorName(status)) + ",  cal="  + gc->getTime(status)  + UnicodeString(calToStr(*gc)) + ", d=" + d);
582    else
583      logln(UnicodeString("GOOD: cal=")  +gc->getTime(status)  + UnicodeString(calToStr(*gc)) + ", d=" + d);
584    delete gc;
585
586    gc = new GregorianCalendar(1998, 10, 14, 21, 43, 55, status);
587    if (gc->getTime(status) != (d=date(98, 10, 14, 21, 43, 55)) || U_FAILURE(status))
588      errln("FAIL: new GregorianCalendar(ymdhms) failed with " + UnicodeString(u_errorName(status)));
589
590    GregorianCalendar gc2(Locale::getEnglish(), status);
591    if (failure(status, "new GregorianCalendar")) return;
592    gc2 = *gc;
593    if (gc2 != *gc || !(gc2 == *gc)) errln("FAIL: GregorianCalendar assignment/operator==/operator!= failed");
594    delete gc;
595    delete z;
596
597    /* Code coverage for Calendar class. */
598    cal = Calendar::createInstance(status);
599    if (failure(status, "Calendar::createInstance #6")) {
600        return;
601    }else {
602        ((Calendar *)cal)->roll(UCAL_HOUR, (int32_t)100, status);
603        ((Calendar *)cal)->clear(UCAL_HOUR);
604#if !UCONFIG_NO_SERVICE
605        URegistryKey key = cal->registerFactory(NULL, status);
606        cal->unregister(key, status);
607#endif
608    }
609    delete cal;
610
611    status = U_ZERO_ERROR;
612    cal = Calendar::createInstance(Locale("he_IL@calendar=hebrew"), status);
613    if (failure(status, "Calendar::createInstance #7")) {
614        return;
615    } else {
616        cal->roll(Calendar::MONTH, (int32_t)100, status);
617    }
618
619    LocalPointer<StringEnumeration> values(
620        Calendar::getKeywordValuesForLocale("calendar", Locale("he"), FALSE, status));
621    if (values.isNull() || U_FAILURE(status)) {
622        dataerrln("FAIL: Calendar::getKeywordValuesForLocale(he): %s", u_errorName(status));
623    } else {
624        UBool containsHebrew = FALSE;
625        const char *charValue;
626        int32_t valueLength;
627        while ((charValue = values->next(&valueLength, status)) != NULL) {
628            if (valueLength == 6 && strcmp(charValue, "hebrew") == 0) {
629                containsHebrew = TRUE;
630            }
631        }
632        if (!containsHebrew) {
633            errln("Calendar::getKeywordValuesForLocale(he)->next() does not contain \"hebrew\"");
634        }
635
636        values->reset(status);
637        containsHebrew = FALSE;
638        UnicodeString hebrew = UNICODE_STRING_SIMPLE("hebrew");
639        const UChar *ucharValue;
640        while ((ucharValue = values->unext(&valueLength, status)) != NULL) {
641            UnicodeString value(FALSE, ucharValue, valueLength);
642            if (value == hebrew) {
643                containsHebrew = TRUE;
644            }
645        }
646        if (!containsHebrew) {
647            errln("Calendar::getKeywordValuesForLocale(he)->unext() does not contain \"hebrew\"");
648        }
649
650        values->reset(status);
651        containsHebrew = FALSE;
652        const UnicodeString *stringValue;
653        while ((stringValue = values->snext(status)) != NULL) {
654            if (*stringValue == hebrew) {
655                containsHebrew = TRUE;
656            }
657        }
658        if (!containsHebrew) {
659            errln("Calendar::getKeywordValuesForLocale(he)->snext() does not contain \"hebrew\"");
660        }
661    }
662    delete cal;
663}
664
665// -------------------------------------
666
667/**
668 * This test confirms the correct behavior of add when incrementing
669 * through subsequent days.
670 */
671void
672CalendarTest::TestRog()
673{
674    UErrorCode status = U_ZERO_ERROR;
675    GregorianCalendar* gc = new GregorianCalendar(status);
676    if (failure(status, "new GregorianCalendar", TRUE)) return;
677    int32_t year = 1997, month = UCAL_APRIL, date = 1;
678    gc->set(year, month, date);
679    gc->set(UCAL_HOUR_OF_DAY, 23);
680    gc->set(UCAL_MINUTE, 0);
681    gc->set(UCAL_SECOND, 0);
682    gc->set(UCAL_MILLISECOND, 0);
683    for (int32_t i = 0; i < 9; i++, gc->add(UCAL_DATE, 1, status)) {
684        if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
685        if (gc->get(UCAL_YEAR, status) != year ||
686            gc->get(UCAL_MONTH, status) != month ||
687            gc->get(UCAL_DATE, status) != (date + i)) errln("FAIL: Date wrong");
688        if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
689    }
690    delete gc;
691}
692
693// -------------------------------------
694
695/**
696 * Test the handling of the day of the week, checking for correctness and
697 * for correct minimum and maximum values.
698 */
699void
700CalendarTest::TestDOW943()
701{
702    dowTest(FALSE);
703    dowTest(TRUE);
704}
705
706void CalendarTest::dowTest(UBool lenient)
707{
708    UErrorCode status = U_ZERO_ERROR;
709    GregorianCalendar* cal = new GregorianCalendar(status);
710    if (failure(status, "new GregorianCalendar", TRUE)) return;
711    logln("cal - Aug 12, 1997\n");
712    cal->set(1997, UCAL_AUGUST, 12);
713    cal->getTime(status);
714    if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
715    logln((lenient?UnicodeString("LENIENT0: "):UnicodeString("nonlenient0: ")) + UnicodeString(calToStr(*cal)));
716    cal->setLenient(lenient);
717    logln("cal - Dec 1, 1996\n");
718    cal->set(1996, UCAL_DECEMBER, 1);
719    logln((lenient?UnicodeString("LENIENT: "):UnicodeString("nonlenient: ")) + UnicodeString(calToStr(*cal)));
720    int32_t dow = cal->get(UCAL_DAY_OF_WEEK, status);
721    if (U_FAILURE(status)) { errln("Calendar::get failed [%s]", u_errorName(status)); return; }
722    int32_t min = cal->getMinimum(UCAL_DAY_OF_WEEK);
723    int32_t max = cal->getMaximum(UCAL_DAY_OF_WEEK);
724    if (dow < min ||
725        dow > max) errln(UnicodeString("FAIL: Day of week ") + (int32_t)dow + " out of range");
726    if (dow != UCAL_SUNDAY) errln("FAIL: Day of week should be SUNDAY[%d] not %d", UCAL_SUNDAY, dow);
727    if (min != UCAL_SUNDAY ||
728        max != UCAL_SATURDAY) errln("FAIL: Min/max bad");
729    delete cal;
730}
731
732// -------------------------------------
733
734/**
735 * Confirm that cloned Calendar objects do not inadvertently share substructures.
736 */
737void
738CalendarTest::TestClonesUnique908()
739{
740    UErrorCode status = U_ZERO_ERROR;
741    Calendar *c = Calendar::createInstance(status);
742    if (failure(status, "Calendar::createInstance", TRUE)) return;
743    Calendar *d = (Calendar*) c->clone();
744    c->set(UCAL_MILLISECOND, 123);
745    d->set(UCAL_MILLISECOND, 456);
746    if (c->get(UCAL_MILLISECOND, status) != 123 ||
747        d->get(UCAL_MILLISECOND, status) != 456) {
748        errln("FAIL: Clones share fields");
749    }
750    if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
751    delete c;
752    delete d;
753}
754
755// -------------------------------------
756
757/**
758 * Confirm that the Gregorian cutoff value works as advertised.
759 */
760void
761CalendarTest::TestGregorianChange768()
762{
763    UBool b;
764    UErrorCode status = U_ZERO_ERROR;
765    UnicodeString str;
766    GregorianCalendar* c = new GregorianCalendar(status);
767    if (failure(status, "new GregorianCalendar", TRUE)) return;
768    logln(UnicodeString("With cutoff ") + dateToString(c->getGregorianChange(), str));
769    b = c->isLeapYear(1800);
770    logln(UnicodeString(" isLeapYear(1800) = ") + (b ? "true" : "false"));
771    logln(UnicodeString(" (should be FALSE)"));
772    if (b) errln("FAIL");
773    c->setGregorianChange(date(0, 0, 1), status);
774    if (U_FAILURE(status)) { errln("GregorianCalendar::setGregorianChange failed"); return; }
775    logln(UnicodeString("With cutoff ") + dateToString(c->getGregorianChange(), str));
776    b = c->isLeapYear(1800);
777    logln(UnicodeString(" isLeapYear(1800) = ") + (b ? "true" : "false"));
778    logln(UnicodeString(" (should be TRUE)"));
779    if (!b) errln("FAIL");
780    delete c;
781}
782
783// -------------------------------------
784
785/**
786 * Confirm the functioning of the field disambiguation algorithm.
787 */
788void
789CalendarTest::TestDisambiguation765()
790{
791    UErrorCode status = U_ZERO_ERROR;
792    Calendar *c = Calendar::createInstance("en_US", status);
793    if (failure(status, "Calendar::createInstance", TRUE)) return;
794    c->setLenient(FALSE);
795    c->clear();
796    c->set(UCAL_YEAR, 1997);
797    c->set(UCAL_MONTH, UCAL_JUNE);
798    c->set(UCAL_DATE, 3);
799    verify765("1997 third day of June = ", c, 1997, UCAL_JUNE, 3);
800    c->clear();
801    c->set(UCAL_YEAR, 1997);
802    c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
803    c->set(UCAL_MONTH, UCAL_JUNE);
804    c->set(UCAL_DAY_OF_WEEK_IN_MONTH, 1);
805    verify765("1997 first Tuesday in June = ", c, 1997, UCAL_JUNE, 3);
806    c->clear();
807    c->set(UCAL_YEAR, 1997);
808    c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
809    c->set(UCAL_MONTH, UCAL_JUNE);
810    c->set(UCAL_DAY_OF_WEEK_IN_MONTH, - 1);
811    verify765("1997 last Tuesday in June = ", c, 1997, UCAL_JUNE, 24);
812
813    status = U_ZERO_ERROR;
814    c->clear();
815    c->set(UCAL_YEAR, 1997);
816    c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
817    c->set(UCAL_MONTH, UCAL_JUNE);
818    c->set(UCAL_DAY_OF_WEEK_IN_MONTH, 0);
819    c->getTime(status);
820    verify765("1997 zero-th Tuesday in June = ", status);
821
822    c->clear();
823    c->set(UCAL_YEAR, 1997);
824    c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
825    c->set(UCAL_MONTH, UCAL_JUNE);
826    c->set(UCAL_WEEK_OF_MONTH, 1);
827    verify765("1997 Tuesday in week 1 of June = ", c, 1997, UCAL_JUNE, 3);
828    c->clear();
829    c->set(UCAL_YEAR, 1997);
830    c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
831    c->set(UCAL_MONTH, UCAL_JUNE);
832    c->set(UCAL_WEEK_OF_MONTH, 5);
833    verify765("1997 Tuesday in week 5 of June = ", c, 1997, UCAL_JULY, 1);
834
835    status = U_ZERO_ERROR;
836    c->clear();
837    c->set(UCAL_YEAR, 1997);
838    c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
839    c->set(UCAL_MONTH, UCAL_JUNE);
840    c->set(UCAL_WEEK_OF_MONTH, 0);
841    c->setMinimalDaysInFirstWeek(1);
842    c->getTime(status);
843    verify765("1997 Tuesday in week 0 of June = ", status);
844
845    /* Note: The following test used to expect YEAR 1997, WOY 1 to
846     * resolve to a date in Dec 1996; that is, to behave as if
847     * YEAR_WOY were 1997.  With the addition of a new explicit
848     * YEAR_WOY field, YEAR_WOY must itself be set if that is what is
849     * desired.  Using YEAR in combination with WOY is ambiguous, and
850     * results in the first WOY/DOW day of the year satisfying the
851     * given fields (there may be up to two such days). In this case,
852     * it propertly resolves to Tue Dec 30 1997, which has a WOY value
853     * of 1 (for YEAR_WOY 1998) and a DOW of Tuesday, and falls in the
854     * _calendar_ year 1997, as specified. - aliu */
855    c->clear();
856    c->set(UCAL_YEAR_WOY, 1997); // aliu
857    c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
858    c->set(UCAL_WEEK_OF_YEAR, 1);
859    verify765("1997 Tuesday in week 1 of yearWOY = ", c, 1996, UCAL_DECEMBER, 31);
860    c->clear(); // - add test for YEAR
861    c->setMinimalDaysInFirstWeek(1);
862    c->set(UCAL_YEAR, 1997);
863    c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
864    c->set(UCAL_WEEK_OF_YEAR, 1);
865    verify765("1997 Tuesday in week 1 of year = ", c, 1997, UCAL_DECEMBER, 30);
866    c->clear();
867    c->set(UCAL_YEAR, 1997);
868    c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
869    c->set(UCAL_WEEK_OF_YEAR, 10);
870    verify765("1997 Tuesday in week 10 of year = ", c, 1997, UCAL_MARCH, 4);
871    //try {
872
873    // {sfb} week 0 is no longer a valid week of year
874    /*c->clear();
875    c->set(Calendar::YEAR, 1997);
876    c->set(Calendar::DAY_OF_WEEK, Calendar::TUESDAY);
877    //c->set(Calendar::WEEK_OF_YEAR, 0);
878    c->set(Calendar::WEEK_OF_YEAR, 1);
879    verify765("1997 Tuesday in week 0 of year = ", c, 1996, Calendar::DECEMBER, 24);*/
880
881    //}
882    //catch(IllegalArgumentException ex) {
883    //    errln("FAIL: Exception seen:");
884    //    ex.printStackTrace(log);
885    //}
886    delete c;
887}
888
889// -------------------------------------
890
891void
892CalendarTest::verify765(const UnicodeString& msg, Calendar* c, int32_t year, int32_t month, int32_t day)
893{
894    UnicodeString str;
895    UErrorCode status = U_ZERO_ERROR;
896    int32_t y = c->get(UCAL_YEAR, status);
897    int32_t m = c->get(UCAL_MONTH, status);
898    int32_t d = c->get(UCAL_DATE, status);
899    if ( y == year &&
900         m == month &&
901         d == day) {
902        if (U_FAILURE(status)) { errln("FAIL: Calendar::get failed"); return; }
903        logln("PASS: " + msg + dateToString(c->getTime(status), str));
904        if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
905    }
906    else {
907        errln("FAIL: " + msg + dateToString(c->getTime(status), str) + "; expected " + (int32_t)year + "/" + (int32_t)(month + 1) + "/" + (int32_t)day +
908            "; got " + (int32_t)y + "/" + (int32_t)(m + 1) + "/" + (int32_t)d + " for Locale: " + c->getLocaleID(ULOC_ACTUAL_LOCALE,status));
909        if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
910    }
911}
912
913// -------------------------------------
914
915void
916CalendarTest::verify765(const UnicodeString& msg/*, IllegalArgumentException e*/, UErrorCode status)
917{
918    if (status != U_ILLEGAL_ARGUMENT_ERROR) errln("FAIL: No IllegalArgumentException for " + msg);
919    else logln("PASS: " + msg + "IllegalArgument as expected");
920}
921
922// -------------------------------------
923
924/**
925 * Confirm that the offset between local time and GMT behaves as expected.
926 */
927void
928CalendarTest::TestGMTvsLocal4064654()
929{
930    test4064654(1997, 1, 1, 12, 0, 0);
931    test4064654(1997, 4, 16, 18, 30, 0);
932}
933
934// -------------------------------------
935
936void
937CalendarTest::test4064654(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn, int32_t sc)
938{
939    UDate date;
940    UErrorCode status = U_ZERO_ERROR;
941    UnicodeString str;
942    Calendar *gmtcal = Calendar::createInstance(status);
943    if (failure(status, "Calendar::createInstance", TRUE)) return;
944    gmtcal->adoptTimeZone(TimeZone::createTimeZone("Africa/Casablanca"));
945    gmtcal->set(yr, mo - 1, dt, hr, mn, sc);
946    gmtcal->set(UCAL_MILLISECOND, 0);
947    date = gmtcal->getTime(status);
948    if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
949    logln("date = " + dateToString(date, str));
950    Calendar *cal = Calendar::createInstance(status);
951    if (U_FAILURE(status)) { errln("Calendar::createInstance failed"); return; }
952    cal->setTime(date, status);
953    if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
954    int32_t offset = cal->getTimeZone().getOffset((uint8_t)cal->get(UCAL_ERA, status),
955                                                  cal->get(UCAL_YEAR, status),
956                                                  cal->get(UCAL_MONTH, status),
957                                                  cal->get(UCAL_DATE, status),
958                                                  (uint8_t)cal->get(UCAL_DAY_OF_WEEK, status),
959                                                  cal->get(UCAL_MILLISECOND, status), status);
960    if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
961    logln("offset for " + dateToString(date, str) + "= " + (offset / 1000 / 60 / 60.0) + "hr");
962    int32_t utc = ((cal->get(UCAL_HOUR_OF_DAY, status) * 60 +
963                    cal->get(UCAL_MINUTE, status)) * 60 +
964                   cal->get(UCAL_SECOND, status)) * 1000 +
965        cal->get(UCAL_MILLISECOND, status) - offset;
966    if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
967    int32_t expected = ((hr * 60 + mn) * 60 + sc) * 1000;
968    if (utc != expected) errln(UnicodeString("FAIL: Discrepancy of ") + (utc - expected) +
969                               " millis = " + ((utc - expected) / 1000 / 60 / 60.0) + " hr");
970    delete gmtcal;
971    delete cal;
972}
973
974// -------------------------------------
975
976/**
977 * The operations of adding and setting should not exhibit pathological
978 * dependence on the order of operations.  This test checks for this.
979 */
980void
981CalendarTest::TestAddSetOrder621()
982{
983    UDate d = date(97, 4, 14, 13, 23, 45);
984    UErrorCode status = U_ZERO_ERROR;
985    Calendar *cal = Calendar::createInstance(status);
986    if (failure(status, "Calendar::createInstance", TRUE)) return;
987
988    cal->setTime(d, status);
989    if (U_FAILURE(status)) {
990        errln("Calendar::setTime failed");
991        delete cal;
992        return;
993    }
994    cal->add(UCAL_DATE, - 5, status);
995    if (U_FAILURE(status)) {
996        errln("Calendar::add failed");
997        delete cal;
998        return;
999    }
1000    cal->set(UCAL_HOUR_OF_DAY, 0);
1001    cal->set(UCAL_MINUTE, 0);
1002    cal->set(UCAL_SECOND, 0);
1003    UnicodeString s;
1004    dateToString(cal->getTime(status), s);
1005    if (U_FAILURE(status)) {
1006        errln("Calendar::getTime failed");
1007        delete cal;
1008        return;
1009    }
1010    delete cal;
1011
1012    cal = Calendar::createInstance(status);
1013    if (U_FAILURE(status)) {
1014        errln("Calendar::createInstance failed");
1015        delete cal;
1016        return;
1017    }
1018    cal->setTime(d, status);
1019    if (U_FAILURE(status)) {
1020        errln("Calendar::setTime failed");
1021        delete cal;
1022        return;
1023    }
1024    cal->set(UCAL_HOUR_OF_DAY, 0);
1025    cal->set(UCAL_MINUTE, 0);
1026    cal->set(UCAL_SECOND, 0);
1027    cal->add(UCAL_DATE, - 5, status);
1028    if (U_FAILURE(status)) {
1029        errln("Calendar::add failed");
1030        delete cal;
1031        return;
1032    }
1033    UnicodeString s2;
1034    dateToString(cal->getTime(status), s2);
1035    if (U_FAILURE(status)) {
1036        errln("Calendar::getTime failed");
1037        delete cal;
1038        return;
1039    }
1040    if (s == s2)
1041        logln("Pass: " + s + " == " + s2);
1042    else
1043        errln("FAIL: " + s + " != " + s2);
1044    delete cal;
1045}
1046
1047// -------------------------------------
1048
1049/**
1050 * Confirm that adding to various fields works.
1051 */
1052void
1053CalendarTest::TestAdd520()
1054{
1055    int32_t y = 1997, m = UCAL_FEBRUARY, d = 1;
1056    UErrorCode status = U_ZERO_ERROR;
1057    GregorianCalendar *temp = new GregorianCalendar(y, m, d, status);
1058    if (failure(status, "new GregorianCalendar", TRUE)) return;
1059    check520(temp, y, m, d);
1060    temp->add(UCAL_YEAR, 1, status);
1061    if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1062    y++;
1063    check520(temp, y, m, d);
1064    temp->add(UCAL_MONTH, 1, status);
1065    if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1066    m++;
1067    check520(temp, y, m, d);
1068    temp->add(UCAL_DATE, 1, status);
1069    if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1070    d++;
1071    check520(temp, y, m, d);
1072    temp->add(UCAL_DATE, 2, status);
1073    if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1074    d += 2;
1075    check520(temp, y, m, d);
1076    temp->add(UCAL_DATE, 28, status);
1077    if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1078    d = 1;++m;
1079    check520(temp, y, m, d);
1080    delete temp;
1081}
1082
1083// -------------------------------------
1084
1085/**
1086 * Execute adding and rolling in GregorianCalendar extensively,
1087 */
1088void
1089CalendarTest::TestAddRollExtensive()
1090{
1091    int32_t maxlimit = 40;
1092    int32_t y = 1997, m = UCAL_FEBRUARY, d = 1, hr = 1, min = 1, sec = 0, ms = 0;
1093    UErrorCode status = U_ZERO_ERROR;
1094    GregorianCalendar *temp = new GregorianCalendar(y, m, d, status);
1095    if (failure(status, "new GregorianCalendar", TRUE)) return;
1096
1097    temp->set(UCAL_HOUR, hr);
1098    temp->set(UCAL_MINUTE, min);
1099    temp->set(UCAL_SECOND, sec);
1100    temp->set(UCAL_MILLISECOND, ms);
1101    temp->setMinimalDaysInFirstWeek(1);
1102
1103    UCalendarDateFields e;
1104
1105    logln("Testing GregorianCalendar add...");
1106    e = UCAL_YEAR;
1107    while (e < UCAL_FIELD_COUNT) {
1108        int32_t i;
1109        int32_t limit = maxlimit;
1110        status = U_ZERO_ERROR;
1111        for (i = 0; i < limit; i++) {
1112            temp->add(e, 1, status);
1113            if (U_FAILURE(status)) { limit = i; status = U_ZERO_ERROR; }
1114        }
1115        for (i = 0; i < limit; i++) {
1116            temp->add(e, -1, status);
1117            if (U_FAILURE(status)) { errln("GregorianCalendar::add -1 failed"); return; }
1118        }
1119        check520(temp, y, m, d, hr, min, sec, ms, e);
1120
1121        e = (UCalendarDateFields) ((int32_t) e + 1);
1122    }
1123
1124    logln("Testing GregorianCalendar roll...");
1125    e = UCAL_YEAR;
1126    while (e < UCAL_FIELD_COUNT) {
1127        int32_t i;
1128        int32_t limit = maxlimit;
1129        status = U_ZERO_ERROR;
1130        for (i = 0; i < limit; i++) {
1131            logln(calToStr(*temp) + UnicodeString("  " ) + fieldName(e) + UnicodeString("++") );
1132            temp->roll(e, 1, status);
1133            if (U_FAILURE(status)) {
1134              logln("caltest.cpp:%d e=%d, i=%d - roll(+) err %s\n",  __LINE__, (int) e, (int) i, u_errorName(status));
1135              logln(calToStr(*temp));
1136              limit = i; status = U_ZERO_ERROR;
1137            }
1138        }
1139        for (i = 0; i < limit; i++) {
1140            logln("caltest.cpp:%d e=%d, i=%d\n",  __LINE__, (int) e, (int) i);
1141            logln(calToStr(*temp) + UnicodeString("  " ) + fieldName(e) + UnicodeString("--") );
1142            temp->roll(e, -1, status);
1143            if (U_FAILURE(status)) { errln(UnicodeString("GregorianCalendar::roll ") + CalendarTest::fieldName(e) + " count=" + UnicodeString('@'+i) + " by -1 failed with " + u_errorName(status) ); return; }
1144        }
1145        check520(temp, y, m, d, hr, min, sec, ms, e);
1146
1147        e = (UCalendarDateFields) ((int32_t) e + 1);
1148    }
1149
1150    delete temp;
1151}
1152
1153// -------------------------------------
1154void
1155CalendarTest::check520(Calendar* c,
1156                        int32_t y, int32_t m, int32_t d,
1157                        int32_t hr, int32_t min, int32_t sec,
1158                        int32_t ms, UCalendarDateFields field)
1159
1160{
1161    UErrorCode status = U_ZERO_ERROR;
1162    if (c->get(UCAL_YEAR, status) != y ||
1163        c->get(UCAL_MONTH, status) != m ||
1164        c->get(UCAL_DATE, status) != d ||
1165        c->get(UCAL_HOUR, status) != hr ||
1166        c->get(UCAL_MINUTE, status) != min ||
1167        c->get(UCAL_SECOND, status) != sec ||
1168        c->get(UCAL_MILLISECOND, status) != ms) {
1169        errln(UnicodeString("U_FAILURE for field ") + (int32_t)field +
1170                ": Expected y/m/d h:m:s:ms of " +
1171                y + "/" + (m + 1) + "/" + d + " " +
1172              hr + ":" + min + ":" + sec + ":" + ms +
1173              "; got " + c->get(UCAL_YEAR, status) +
1174              "/" + (c->get(UCAL_MONTH, status) + 1) +
1175              "/" + c->get(UCAL_DATE, status) +
1176              " " + c->get(UCAL_HOUR, status) + ":" +
1177              c->get(UCAL_MINUTE, status) + ":" +
1178              c->get(UCAL_SECOND, status) + ":" +
1179              c->get(UCAL_MILLISECOND, status)
1180              );
1181
1182        if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1183    }
1184    else
1185        logln(UnicodeString("Confirmed: ") + y + "/" +
1186                (m + 1) + "/" + d + " " +
1187                hr + ":" + min + ":" + sec + ":" + ms);
1188}
1189
1190// -------------------------------------
1191void
1192CalendarTest::check520(Calendar* c,
1193                        int32_t y, int32_t m, int32_t d)
1194
1195{
1196    UErrorCode status = U_ZERO_ERROR;
1197    if (c->get(UCAL_YEAR, status) != y ||
1198        c->get(UCAL_MONTH, status) != m ||
1199        c->get(UCAL_DATE, status) != d) {
1200        errln(UnicodeString("FAILURE: Expected y/m/d of ") +
1201              y + "/" + (m + 1) + "/" + d + " " +
1202              "; got " + c->get(UCAL_YEAR, status) +
1203              "/" + (c->get(UCAL_MONTH, status) + 1) +
1204              "/" + c->get(UCAL_DATE, status)
1205              );
1206
1207        if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1208    }
1209    else
1210        logln(UnicodeString("Confirmed: ") + y + "/" +
1211                (m + 1) + "/" + d);
1212}
1213
1214// -------------------------------------
1215
1216/**
1217 * Test that setting of fields works.  In particular, make sure that all instances
1218 * of GregorianCalendar don't share a static instance of the fields array.
1219 */
1220void
1221CalendarTest::TestFieldSet4781()
1222{
1223    // try {
1224        UErrorCode status = U_ZERO_ERROR;
1225        GregorianCalendar *g = new GregorianCalendar(status);
1226        if (failure(status, "new GregorianCalendar", TRUE)) return;
1227        GregorianCalendar *g2 = new GregorianCalendar(status);
1228        if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
1229        g2->set(UCAL_HOUR, 12, status);
1230        g2->set(UCAL_MINUTE, 0, status);
1231        g2->set(UCAL_SECOND, 0, status);
1232        if (U_FAILURE(status)) { errln("Calendar::set failed"); return; }
1233        if (*g == *g2) logln("Same");
1234        else logln("Different");
1235    //}
1236        //catch(IllegalArgumentException e) {
1237        //errln("Unexpected exception seen: " + e);
1238    //}
1239        delete g;
1240        delete g2;
1241}
1242
1243// -------------------------------------
1244
1245/* We don't support serialization on C++
1246void
1247CalendarTest::TestSerialize337()
1248{
1249    Calendar cal = Calendar::getInstance();
1250    UBool ok = FALSE;
1251    try {
1252        FileOutputStream f = new FileOutputStream(FILENAME);
1253        ObjectOutput s = new ObjectOutputStream(f);
1254        s.writeObject(PREFIX);
1255        s.writeObject(cal);
1256        s.writeObject(POSTFIX);
1257        f.close();
1258        FileInputStream in = new FileInputStream(FILENAME);
1259        ObjectInputStream t = new ObjectInputStream(in);
1260        UnicodeString& pre = (UnicodeString&) t.readObject();
1261        Calendar c = (Calendar) t.readObject();
1262        UnicodeString& post = (UnicodeString&) t.readObject();
1263        in.close();
1264        ok = pre.equals(PREFIX) &&
1265            post.equals(POSTFIX) &&
1266            cal->equals(c);
1267        File fl = new File(FILENAME);
1268        fl.delete();
1269    }
1270    catch(IOException e) {
1271        errln("FAIL: Exception received:");
1272        e.printStackTrace(log);
1273    }
1274    catch(ClassNotFoundException e) {
1275        errln("FAIL: Exception received:");
1276        e.printStackTrace(log);
1277    }
1278    if (!ok) errln("Serialization of Calendar object failed.");
1279}
1280
1281UnicodeString& CalendarTest::PREFIX = "abc";
1282
1283UnicodeString& CalendarTest::POSTFIX = "def";
1284
1285UnicodeString& CalendarTest::FILENAME = "tmp337.bin";
1286 */
1287
1288// -------------------------------------
1289
1290/**
1291 * Verify that the seconds of a Calendar can be zeroed out through the
1292 * expected sequence of operations.
1293 */
1294void
1295CalendarTest::TestSecondsZero121()
1296{
1297    UErrorCode status = U_ZERO_ERROR;
1298    Calendar *cal = new GregorianCalendar(status);
1299    if (failure(status, "new GregorianCalendar", TRUE)) return;
1300    cal->setTime(Calendar::getNow(), status);
1301    if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
1302    cal->set(UCAL_SECOND, 0);
1303    if (U_FAILURE(status)) { errln("Calendar::set failed"); return; }
1304    UDate d = cal->getTime(status);
1305    if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
1306    UnicodeString s;
1307    dateToString(d, s);
1308    if (s.indexOf("DATE_FORMAT_FAILURE") >= 0) {
1309        dataerrln("Got: \"DATE_FORMAT_FAILURE\".");
1310    } else if (s.indexOf(":00 ") < 0) {
1311        errln("Expected to see :00 in " + s);
1312    }
1313    delete cal;
1314}
1315
1316// -------------------------------------
1317
1318/**
1319 * Verify that a specific sequence of adding and setting works as expected;
1320 * it should not vary depending on when and whether the get method is
1321 * called.
1322 */
1323void
1324CalendarTest::TestAddSetGet0610()
1325{
1326    UnicodeString EXPECTED_0610("1993/0/5", "");
1327    UErrorCode status = U_ZERO_ERROR;
1328    {
1329        Calendar *calendar = new GregorianCalendar(status);
1330        if (failure(status, "new GregorianCalendar", TRUE)) return;
1331        calendar->set(1993, UCAL_JANUARY, 4);
1332        logln("1A) " + value(calendar));
1333        calendar->add(UCAL_DATE, 1, status);
1334        if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1335        UnicodeString v = value(calendar);
1336        logln("1B) " + v);
1337        logln("--) 1993/0/5");
1338        if (!(v == EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + "; saw " + v);
1339        delete calendar;
1340    }
1341    {
1342        Calendar *calendar = new GregorianCalendar(1993, UCAL_JANUARY, 4, status);
1343        if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
1344        logln("2A) " + value(calendar));
1345        calendar->add(UCAL_DATE, 1, status);
1346        if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1347        UnicodeString v = value(calendar);
1348        logln("2B) " + v);
1349        logln("--) 1993/0/5");
1350        if (!(v == EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + "; saw " + v);
1351        delete calendar;
1352    }
1353    {
1354        Calendar *calendar = new GregorianCalendar(1993, UCAL_JANUARY, 4, status);
1355        if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
1356        logln("3A) " + value(calendar));
1357        calendar->getTime(status);
1358        if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
1359        calendar->add(UCAL_DATE, 1, status);
1360        if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1361        UnicodeString v = value(calendar);
1362        logln("3B) " + v);
1363        logln("--) 1993/0/5");
1364        if (!(v == EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + "; saw " + v);
1365        delete calendar;
1366    }
1367}
1368
1369// -------------------------------------
1370
1371UnicodeString
1372CalendarTest::value(Calendar* calendar)
1373{
1374    UErrorCode status = U_ZERO_ERROR;
1375    return UnicodeString("") + (int32_t)calendar->get(UCAL_YEAR, status) +
1376        "/" + (int32_t)calendar->get(UCAL_MONTH, status) +
1377        "/" + (int32_t)calendar->get(UCAL_DATE, status) +
1378        (U_FAILURE(status) ? " FAIL: Calendar::get failed" : "");
1379}
1380
1381
1382// -------------------------------------
1383
1384/**
1385 * Verify that various fields on a known date are set correctly.
1386 */
1387void
1388CalendarTest::TestFields060()
1389{
1390    UErrorCode status = U_ZERO_ERROR;
1391    int32_t year = 1997;
1392    int32_t month = UCAL_OCTOBER;
1393    int32_t dDate = 22;
1394    GregorianCalendar *calendar = 0;
1395    calendar = new GregorianCalendar(year, month, dDate, status);
1396    if (failure(status, "new GregorianCalendar", TRUE)) return;
1397    for (int32_t i = 0; i < EXPECTED_FIELDS_length;) {
1398        UCalendarDateFields field = (UCalendarDateFields)EXPECTED_FIELDS[i++];
1399        int32_t expected = EXPECTED_FIELDS[i++];
1400        if (calendar->get(field, status) != expected) {
1401            errln(UnicodeString("Expected field ") + (int32_t)field + " to have value " + (int32_t)expected +
1402                  "; received " + (int32_t)calendar->get(field, status) + " instead");
1403            if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1404        }
1405    }
1406    delete calendar;
1407}
1408
1409int32_t CalendarTest::EXPECTED_FIELDS[] = {
1410    UCAL_YEAR, 1997,
1411    UCAL_MONTH, UCAL_OCTOBER,
1412    UCAL_DATE, 22,
1413    UCAL_DAY_OF_WEEK, UCAL_WEDNESDAY,
1414    UCAL_DAY_OF_WEEK_IN_MONTH, 4,
1415    UCAL_DAY_OF_YEAR, 295
1416};
1417
1418const int32_t CalendarTest::EXPECTED_FIELDS_length = (int32_t)(sizeof(CalendarTest::EXPECTED_FIELDS) /
1419    sizeof(CalendarTest::EXPECTED_FIELDS[0]));
1420
1421// -------------------------------------
1422
1423/**
1424 * Verify that various fields on a known date are set correctly.  In this
1425 * case, the start of the epoch (January 1 1970).
1426 */
1427void
1428CalendarTest::TestEpochStartFields()
1429{
1430    UErrorCode status = U_ZERO_ERROR;
1431    TimeZone *z = TimeZone::createDefault();
1432    Calendar *c = Calendar::createInstance(status);
1433    if (failure(status, "Calendar::createInstance", TRUE)) return;
1434    UDate d = - z->getRawOffset();
1435    GregorianCalendar *gc = new GregorianCalendar(status);
1436    if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
1437    gc->setTimeZone(*z);
1438    gc->setTime(d, status);
1439    if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
1440    UBool idt = gc->inDaylightTime(status);
1441    if (U_FAILURE(status)) { errln("GregorianCalendar::inDaylightTime failed"); return; }
1442    if (idt) {
1443        UnicodeString str;
1444        logln("Warning: Skipping test because " + dateToString(d, str) + " is in DST.");
1445    }
1446    else {
1447        c->setTime(d, status);
1448        if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
1449        for (int32_t i = 0; i < UCAL_ZONE_OFFSET;++i) {
1450            if (c->get((UCalendarDateFields)i, status) != EPOCH_FIELDS[i])
1451                dataerrln(UnicodeString("Expected field ") + i + " to have value " + EPOCH_FIELDS[i] +
1452                      "; saw " + c->get((UCalendarDateFields)i, status) + " instead");
1453            if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1454        }
1455        if (c->get(UCAL_ZONE_OFFSET, status) != z->getRawOffset())
1456        {
1457            errln(UnicodeString("Expected field ZONE_OFFSET to have value ") + z->getRawOffset() +
1458                  "; saw " + c->get(UCAL_ZONE_OFFSET, status) + " instead");
1459            if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1460        }
1461        if (c->get(UCAL_DST_OFFSET, status) != 0)
1462        {
1463            errln(UnicodeString("Expected field DST_OFFSET to have value 0") +
1464                  "; saw " + c->get(UCAL_DST_OFFSET, status) + " instead");
1465            if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1466        }
1467    }
1468    delete c;
1469    delete z;
1470    delete gc;
1471}
1472
1473int32_t CalendarTest::EPOCH_FIELDS[] = {
1474    1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, - 28800000, 0
1475};
1476
1477// -------------------------------------
1478
1479/**
1480 * Test that the days of the week progress properly when add is called repeatedly
1481 * for increments of 24 days.
1482 */
1483void
1484CalendarTest::TestDOWProgression()
1485{
1486    UErrorCode status = U_ZERO_ERROR;
1487    Calendar *cal = new GregorianCalendar(1972, UCAL_OCTOBER, 26, status);
1488    if (failure(status, "new GregorianCalendar", TRUE)) return;
1489    marchByDelta(cal, 24);
1490    delete cal;
1491}
1492
1493// -------------------------------------
1494
1495void
1496CalendarTest::TestDOW_LOCALandYEAR_WOY()
1497{
1498    /* Note: I've commented out the loop_addroll tests for YEAR and
1499     * YEAR_WOY below because these two fields should NOT behave
1500     * identically when adding.  YEAR should keep the month/dom
1501     * invariant.  YEAR_WOY should keep the woy/dow invariant.  I've
1502     * added a new test that checks for this in place of the old call
1503     * to loop_addroll. - aliu */
1504    UErrorCode status = U_ZERO_ERROR;
1505    int32_t times = 20;
1506    Calendar *cal=Calendar::createInstance(Locale::getGermany(), status);
1507    if (failure(status, "Calendar::createInstance", TRUE)) return;
1508    SimpleDateFormat *sdf=new SimpleDateFormat(UnicodeString("YYYY'-W'ww-ee"), Locale::getGermany(), status);
1509    if (U_FAILURE(status)) { dataerrln("Couldn't create SimpleDateFormat - %s", u_errorName(status)); return; }
1510
1511    // ICU no longer use localized date-time pattern characters by default.
1512    // So we set pattern chars using 'J' instead of 'Y'.
1513    DateFormatSymbols *dfs = new DateFormatSymbols(Locale::getGermany(), status);
1514    dfs->setLocalPatternChars(UnicodeString("GyMdkHmsSEDFwWahKzJeugAZvcLQq"));
1515    sdf->adoptDateFormatSymbols(dfs);
1516    sdf->applyLocalizedPattern(UnicodeString("JJJJ'-W'ww-ee"), status);
1517    if (U_FAILURE(status)) { errln("Couldn't apply localized pattern"); return; }
1518
1519    cal->clear();
1520    cal->set(1997, UCAL_DECEMBER, 25);
1521    doYEAR_WOYLoop(cal, sdf, times, status);
1522    //loop_addroll(cal, /*sdf,*/ times, UCAL_YEAR_WOY, UCAL_YEAR,  status);
1523    yearAddTest(*cal, status); // aliu
1524    loop_addroll(cal, /*sdf,*/ times, UCAL_DOW_LOCAL, UCAL_DAY_OF_WEEK, status);
1525    if (U_FAILURE(status)) { errln("Error in parse/calculate test for 1997"); return; }
1526
1527    cal->clear();
1528    cal->set(1998, UCAL_DECEMBER, 25);
1529    doYEAR_WOYLoop(cal, sdf, times, status);
1530    //loop_addroll(cal, /*sdf,*/ times, UCAL_YEAR_WOY, UCAL_YEAR,  status);
1531    yearAddTest(*cal, status); // aliu
1532    loop_addroll(cal, /*sdf,*/ times, UCAL_DOW_LOCAL, UCAL_DAY_OF_WEEK, status);
1533    if (U_FAILURE(status)) { errln("Error in parse/calculate test for 1998"); return; }
1534
1535    cal->clear();
1536    cal->set(1582, UCAL_OCTOBER, 1);
1537    doYEAR_WOYLoop(cal, sdf, times, status);
1538    //loop_addroll(cal, /*sdf,*/ times, Calendar::YEAR_WOY, Calendar::YEAR,  status);
1539    yearAddTest(*cal, status); // aliu
1540    loop_addroll(cal, /*sdf,*/ times, UCAL_DOW_LOCAL, UCAL_DAY_OF_WEEK, status);
1541    if (U_FAILURE(status)) { errln("Error in parse/calculate test for 1582"); return; }
1542    delete sdf;
1543    delete cal;
1544
1545    return;
1546}
1547
1548/**
1549 * Confirm that adding a YEAR and adding a YEAR_WOY work properly for
1550 * the given Calendar at its current setting.
1551 */
1552void CalendarTest::yearAddTest(Calendar& cal, UErrorCode& status) {
1553    /**
1554     * When adding the YEAR, the month and day should remain constant.
1555     * When adding the YEAR_WOY, the WOY and DOW should remain constant. - aliu
1556     * Examples:
1557     *  Wed Jan 14 1998 / 1998-W03-03 Add(YEAR_WOY, 1) -> Wed Jan 20 1999 / 1999-W03-03
1558     *                                Add(YEAR, 1)     -> Thu Jan 14 1999 / 1999-W02-04
1559     *  Thu Jan 14 1999 / 1999-W02-04 Add(YEAR_WOY, 1) -> Thu Jan 13 2000 / 2000-W02-04
1560     *                                Add(YEAR, 1)     -> Fri Jan 14 2000 / 2000-W02-05
1561     *  Sun Oct 31 1582 / 1582-W42-07 Add(YEAR_WOY, 1) -> Sun Oct 23 1583 / 1583-W42-07
1562     *                                Add(YEAR, 1)     -> Mon Oct 31 1583 / 1583-W44-01
1563     */
1564    int32_t y   = cal.get(UCAL_YEAR, status);
1565    int32_t mon = cal.get(UCAL_MONTH, status);
1566    int32_t day = cal.get(UCAL_DATE, status);
1567    int32_t ywy = cal.get(UCAL_YEAR_WOY, status);
1568    int32_t woy = cal.get(UCAL_WEEK_OF_YEAR, status);
1569    int32_t dow = cal.get(UCAL_DOW_LOCAL, status);
1570    UDate t = cal.getTime(status);
1571
1572    if(U_FAILURE(status)){
1573        errln(UnicodeString("Failed to create Calendar for locale. Error: ") + UnicodeString(u_errorName(status)));
1574        return;
1575    }
1576    UnicodeString str, str2;
1577    SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"), status);
1578    fmt.setCalendar(cal);
1579
1580    fmt.format(t, str.remove());
1581    str += ".add(YEAR, 1)    =>";
1582    cal.add(UCAL_YEAR, 1, status);
1583    int32_t y2   = cal.get(UCAL_YEAR, status);
1584    int32_t mon2 = cal.get(UCAL_MONTH, status);
1585    int32_t day2 = cal.get(UCAL_DATE, status);
1586    fmt.format(cal.getTime(status), str);
1587    if (y2 != (y+1) || mon2 != mon || day2 != day) {
1588        str += (UnicodeString)", expected year " +
1589            (y+1) + ", month " + (mon+1) + ", day " + day;
1590        errln((UnicodeString)"FAIL: " + str);
1591        logln( UnicodeString(" -> ") + CalendarTest::calToStr(cal) );
1592    } else {
1593        logln(str);
1594    }
1595
1596    fmt.format(t, str.remove());
1597    str += ".add(YEAR_WOY, 1)=>";
1598    cal.setTime(t, status);
1599    logln( UnicodeString(" <- ") + CalendarTest::calToStr(cal) );
1600    cal.add(UCAL_YEAR_WOY, 1, status);
1601    int32_t ywy2 = cal.get(UCAL_YEAR_WOY, status);
1602    int32_t woy2 = cal.get(UCAL_WEEK_OF_YEAR, status);
1603    int32_t dow2 = cal.get(UCAL_DOW_LOCAL, status);
1604    fmt.format(cal.getTime(status), str);
1605    if (ywy2 != (ywy+1) || woy2 != woy || dow2 != dow) {
1606        str += (UnicodeString)", expected yearWOY " +
1607            (ywy+1) + ", woy " + woy + ", dowLocal " + dow;
1608        errln((UnicodeString)"FAIL: " + str);
1609        logln( UnicodeString(" -> ") + CalendarTest::calToStr(cal) );
1610    } else {
1611        logln(str);
1612    }
1613}
1614
1615// -------------------------------------
1616
1617void CalendarTest::loop_addroll(Calendar *cal, /*SimpleDateFormat *sdf,*/ int times, UCalendarDateFields field, UCalendarDateFields field2, UErrorCode& errorCode) {
1618    Calendar *calclone;
1619    SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"), errorCode);
1620    fmt.setCalendar(*cal);
1621    int i;
1622
1623    for(i = 0; i<times; i++) {
1624        calclone = cal->clone();
1625        UDate start = cal->getTime(errorCode);
1626        cal->add(field,1,errorCode);
1627        if (U_FAILURE(errorCode)) { errln("Error in add"); delete calclone; return; }
1628        calclone->add(field2,1,errorCode);
1629        if (U_FAILURE(errorCode)) { errln("Error in add"); delete calclone; return; }
1630        if(cal->getTime(errorCode) != calclone->getTime(errorCode)) {
1631            UnicodeString str("FAIL: Results of add differ. "), str2;
1632            str += fmt.format(start, str2) + " ";
1633            str += UnicodeString("Add(") + fieldName(field) + ", 1) -> " +
1634                fmt.format(cal->getTime(errorCode), str2.remove()) + "; ";
1635            str += UnicodeString("Add(") + fieldName(field2) + ", 1) -> " +
1636                fmt.format(calclone->getTime(errorCode), str2.remove());
1637            errln(str);
1638            delete calclone;
1639            return;
1640        }
1641        delete calclone;
1642    }
1643
1644    for(i = 0; i<times; i++) {
1645        calclone = cal->clone();
1646        cal->roll(field,(int32_t)1,errorCode);
1647        if (U_FAILURE(errorCode)) { errln("Error in roll"); delete calclone; return; }
1648        calclone->roll(field2,(int32_t)1,errorCode);
1649        if (U_FAILURE(errorCode)) { errln("Error in roll"); delete calclone; return; }
1650        if(cal->getTime(errorCode) != calclone->getTime(errorCode)) {
1651            delete calclone;
1652            errln("Results of roll differ!");
1653            return;
1654        }
1655        delete calclone;
1656    }
1657}
1658
1659// -------------------------------------
1660
1661void
1662CalendarTest::doYEAR_WOYLoop(Calendar *cal, SimpleDateFormat *sdf,
1663                                    int32_t times, UErrorCode& errorCode) {
1664
1665    UnicodeString us;
1666    UDate tst, original;
1667    Calendar *tstres = new GregorianCalendar(Locale::getGermany(), errorCode);
1668    for(int i=0; i<times; ++i) {
1669        sdf->format(Formattable(cal->getTime(errorCode),Formattable::kIsDate), us, errorCode);
1670        //logln("expected: "+us);
1671        if (U_FAILURE(errorCode)) { errln("Format error"); return; }
1672        tst=sdf->parse(us,errorCode);
1673        if (U_FAILURE(errorCode)) { errln("Parse error"); return; }
1674        tstres->clear();
1675        tstres->setTime(tst, errorCode);
1676        //logln((UnicodeString)"Parsed week of year is "+tstres->get(UCAL_WEEK_OF_YEAR, errorCode));
1677        if (U_FAILURE(errorCode)) { errln("Set time error"); return; }
1678        original = cal->getTime(errorCode);
1679        us.remove();
1680        sdf->format(Formattable(tst,Formattable::kIsDate), us, errorCode);
1681        //logln("got: "+us);
1682        if (U_FAILURE(errorCode)) { errln("Get time error"); return; }
1683        if(original!=tst) {
1684            us.remove();
1685            sdf->format(Formattable(original, Formattable::kIsDate), us, errorCode);
1686            errln("FAIL: Parsed time doesn't match with regular");
1687            logln("expected "+us + " " + calToStr(*cal));
1688            us.remove();
1689            sdf->format(Formattable(tst, Formattable::kIsDate), us, errorCode);
1690            logln("got "+us + " " + calToStr(*tstres));
1691        }
1692        tstres->clear();
1693        tstres->set(UCAL_YEAR_WOY, cal->get(UCAL_YEAR_WOY, errorCode));
1694        tstres->set(UCAL_WEEK_OF_YEAR, cal->get(UCAL_WEEK_OF_YEAR, errorCode));
1695        tstres->set(UCAL_DOW_LOCAL, cal->get(UCAL_DOW_LOCAL, errorCode));
1696        if(cal->get(UCAL_YEAR, errorCode) != tstres->get(UCAL_YEAR, errorCode)) {
1697            errln("FAIL: Different Year!");
1698            logln((UnicodeString)"Expected "+cal->get(UCAL_YEAR, errorCode));
1699            logln((UnicodeString)"Got "+tstres->get(UCAL_YEAR, errorCode));
1700            return;
1701        }
1702        if(cal->get(UCAL_DAY_OF_YEAR, errorCode) != tstres->get(UCAL_DAY_OF_YEAR, errorCode)) {
1703            errln("FAIL: Different Day Of Year!");
1704            logln((UnicodeString)"Expected "+cal->get(UCAL_DAY_OF_YEAR, errorCode));
1705            logln((UnicodeString)"Got "+tstres->get(UCAL_DAY_OF_YEAR, errorCode));
1706            return;
1707        }
1708        //logln(calToStr(*cal));
1709        cal->add(UCAL_DATE, 1, errorCode);
1710        if (U_FAILURE(errorCode)) { errln("Add error"); return; }
1711        us.remove();
1712    }
1713    delete (tstres);
1714}
1715// -------------------------------------
1716
1717void
1718CalendarTest::marchByDelta(Calendar* cal, int32_t delta)
1719{
1720    UErrorCode status = U_ZERO_ERROR;
1721    Calendar *cur = (Calendar*) cal->clone();
1722    int32_t initialDOW = cur->get(UCAL_DAY_OF_WEEK, status);
1723    if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1724    int32_t DOW, newDOW = initialDOW;
1725    do {
1726        UnicodeString str;
1727        DOW = newDOW;
1728        logln(UnicodeString("DOW = ") + DOW + "  " + dateToString(cur->getTime(status), str));
1729        if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
1730        cur->add(UCAL_DAY_OF_WEEK, delta, status);
1731        if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1732        newDOW = cur->get(UCAL_DAY_OF_WEEK, status);
1733        if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1734        int32_t expectedDOW = 1 + (DOW + delta - 1) % 7;
1735        if (newDOW != expectedDOW) {
1736            errln(UnicodeString("Day of week should be ") + expectedDOW + " instead of " + newDOW +
1737                  " on " + dateToString(cur->getTime(status), str));
1738            if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
1739            return;
1740        }
1741    }
1742    while (newDOW != initialDOW);
1743    delete cur;
1744}
1745
1746#define CHECK(status, msg) \
1747    if (U_FAILURE(status)) { \
1748        errcheckln(status, msg); \
1749        return; \
1750    }
1751
1752void CalendarTest::TestWOY(void) {
1753    /*
1754      FDW = Mon, MDFW = 4:
1755         Sun Dec 26 1999, WOY 51
1756         Mon Dec 27 1999, WOY 52
1757         Tue Dec 28 1999, WOY 52
1758         Wed Dec 29 1999, WOY 52
1759         Thu Dec 30 1999, WOY 52
1760         Fri Dec 31 1999, WOY 52
1761         Sat Jan 01 2000, WOY 52 ***
1762         Sun Jan 02 2000, WOY 52 ***
1763         Mon Jan 03 2000, WOY 1
1764         Tue Jan 04 2000, WOY 1
1765         Wed Jan 05 2000, WOY 1
1766         Thu Jan 06 2000, WOY 1
1767         Fri Jan 07 2000, WOY 1
1768         Sat Jan 08 2000, WOY 1
1769         Sun Jan 09 2000, WOY 1
1770         Mon Jan 10 2000, WOY 2
1771
1772      FDW = Mon, MDFW = 2:
1773         Sun Dec 26 1999, WOY 52
1774         Mon Dec 27 1999, WOY 1  ***
1775         Tue Dec 28 1999, WOY 1  ***
1776         Wed Dec 29 1999, WOY 1  ***
1777         Thu Dec 30 1999, WOY 1  ***
1778         Fri Dec 31 1999, WOY 1  ***
1779         Sat Jan 01 2000, WOY 1
1780         Sun Jan 02 2000, WOY 1
1781         Mon Jan 03 2000, WOY 2
1782         Tue Jan 04 2000, WOY 2
1783         Wed Jan 05 2000, WOY 2
1784         Thu Jan 06 2000, WOY 2
1785         Fri Jan 07 2000, WOY 2
1786         Sat Jan 08 2000, WOY 2
1787         Sun Jan 09 2000, WOY 2
1788         Mon Jan 10 2000, WOY 3
1789    */
1790
1791    UnicodeString str;
1792    UErrorCode status = U_ZERO_ERROR;
1793    int32_t i;
1794
1795    GregorianCalendar cal(status);
1796    SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy', WOY' w"), status);
1797    if (failure(status, "Cannot construct calendar/format", TRUE)) return;
1798
1799    UCalendarDaysOfWeek fdw = (UCalendarDaysOfWeek) 0;
1800
1801    //for (int8_t pass=2; pass<=2; ++pass) {
1802    for (int8_t pass=1; pass<=2; ++pass) {
1803        switch (pass) {
1804        case 1:
1805            fdw = UCAL_MONDAY;
1806            cal.setFirstDayOfWeek(fdw);
1807            cal.setMinimalDaysInFirstWeek(4);
1808            fmt.adoptCalendar(cal.clone());
1809            break;
1810        case 2:
1811            fdw = UCAL_MONDAY;
1812            cal.setFirstDayOfWeek(fdw);
1813            cal.setMinimalDaysInFirstWeek(2);
1814            fmt.adoptCalendar(cal.clone());
1815            break;
1816        }
1817
1818        //for (i=2; i<=6; ++i) {
1819        for (i=0; i<16; ++i) {
1820        UDate t, t2;
1821        int32_t t_y, t_woy, t_dow;
1822        cal.clear();
1823        cal.set(1999, UCAL_DECEMBER, 26 + i);
1824        fmt.format(t = cal.getTime(status), str.remove());
1825        CHECK(status, "Fail: getTime failed");
1826        logln(UnicodeString("* ") + str);
1827        int32_t dow = cal.get(UCAL_DAY_OF_WEEK, status);
1828        int32_t woy = cal.get(UCAL_WEEK_OF_YEAR, status);
1829        int32_t year = cal.get(UCAL_YEAR, status);
1830        int32_t mon = cal.get(UCAL_MONTH, status);
1831        logln(calToStr(cal));
1832        CHECK(status, "Fail: get failed");
1833        int32_t dowLocal = dow - fdw;
1834        if (dowLocal < 0) dowLocal += 7;
1835        dowLocal++;
1836        int32_t yearWoy = year;
1837        if (mon == UCAL_JANUARY) {
1838            if (woy >= 52) --yearWoy;
1839        } else {
1840            if (woy == 1) ++yearWoy;
1841        }
1842
1843        // Basic fields->time check y/woy/dow
1844        // Since Y/WOY is ambiguous, we do a check of the fields,
1845        // not of the specific time.
1846        cal.clear();
1847        cal.set(UCAL_YEAR, year);
1848        cal.set(UCAL_WEEK_OF_YEAR, woy);
1849        cal.set(UCAL_DAY_OF_WEEK, dow);
1850        t_y = cal.get(UCAL_YEAR, status);
1851        t_woy = cal.get(UCAL_WEEK_OF_YEAR, status);
1852        t_dow = cal.get(UCAL_DAY_OF_WEEK, status);
1853        CHECK(status, "Fail: get failed");
1854        if (t_y != year || t_woy != woy || t_dow != dow) {
1855            str = "Fail: y/woy/dow fields->time => ";
1856            fmt.format(cal.getTime(status), str);
1857            errln(str);
1858            logln(calToStr(cal));
1859            logln("[get!=set] Y%d!=%d || woy%d!=%d || dow%d!=%d\n",
1860                  t_y, year, t_woy, woy, t_dow, dow);
1861        } else {
1862          logln("y/woy/dow fields->time OK");
1863        }
1864
1865        // Basic fields->time check y/woy/dow_local
1866        // Since Y/WOY is ambiguous, we do a check of the fields,
1867        // not of the specific time.
1868        cal.clear();
1869        cal.set(UCAL_YEAR, year);
1870        cal.set(UCAL_WEEK_OF_YEAR, woy);
1871        cal.set(UCAL_DOW_LOCAL, dowLocal);
1872        t_y = cal.get(UCAL_YEAR, status);
1873        t_woy = cal.get(UCAL_WEEK_OF_YEAR, status);
1874        t_dow = cal.get(UCAL_DOW_LOCAL, status);
1875        CHECK(status, "Fail: get failed");
1876        if (t_y != year || t_woy != woy || t_dow != dowLocal) {
1877            str = "Fail: y/woy/dow_local fields->time => ";
1878            fmt.format(cal.getTime(status), str);
1879            errln(str);
1880        }
1881
1882        // Basic fields->time check y_woy/woy/dow
1883        cal.clear();
1884        cal.set(UCAL_YEAR_WOY, yearWoy);
1885        cal.set(UCAL_WEEK_OF_YEAR, woy);
1886        cal.set(UCAL_DAY_OF_WEEK, dow);
1887        t2 = cal.getTime(status);
1888        CHECK(status, "Fail: getTime failed");
1889        if (t != t2) {
1890            str = "Fail: y_woy/woy/dow fields->time => ";
1891            fmt.format(t2, str);
1892            errln(str);
1893            logln(calToStr(cal));
1894            logln("%.f != %.f\n", t, t2);
1895        } else {
1896          logln("y_woy/woy/dow OK");
1897        }
1898
1899        // Basic fields->time check y_woy/woy/dow_local
1900        cal.clear();
1901        cal.set(UCAL_YEAR_WOY, yearWoy);
1902        cal.set(UCAL_WEEK_OF_YEAR, woy);
1903        cal.set(UCAL_DOW_LOCAL, dowLocal);
1904        t2 = cal.getTime(status);
1905        CHECK(status, "Fail: getTime failed");
1906        if (t != t2) {
1907            str = "Fail: y_woy/woy/dow_local fields->time => ";
1908            fmt.format(t2, str);
1909            errln(str);
1910        }
1911
1912        logln("Testing DOW_LOCAL.. dow%d\n", dow);
1913        // Make sure DOW_LOCAL disambiguates over DOW
1914        int32_t wrongDow = dow - 3;
1915        if (wrongDow < 1) wrongDow += 7;
1916        cal.setTime(t, status);
1917        cal.set(UCAL_DAY_OF_WEEK, wrongDow);
1918        cal.set(UCAL_DOW_LOCAL, dowLocal);
1919        t2 = cal.getTime(status);
1920        CHECK(status, "Fail: set/getTime failed");
1921        if (t != t2) {
1922            str = "Fail: DOW_LOCAL fields->time => ";
1923            fmt.format(t2, str);
1924            errln(str);
1925            logln(calToStr(cal));
1926            logln("%.f :   DOW%d, DOW_LOCAL%d -> %.f\n",
1927                  t, wrongDow, dowLocal, t2);
1928        }
1929
1930        // Make sure DOW disambiguates over DOW_LOCAL
1931        int32_t wrongDowLocal = dowLocal - 3;
1932        if (wrongDowLocal < 1) wrongDowLocal += 7;
1933        cal.setTime(t, status);
1934        cal.set(UCAL_DOW_LOCAL, wrongDowLocal);
1935        cal.set(UCAL_DAY_OF_WEEK, dow);
1936        t2 = cal.getTime(status);
1937        CHECK(status, "Fail: set/getTime failed");
1938        if (t != t2) {
1939            str = "Fail: DOW       fields->time => ";
1940            fmt.format(t2, str);
1941            errln(str);
1942        }
1943
1944        // Make sure YEAR_WOY disambiguates over YEAR
1945        cal.setTime(t, status);
1946        cal.set(UCAL_YEAR, year - 2);
1947        cal.set(UCAL_YEAR_WOY, yearWoy);
1948        t2 = cal.getTime(status);
1949        CHECK(status, "Fail: set/getTime failed");
1950        if (t != t2) {
1951            str = "Fail: YEAR_WOY  fields->time => ";
1952            fmt.format(t2, str);
1953            errln(str);
1954        }
1955
1956        // Make sure YEAR disambiguates over YEAR_WOY
1957        cal.setTime(t, status);
1958        cal.set(UCAL_YEAR_WOY, yearWoy - 2);
1959        cal.set(UCAL_YEAR, year);
1960        t2 = cal.getTime(status);
1961        CHECK(status, "Fail: set/getTime failed");
1962        if (t != t2) {
1963            str = "Fail: YEAR      fields->time => ";
1964            fmt.format(t2, str);
1965            errln(str);
1966        }
1967    }
1968    }
1969
1970    /*
1971      FDW = Mon, MDFW = 4:
1972         Sun Dec 26 1999, WOY 51
1973         Mon Dec 27 1999, WOY 52
1974         Tue Dec 28 1999, WOY 52
1975         Wed Dec 29 1999, WOY 52
1976         Thu Dec 30 1999, WOY 52
1977         Fri Dec 31 1999, WOY 52
1978         Sat Jan 01 2000, WOY 52
1979         Sun Jan 02 2000, WOY 52
1980    */
1981
1982    // Roll the DOW_LOCAL within week 52
1983    for (i=27; i<=33; ++i) {
1984        int32_t amount;
1985        for (amount=-7; amount<=7; ++amount) {
1986            str = "roll(";
1987            cal.set(1999, UCAL_DECEMBER, i);
1988            UDate t, t2;
1989            fmt.format(cal.getTime(status), str);
1990            CHECK(status, "Fail: getTime failed");
1991            str += UnicodeString(", ") + amount + ") = ";
1992
1993            cal.roll(UCAL_DOW_LOCAL, amount, status);
1994            CHECK(status, "Fail: roll failed");
1995
1996            t = cal.getTime(status);
1997            int32_t newDom = i + amount;
1998            while (newDom < 27) newDom += 7;
1999            while (newDom > 33) newDom -= 7;
2000            cal.set(1999, UCAL_DECEMBER, newDom);
2001            t2 = cal.getTime(status);
2002            CHECK(status, "Fail: getTime failed");
2003            fmt.format(t, str);
2004
2005            if (t != t2) {
2006                str.append(", exp ");
2007                fmt.format(t2, str);
2008                errln(str);
2009            } else {
2010                logln(str);
2011            }
2012        }
2013    }
2014}
2015
2016void CalendarTest::TestYWOY()
2017{
2018   UnicodeString str;
2019   UErrorCode status = U_ZERO_ERROR;
2020
2021   GregorianCalendar cal(status);
2022   if (failure(status, "construct GregorianCalendar", TRUE)) return;
2023
2024   cal.setFirstDayOfWeek(UCAL_SUNDAY);
2025   cal.setMinimalDaysInFirstWeek(1);
2026
2027   logln("Setting:  ywoy=2004, woy=1, dow=MONDAY");
2028   cal.clear();
2029   cal.set(UCAL_YEAR_WOY,2004);
2030   cal.set(UCAL_WEEK_OF_YEAR,1);
2031   cal.set(UCAL_DAY_OF_WEEK, UCAL_MONDAY);
2032
2033   logln(calToStr(cal));
2034   if(cal.get(UCAL_YEAR, status) != 2003) {
2035     errln("year not 2003");
2036   }
2037
2038   logln("+ setting DOW to THURSDAY");
2039   cal.clear();
2040   cal.set(UCAL_YEAR_WOY,2004);
2041   cal.set(UCAL_WEEK_OF_YEAR,1);
2042   cal.set(UCAL_DAY_OF_WEEK, UCAL_THURSDAY);
2043
2044   logln(calToStr(cal));
2045   if(cal.get(UCAL_YEAR, status) != 2004) {
2046     errln("year not 2004");
2047   }
2048
2049   logln("+ setting DOW_LOCAL to 1");
2050   cal.clear();
2051   cal.set(UCAL_YEAR_WOY,2004);
2052   cal.set(UCAL_WEEK_OF_YEAR,1);
2053   cal.set(UCAL_DAY_OF_WEEK, UCAL_THURSDAY);
2054   cal.set(UCAL_DOW_LOCAL, 1);
2055
2056   logln(calToStr(cal));
2057   if(cal.get(UCAL_YEAR, status) != 2003) {
2058     errln("year not 2003");
2059   }
2060
2061   cal.setFirstDayOfWeek(UCAL_MONDAY);
2062   cal.setMinimalDaysInFirstWeek(4);
2063   UDate t = 946713600000.;
2064   cal.setTime(t, status);
2065   cal.set(UCAL_DAY_OF_WEEK, 4);
2066   cal.set(UCAL_DOW_LOCAL, 6);
2067   if(cal.getTime(status) != t) {
2068     logln(calToStr(cal));
2069     errln("FAIL:  DOW_LOCAL did not take precedence");
2070   }
2071
2072}
2073
2074void CalendarTest::TestJD()
2075{
2076  int32_t jd;
2077  static const int32_t kEpochStartAsJulianDay = 2440588;
2078  UErrorCode status = U_ZERO_ERROR;
2079  GregorianCalendar cal(status);
2080  if (failure(status, "construct GregorianCalendar", TRUE)) return;
2081  cal.setTimeZone(*TimeZone::getGMT());
2082  cal.clear();
2083  jd = cal.get(UCAL_JULIAN_DAY, status);
2084  if(jd != kEpochStartAsJulianDay) {
2085    errln("Wanted JD of %d at time=0, [epoch 1970] but got %d\n", kEpochStartAsJulianDay, jd);
2086  } else {
2087    logln("Wanted JD of %d at time=0, [epoch 1970], got %d\n", kEpochStartAsJulianDay, jd);
2088  }
2089
2090  cal.setTime(Calendar::getNow(), status);
2091  cal.clear();
2092  cal.set(UCAL_JULIAN_DAY, kEpochStartAsJulianDay);
2093  UDate epochTime = cal.getTime(status);
2094  if(epochTime != 0) {
2095    errln("Wanted time of 0 at jd=%d, got %.1lf\n", kEpochStartAsJulianDay, epochTime);
2096  } else {
2097    logln("Wanted time of 0 at jd=%d, got %.1lf\n", kEpochStartAsJulianDay, epochTime);
2098  }
2099
2100}
2101
2102// make sure the ctestfw utilities are in sync with the Calendar
2103void CalendarTest::TestDebug()
2104{
2105    for(int32_t  t=0;t<=UDBG_ENUM_COUNT;t++) {
2106        int32_t count = udbg_enumCount((UDebugEnumType)t);
2107        if(count == -1) {
2108            logln("enumCount(%d) returned -1", count);
2109            continue;
2110        }
2111        for(int32_t i=0;i<=count;i++) {
2112            if(t<=UDBG_HIGHEST_CONTIGUOUS_ENUM && i<count) {
2113                if( i!=udbg_enumArrayValue((UDebugEnumType)t, i)) {
2114                    errln("FAIL: udbg_enumArrayValue(%d,%d) returned %d, expected %d", t, i, udbg_enumArrayValue((UDebugEnumType)t,i), i);
2115                }
2116            } else {
2117                logln("Testing count+1:");
2118            }
2119                  const char *name = udbg_enumName((UDebugEnumType)t,i);
2120                  if(name==NULL) {
2121                          if(i==count || t>UDBG_HIGHEST_CONTIGUOUS_ENUM  ) {
2122                                logln(" null name - expected.\n");
2123                          } else {
2124                                errln("FAIL: udbg_enumName(%d,%d) returned NULL", t, i);
2125                          }
2126                          name = "(null)";
2127                  }
2128          logln("udbg_enumArrayValue(%d,%d) = %s, returned %d", t, i,
2129                      name, udbg_enumArrayValue((UDebugEnumType)t,i));
2130            logln("udbg_enumString = " + udbg_enumString((UDebugEnumType)t,i));
2131        }
2132        if(udbg_enumExpectedCount((UDebugEnumType)t) != count && t<=UDBG_HIGHEST_CONTIGUOUS_ENUM) {
2133            errln("FAIL: udbg_enumExpectedCount(%d): %d, != UCAL_FIELD_COUNT=%d ", t, udbg_enumExpectedCount((UDebugEnumType)t), count);
2134        } else {
2135            logln("udbg_ucal_fieldCount: %d, UCAL_FIELD_COUNT=udbg_enumCount %d ", udbg_enumExpectedCount((UDebugEnumType)t), count);
2136        }
2137    }
2138}
2139
2140
2141#undef CHECK
2142
2143// List of interesting locales
2144const char *CalendarTest::testLocaleID(int32_t i)
2145{
2146  switch(i) {
2147  case 0: return "he_IL@calendar=hebrew";
2148  case 1: return "en_US@calendar=hebrew";
2149  case 2: return "fr_FR@calendar=hebrew";
2150  case 3: return "fi_FI@calendar=hebrew";
2151  case 4: return "nl_NL@calendar=hebrew";
2152  case 5: return "hu_HU@calendar=hebrew";
2153  case 6: return "nl_BE@currency=MTL;calendar=islamic";
2154  case 7: return "th_TH_TRADITIONAL@calendar=gregorian";
2155  case 8: return "ar_JO@calendar=islamic-civil";
2156  case 9: return "fi_FI@calendar=islamic";
2157  case 10: return "fr_CH@calendar=islamic-civil";
2158  case 11: return "he_IL@calendar=islamic-civil";
2159  case 12: return "hu_HU@calendar=buddhist";
2160  case 13: return "hu_HU@calendar=islamic";
2161  case 14: return "en_US@calendar=japanese";
2162  default: return NULL;
2163  }
2164}
2165
2166int32_t CalendarTest::testLocaleCount()
2167{
2168  static int32_t gLocaleCount = -1;
2169  if(gLocaleCount < 0) {
2170    int32_t i;
2171    for(i=0;testLocaleID(i) != NULL;i++) {
2172      ;
2173    }
2174    gLocaleCount = i;
2175  }
2176  return gLocaleCount;
2177}
2178
2179static UDate doMinDateOfCalendar(Calendar* adopt, UBool &isGregorian, UErrorCode& status) {
2180  if(U_FAILURE(status)) return 0.0;
2181
2182  adopt->clear();
2183  adopt->set(UCAL_EXTENDED_YEAR, adopt->getActualMinimum(UCAL_EXTENDED_YEAR, status));
2184  UDate ret = adopt->getTime(status);
2185  isGregorian = dynamic_cast<GregorianCalendar*>(adopt) != NULL;
2186  delete adopt;
2187  return ret;
2188}
2189
2190UDate CalendarTest::minDateOfCalendar(const Locale& locale, UBool &isGregorian, UErrorCode& status) {
2191  if(U_FAILURE(status)) return 0.0;
2192  return doMinDateOfCalendar(Calendar::createInstance(locale, status), isGregorian, status);
2193}
2194
2195UDate CalendarTest::minDateOfCalendar(const Calendar& cal, UBool &isGregorian, UErrorCode& status) {
2196  if(U_FAILURE(status)) return 0.0;
2197  return doMinDateOfCalendar(cal.clone(), isGregorian, status);
2198}
2199
2200void CalendarTest::Test6703()
2201{
2202    UErrorCode status = U_ZERO_ERROR;
2203    Calendar *cal;
2204
2205    Locale loc1("en@calendar=fubar");
2206    cal = Calendar::createInstance(loc1, status);
2207    if (failure(status, "Calendar::createInstance", TRUE)) return;
2208    delete cal;
2209
2210    status = U_ZERO_ERROR;
2211    Locale loc2("en");
2212    cal = Calendar::createInstance(loc2, status);
2213    if (failure(status, "Calendar::createInstance")) return;
2214    delete cal;
2215
2216    status = U_ZERO_ERROR;
2217    Locale loc3("en@calendar=roc");
2218    cal = Calendar::createInstance(loc3, status);
2219    if (failure(status, "Calendar::createInstance")) return;
2220    delete cal;
2221
2222    return;
2223}
2224
2225void CalendarTest::Test3785()
2226{
2227    UErrorCode status = U_ZERO_ERROR;
2228    UnicodeString uzone = UNICODE_STRING_SIMPLE("Europe/Paris");
2229    UnicodeString exp1 = UNICODE_STRING_SIMPLE("Mon 30 Jumada II 1433 AH, 01:47:03");
2230    UnicodeString exp2 = UNICODE_STRING_SIMPLE("Mon 1 Rajab 1433 AH, 01:47:04");
2231
2232    LocalUDateFormatPointer df(udat_open(UDAT_NONE, UDAT_NONE, "en@calendar=islamic", uzone.getTerminatedBuffer(),
2233                                         uzone.length(), NULL, 0, &status));
2234    if (df.isNull() || U_FAILURE(status)) return;
2235
2236    UChar upattern[64];
2237    u_uastrcpy(upattern, "EEE d MMMM y G, HH:mm:ss");
2238    udat_applyPattern(df.getAlias(), FALSE, upattern, u_strlen(upattern));
2239
2240    UChar ubuffer[1024];
2241    UDate ud0 = 1337557623000.0;
2242
2243    status = U_ZERO_ERROR;
2244    udat_format(df.getAlias(), ud0, ubuffer, 1024, NULL, &status);
2245    if (U_FAILURE(status)) {
2246        errln("Error formatting date 1\n");
2247        return;
2248    }
2249    //printf("formatted: '%s'\n", mkcstr(ubuffer));
2250
2251    UnicodeString act1(ubuffer);
2252    if ( act1 != exp1 ) {
2253        errln("Unexpected result from date 1 format\n");
2254    }
2255    ud0 += 1000.0; // add one second
2256
2257    status = U_ZERO_ERROR;
2258    udat_format(df.getAlias(), ud0, ubuffer, 1024, NULL, &status);
2259    if (U_FAILURE(status)) {
2260        errln("Error formatting date 2\n");
2261        return;
2262    }
2263    //printf("formatted: '%s'\n", mkcstr(ubuffer));
2264    UnicodeString act2(ubuffer);
2265    if ( act2 != exp2 ) {
2266        errln("Unexpected result from date 2 format\n");
2267    }
2268
2269    return;
2270}
2271
2272void CalendarTest::Test1624() {
2273    UErrorCode status = U_ZERO_ERROR;
2274    Locale loc("he_IL@calendar=hebrew");
2275    HebrewCalendar hc(loc,status);
2276
2277    for (int32_t year = 5600; year < 5800; year++ ) {
2278
2279        for (int32_t month = HebrewCalendar::TISHRI; month <= HebrewCalendar::ELUL; month++) {
2280            // skip the adar 1 month if year is not a leap year
2281            if (HebrewCalendar::isLeapYear(year) == FALSE && month == HebrewCalendar::ADAR_1) {
2282                continue;
2283            }
2284            int32_t day = 15;
2285            hc.set(year,month,day);
2286            int32_t dayHC = hc.get(UCAL_DATE,status);
2287            int32_t monthHC = hc.get(UCAL_MONTH,status);
2288            int32_t yearHC = hc.get(UCAL_YEAR,status);
2289
2290            if (failure(status, "HebrewCalendar.get()", TRUE)) continue;
2291
2292            if (dayHC != day) {
2293                errln(" ==> day %d incorrect, should be: %d\n",dayHC,day);
2294                break;
2295            }
2296            if (monthHC != month) {
2297                errln(" ==> month %d incorrect, should be: %d\n",monthHC,month);
2298                break;
2299            }
2300            if (yearHC != year) {
2301                errln(" ==> day %d incorrect, should be: %d\n",yearHC,year);
2302                break;
2303            }
2304        }
2305    }
2306    return;
2307}
2308
2309void CalendarTest::TestTimeStamp() {
2310    UErrorCode status = U_ZERO_ERROR;
2311    UDate start = 0.0, time;
2312    Calendar *cal;
2313
2314    // Create a new Gregorian Calendar.
2315    cal = Calendar::createInstance("en_US@calender=gregorian", status);
2316    if (U_FAILURE(status)) {
2317        dataerrln("Error creating Gregorian calendar.");
2318        return;
2319    }
2320
2321    for (int i = 0; i < 20000; i++) {
2322        // Set the Gregorian Calendar to a specific date for testing.
2323        cal->set(2009, UCAL_JULY, 3, 0, 49, 46);
2324
2325        time = cal->getTime(status);
2326        if (U_FAILURE(status)) {
2327            errln("Error calling getTime()");
2328            break;
2329        }
2330
2331        if (i == 0) {
2332            start = time;
2333        } else {
2334            if (start != time) {
2335                errln("start and time not equal.");
2336                break;
2337            }
2338        }
2339    }
2340
2341    delete cal;
2342}
2343
2344void CalendarTest::TestISO8601() {
2345    const char* TEST_LOCALES[] = {
2346        "en_US@calendar=iso8601",
2347        "en_US@calendar=Iso8601",
2348        "th_TH@calendar=iso8601",
2349        "ar_EG@calendar=iso8601",
2350        NULL
2351    };
2352
2353    int32_t TEST_DATA[][3] = {
2354        {2008, 1, 2008},
2355        {2009, 1, 2009},
2356        {2010, 53, 2009},
2357        {2011, 52, 2010},
2358        {2012, 52, 2011},
2359        {2013, 1, 2013},
2360        {2014, 1, 2014},
2361        {0, 0, 0},
2362    };
2363
2364    for (int i = 0; TEST_LOCALES[i] != NULL; i++) {
2365        UErrorCode status = U_ZERO_ERROR;
2366        Calendar *cal = Calendar::createInstance(TEST_LOCALES[i], status);
2367        if (U_FAILURE(status)) {
2368            errln("Error: Failed to create a calendar for locale: %s", TEST_LOCALES[i]);
2369            continue;
2370        }
2371        if (uprv_strcmp(cal->getType(), "gregorian") != 0) {
2372            errln("Error: Gregorian calendar is not used for locale: %s", TEST_LOCALES[i]);
2373            continue;
2374        }
2375        for (int j = 0; TEST_DATA[j][0] != 0; j++) {
2376            cal->set(TEST_DATA[j][0], UCAL_JANUARY, 1);
2377            int32_t weekNum = cal->get(UCAL_WEEK_OF_YEAR, status);
2378            int32_t weekYear = cal->get(UCAL_YEAR_WOY, status);
2379            if (U_FAILURE(status)) {
2380                errln("Error: Failed to get week of year");
2381                break;
2382            }
2383            if (weekNum != TEST_DATA[j][1] || weekYear != TEST_DATA[j][2]) {
2384                errln("Error: Incorrect week of year on January 1st, %d for locale %s: Returned [weekNum=%d, weekYear=%d], Expected [weekNum=%d, weekYear=%d]",
2385                    TEST_DATA[j][0], TEST_LOCALES[i], weekNum, weekYear, TEST_DATA[j][1], TEST_DATA[j][2]);
2386            }
2387        }
2388        delete cal;
2389    }
2390
2391}
2392
2393void
2394CalendarTest::TestAmbiguousWallTimeAPIs(void) {
2395    UErrorCode status = U_ZERO_ERROR;
2396    Calendar* cal = Calendar::createInstance(status);
2397    if (U_FAILURE(status)) {
2398        errln("Fail: Error creating a calendar instance.");
2399        return;
2400    }
2401
2402    if (cal->getRepeatedWallTimeOption() != UCAL_WALLTIME_LAST) {
2403        errln("Fail: Default repeted time option is not UCAL_WALLTIME_LAST");
2404    }
2405    if (cal->getSkippedWallTimeOption() != UCAL_WALLTIME_LAST) {
2406        errln("Fail: Default skipped time option is not UCAL_WALLTIME_LAST");
2407    }
2408
2409    Calendar* cal2 = cal->clone();
2410
2411    if (*cal != *cal2) {
2412        errln("Fail: Cloned calendar != the original");
2413    }
2414    if (!cal->equals(*cal2, status)) {
2415        errln("Fail: The time of cloned calendar is not equal to the original");
2416    } else if (U_FAILURE(status)) {
2417        errln("Fail: Error equals");
2418    }
2419    status = U_ZERO_ERROR;
2420
2421    cal2->setRepeatedWallTimeOption(UCAL_WALLTIME_FIRST);
2422    cal2->setSkippedWallTimeOption(UCAL_WALLTIME_FIRST);
2423
2424    if (*cal == *cal2) {
2425        errln("Fail: Cloned and modified calendar == the original");
2426    }
2427    if (!cal->equals(*cal2, status)) {
2428        errln("Fail: The time of cloned calendar is not equal to the original after changing wall time options");
2429    } else if (U_FAILURE(status)) {
2430        errln("Fail: Error equals after changing wall time options");
2431    }
2432    status = U_ZERO_ERROR;
2433
2434    if (cal2->getRepeatedWallTimeOption() != UCAL_WALLTIME_FIRST) {
2435        errln("Fail: Repeted time option is not UCAL_WALLTIME_FIRST");
2436    }
2437    if (cal2->getSkippedWallTimeOption() != UCAL_WALLTIME_FIRST) {
2438        errln("Fail: Skipped time option is not UCAL_WALLTIME_FIRST");
2439    }
2440
2441    cal2->setRepeatedWallTimeOption(UCAL_WALLTIME_NEXT_VALID);
2442    if (cal2->getRepeatedWallTimeOption() != UCAL_WALLTIME_FIRST) {
2443        errln("Fail: Repeated wall time option was updated other than UCAL_WALLTIME_FIRST");
2444    }
2445
2446    delete cal;
2447    delete cal2;
2448}
2449
2450class CalFields {
2451public:
2452    CalFields(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec, int32_t ms = 0);
2453    CalFields(const Calendar& cal, UErrorCode& status);
2454    void setTo(Calendar& cal) const;
2455    char* toString(char* buf, int32_t len) const;
2456    UBool operator==(const CalFields& rhs) const;
2457    UBool operator!=(const CalFields& rhs) const;
2458    UBool isEquivalentTo(const Calendar& cal, UErrorCode& status) const;
2459
2460private:
2461    int32_t year;
2462    int32_t month;
2463    int32_t day;
2464    int32_t hour;
2465    int32_t min;
2466    int32_t sec;
2467    int32_t ms;
2468};
2469
2470CalFields::CalFields(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec, int32_t ms)
2471    : year(year), month(month), day(day), hour(hour), min(min), sec(sec), ms(ms) {
2472}
2473
2474CalFields::CalFields(const Calendar& cal, UErrorCode& status) {
2475    year = cal.get(UCAL_YEAR, status);
2476    month = cal.get(UCAL_MONTH, status) + 1;
2477    day = cal.get(UCAL_DAY_OF_MONTH, status);
2478    hour = cal.get(UCAL_HOUR_OF_DAY, status);
2479    min = cal.get(UCAL_MINUTE, status);
2480    sec = cal.get(UCAL_SECOND, status);
2481    ms = cal.get(UCAL_MILLISECOND, status);
2482}
2483
2484void
2485CalFields::setTo(Calendar& cal) const {
2486    cal.clear();
2487    cal.set(year, month - 1, day, hour, min, sec);
2488    cal.set(UCAL_MILLISECOND, ms);
2489}
2490
2491char*
2492CalFields::toString(char* buf, int32_t len) const {
2493    char local[32];
2494    sprintf(local, "%04d-%02d-%02d %02d:%02d:%02d.%03d", year, month, day, hour, min, sec, ms);
2495    uprv_strncpy(buf, local, len - 1);
2496    buf[len - 1] = 0;
2497    return buf;
2498}
2499
2500UBool
2501CalFields::operator==(const CalFields& rhs) const {
2502    return year == rhs.year
2503        && month == rhs.month
2504        && day == rhs.day
2505        && hour == rhs.hour
2506        && min == rhs.min
2507        && sec == rhs.sec
2508        && ms == rhs.ms;
2509}
2510
2511UBool
2512CalFields::operator!=(const CalFields& rhs) const {
2513    return !(*this == rhs);
2514}
2515
2516UBool
2517CalFields::isEquivalentTo(const Calendar& cal, UErrorCode& status) const {
2518    return year == cal.get(UCAL_YEAR, status)
2519        && month == cal.get(UCAL_MONTH, status) + 1
2520        && day == cal.get(UCAL_DAY_OF_MONTH, status)
2521        && hour == cal.get(UCAL_HOUR_OF_DAY, status)
2522        && min == cal.get(UCAL_MINUTE, status)
2523        && sec == cal.get(UCAL_SECOND, status)
2524        && ms == cal.get(UCAL_MILLISECOND, status);
2525}
2526
2527typedef struct {
2528    const char*     tzid;
2529    const CalFields in;
2530    const CalFields expLastGMT;
2531    const CalFields expFirstGMT;
2532} RepeatedWallTimeTestData;
2533
2534static const RepeatedWallTimeTestData RPDATA[] =
2535{
2536    // Time zone            Input wall time                 WALLTIME_LAST in GMT            WALLTIME_FIRST in GMT
2537    {"America/New_York",    CalFields(2011,11,6,0,59,59),   CalFields(2011,11,6,4,59,59),   CalFields(2011,11,6,4,59,59)},
2538    {"America/New_York",    CalFields(2011,11,6,1,0,0),     CalFields(2011,11,6,6,0,0),     CalFields(2011,11,6,5,0,0)},
2539    {"America/New_York",    CalFields(2011,11,6,1,0,1),     CalFields(2011,11,6,6,0,1),     CalFields(2011,11,6,5,0,1)},
2540    {"America/New_York",    CalFields(2011,11,6,1,30,0),    CalFields(2011,11,6,6,30,0),    CalFields(2011,11,6,5,30,0)},
2541    {"America/New_York",    CalFields(2011,11,6,1,59,59),   CalFields(2011,11,6,6,59,59),   CalFields(2011,11,6,5,59,59)},
2542    {"America/New_York",    CalFields(2011,11,6,2,0,0),     CalFields(2011,11,6,7,0,0),     CalFields(2011,11,6,7,0,0)},
2543    {"America/New_York",    CalFields(2011,11,6,2,0,1),     CalFields(2011,11,6,7,0,1),     CalFields(2011,11,6,7,0,1)},
2544
2545    {"Australia/Lord_Howe", CalFields(2011,4,3,1,29,59),    CalFields(2011,4,2,14,29,59),   CalFields(2011,4,2,14,29,59)},
2546    {"Australia/Lord_Howe", CalFields(2011,4,3,1,30,0),     CalFields(2011,4,2,15,0,0),     CalFields(2011,4,2,14,30,0)},
2547    {"Australia/Lord_Howe", CalFields(2011,4,3,1,45,0),     CalFields(2011,4,2,15,15,0),    CalFields(2011,4,2,14,45,0)},
2548    {"Australia/Lord_Howe", CalFields(2011,4,3,1,59,59),    CalFields(2011,4,2,15,29,59),   CalFields(2011,4,2,14,59,59)},
2549    {"Australia/Lord_Howe", CalFields(2011,4,3,2,0,0),      CalFields(2011,4,2,15,30,0),    CalFields(2011,4,2,15,30,0)},
2550    {"Australia/Lord_Howe", CalFields(2011,4,3,2,0,1),      CalFields(2011,4,2,15,30,1),    CalFields(2011,4,2,15,30,1)},
2551
2552    {NULL,                  CalFields(0,0,0,0,0,0),         CalFields(0,0,0,0,0,0),          CalFields(0,0,0,0,0,0)}
2553};
2554
2555void CalendarTest::TestRepeatedWallTime(void) {
2556    UErrorCode status = U_ZERO_ERROR;
2557    GregorianCalendar calGMT((const TimeZone&)*TimeZone::getGMT(), status);
2558    GregorianCalendar calDefault(status);
2559    GregorianCalendar calLast(status);
2560    GregorianCalendar calFirst(status);
2561
2562    if (U_FAILURE(status)) {
2563        errln("Fail: Failed to create a calendar object.");
2564        return;
2565    }
2566
2567    calLast.setRepeatedWallTimeOption(UCAL_WALLTIME_LAST);
2568    calFirst.setRepeatedWallTimeOption(UCAL_WALLTIME_FIRST);
2569
2570    for (int32_t i = 0; RPDATA[i].tzid != NULL; i++) {
2571        char buf[32];
2572        TimeZone *tz = TimeZone::createTimeZone(RPDATA[i].tzid);
2573
2574        // UCAL_WALLTIME_LAST
2575        status = U_ZERO_ERROR;
2576        calLast.setTimeZone(*tz);
2577        RPDATA[i].in.setTo(calLast);
2578        calGMT.setTime(calLast.getTime(status), status);
2579        CalFields outLastGMT(calGMT, status);
2580        if (U_FAILURE(status)) {
2581            errln(UnicodeString("Fail: Failed to get/set time calLast/calGMT (UCAL_WALLTIME_LAST) - ")
2582                + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "]");
2583        } else {
2584            if (outLastGMT != RPDATA[i].expLastGMT) {
2585                dataerrln(UnicodeString("Fail: UCAL_WALLTIME_LAST ") + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "] is parsed as "
2586                    + outLastGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + RPDATA[i].expLastGMT.toString(buf, sizeof(buf)) + "[GMT]");
2587            }
2588        }
2589
2590        // default
2591        status = U_ZERO_ERROR;
2592        calDefault.setTimeZone(*tz);
2593        RPDATA[i].in.setTo(calDefault);
2594        calGMT.setTime(calDefault.getTime(status), status);
2595        CalFields outDefGMT(calGMT, status);
2596        if (U_FAILURE(status)) {
2597            errln(UnicodeString("Fail: Failed to get/set time calLast/calGMT (default) - ")
2598                + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "]");
2599        } else {
2600            if (outDefGMT != RPDATA[i].expLastGMT) {
2601                dataerrln(UnicodeString("Fail: (default) ") + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "] is parsed as "
2602                    + outDefGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + RPDATA[i].expLastGMT.toString(buf, sizeof(buf)) + "[GMT]");
2603            }
2604        }
2605
2606        // UCAL_WALLTIME_FIRST
2607        status = U_ZERO_ERROR;
2608        calFirst.setTimeZone(*tz);
2609        RPDATA[i].in.setTo(calFirst);
2610        calGMT.setTime(calFirst.getTime(status), status);
2611        CalFields outFirstGMT(calGMT, status);
2612        if (U_FAILURE(status)) {
2613            errln(UnicodeString("Fail: Failed to get/set time calLast/calGMT (UCAL_WALLTIME_FIRST) - ")
2614                + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "]");
2615        } else {
2616            if (outFirstGMT != RPDATA[i].expFirstGMT) {
2617                dataerrln(UnicodeString("Fail: UCAL_WALLTIME_FIRST ") + RPDATA[i].in.toString(buf, sizeof(buf)) + "[" + RPDATA[i].tzid + "] is parsed as "
2618                    + outFirstGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + RPDATA[i].expFirstGMT.toString(buf, sizeof(buf)) + "[GMT]");
2619            }
2620        }
2621        delete tz;
2622    }
2623}
2624
2625typedef struct {
2626    const char*     tzid;
2627    const CalFields in;
2628    UBool           isValid;
2629    const CalFields expLastGMT;
2630    const CalFields expFirstGMT;
2631    const CalFields expNextAvailGMT;
2632} SkippedWallTimeTestData;
2633
2634static SkippedWallTimeTestData SKDATA[] =
2635{
2636     // Time zone           Input wall time                 valid?  WALLTIME_LAST in GMT            WALLTIME_FIRST in GMT           WALLTIME_NEXT_VALID in GMT
2637    {"America/New_York",    CalFields(2011,3,13,1,59,59),   TRUE,   CalFields(2011,3,13,6,59,59),   CalFields(2011,3,13,6,59,59),   CalFields(2011,3,13,6,59,59)},
2638    {"America/New_York",    CalFields(2011,3,13,2,0,0),     FALSE,  CalFields(2011,3,13,7,0,0),     CalFields(2011,3,13,6,0,0),     CalFields(2011,3,13,7,0,0)},
2639    {"America/New_York",    CalFields(2011,3,13,2,1,0),     FALSE,  CalFields(2011,3,13,7,1,0),     CalFields(2011,3,13,6,1,0),     CalFields(2011,3,13,7,0,0)},
2640    {"America/New_York",    CalFields(2011,3,13,2,30,0),    FALSE,  CalFields(2011,3,13,7,30,0),    CalFields(2011,3,13,6,30,0),    CalFields(2011,3,13,7,0,0)},
2641    {"America/New_York",    CalFields(2011,3,13,2,59,59),   FALSE,  CalFields(2011,3,13,7,59,59),   CalFields(2011,3,13,6,59,59),   CalFields(2011,3,13,7,0,0)},
2642    {"America/New_York",    CalFields(2011,3,13,3,0,0),     TRUE,   CalFields(2011,3,13,7,0,0),     CalFields(2011,3,13,7,0,0),     CalFields(2011,3,13,7,0,0)},
2643
2644    {"Pacific/Apia",        CalFields(2011,12,29,23,59,59), TRUE,   CalFields(2011,12,30,9,59,59),  CalFields(2011,12,30,9,59,59),  CalFields(2011,12,30,9,59,59)},
2645    {"Pacific/Apia",        CalFields(2011,12,30,0,0,0),    FALSE,  CalFields(2011,12,30,10,0,0),   CalFields(2011,12,29,10,0,0),   CalFields(2011,12,30,10,0,0)},
2646    {"Pacific/Apia",        CalFields(2011,12,30,12,0,0),   FALSE,  CalFields(2011,12,30,22,0,0),   CalFields(2011,12,29,22,0,0),   CalFields(2011,12,30,10,0,0)},
2647    {"Pacific/Apia",        CalFields(2011,12,30,23,59,59), FALSE,  CalFields(2011,12,31,9,59,59),  CalFields(2011,12,30,9,59,59),  CalFields(2011,12,30,10,0,0)},
2648    {"Pacific/Apia",        CalFields(2011,12,31,0,0,0),    TRUE,   CalFields(2011,12,30,10,0,0),   CalFields(2011,12,30,10,0,0),   CalFields(2011,12,30,10,0,0)},
2649
2650    {NULL,                  CalFields(0,0,0,0,0,0),         TRUE,   CalFields(0,0,0,0,0,0),         CalFields(0,0,0,0,0,0),         CalFields(0,0,0,0,0,0)}
2651};
2652
2653
2654void CalendarTest::TestSkippedWallTime(void) {
2655    UErrorCode status = U_ZERO_ERROR;
2656    GregorianCalendar calGMT((const TimeZone&)*TimeZone::getGMT(), status);
2657    GregorianCalendar calDefault(status);
2658    GregorianCalendar calLast(status);
2659    GregorianCalendar calFirst(status);
2660    GregorianCalendar calNextAvail(status);
2661
2662    if (U_FAILURE(status)) {
2663        errln("Fail: Failed to create a calendar object.");
2664        return;
2665    }
2666
2667    calLast.setSkippedWallTimeOption(UCAL_WALLTIME_LAST);
2668    calFirst.setSkippedWallTimeOption(UCAL_WALLTIME_FIRST);
2669    calNextAvail.setSkippedWallTimeOption(UCAL_WALLTIME_NEXT_VALID);
2670
2671    for (int32_t i = 0; SKDATA[i].tzid != NULL; i++) {
2672        UDate d;
2673        char buf[32];
2674        TimeZone *tz = TimeZone::createTimeZone(SKDATA[i].tzid);
2675
2676        for (int32_t j = 0; j < 2; j++) {
2677            UBool bLenient = (j == 0);
2678
2679            // UCAL_WALLTIME_LAST
2680            status = U_ZERO_ERROR;
2681            calLast.setLenient(bLenient);
2682            calLast.setTimeZone(*tz);
2683            SKDATA[i].in.setTo(calLast);
2684            d = calLast.getTime(status);
2685            if (bLenient || SKDATA[i].isValid) {
2686                calGMT.setTime(d, status);
2687                CalFields outLastGMT(calGMT, status);
2688                if (U_FAILURE(status)) {
2689                    errln(UnicodeString("Fail: Failed to get/set time calLast/calGMT (UCAL_WALLTIME_LAST) - ")
2690                        + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
2691                } else {
2692                    if (outLastGMT != SKDATA[i].expLastGMT) {
2693                        dataerrln(UnicodeString("Fail: UCAL_WALLTIME_LAST ") + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "] is parsed as "
2694                            + outLastGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + SKDATA[i].expLastGMT.toString(buf, sizeof(buf)) + "[GMT]");
2695                    }
2696                }
2697            } else if (U_SUCCESS(status)) {
2698                // strict, invalid wall time - must report an error
2699                dataerrln(UnicodeString("Fail: An error expected (UCAL_WALLTIME_LAST)") +
2700                    + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
2701            }
2702
2703            // default
2704            status = U_ZERO_ERROR;
2705            calDefault.setLenient(bLenient);
2706            calDefault.setTimeZone(*tz);
2707            SKDATA[i].in.setTo(calDefault);
2708            d = calDefault.getTime(status);
2709            if (bLenient || SKDATA[i].isValid) {
2710                calGMT.setTime(d, status);
2711                CalFields outDefGMT(calGMT, status);
2712                if (U_FAILURE(status)) {
2713                    errln(UnicodeString("Fail: Failed to get/set time calDefault/calGMT (default) - ")
2714                        + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
2715                } else {
2716                    if (outDefGMT != SKDATA[i].expLastGMT) {
2717                        dataerrln(UnicodeString("Fail: (default) ") + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "] is parsed as "
2718                            + outDefGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + SKDATA[i].expLastGMT.toString(buf, sizeof(buf)) + "[GMT]");
2719                    }
2720                }
2721            } else if (U_SUCCESS(status)) {
2722                // strict, invalid wall time - must report an error
2723                dataerrln(UnicodeString("Fail: An error expected (default)") +
2724                    + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
2725            }
2726
2727            // UCAL_WALLTIME_FIRST
2728            status = U_ZERO_ERROR;
2729            calFirst.setLenient(bLenient);
2730            calFirst.setTimeZone(*tz);
2731            SKDATA[i].in.setTo(calFirst);
2732            d = calFirst.getTime(status);
2733            if (bLenient || SKDATA[i].isValid) {
2734                calGMT.setTime(d, status);
2735                CalFields outFirstGMT(calGMT, status);
2736                if (U_FAILURE(status)) {
2737                    errln(UnicodeString("Fail: Failed to get/set time calFirst/calGMT (UCAL_WALLTIME_FIRST) - ")
2738                        + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
2739                } else {
2740                    if (outFirstGMT != SKDATA[i].expFirstGMT) {
2741                        dataerrln(UnicodeString("Fail: UCAL_WALLTIME_FIRST ") + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "] is parsed as "
2742                            + outFirstGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + SKDATA[i].expFirstGMT.toString(buf, sizeof(buf)) + "[GMT]");
2743                    }
2744                }
2745            } else if (U_SUCCESS(status)) {
2746                // strict, invalid wall time - must report an error
2747                dataerrln(UnicodeString("Fail: An error expected (UCAL_WALLTIME_FIRST)") +
2748                    + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
2749            }
2750
2751            // UCAL_WALLTIME_NEXT_VALID
2752            status = U_ZERO_ERROR;
2753            calNextAvail.setLenient(bLenient);
2754            calNextAvail.setTimeZone(*tz);
2755            SKDATA[i].in.setTo(calNextAvail);
2756            d = calNextAvail.getTime(status);
2757            if (bLenient || SKDATA[i].isValid) {
2758                calGMT.setTime(d, status);
2759                CalFields outNextAvailGMT(calGMT, status);
2760                if (U_FAILURE(status)) {
2761                    errln(UnicodeString("Fail: Failed to get/set time calNextAvail/calGMT (UCAL_WALLTIME_NEXT_VALID) - ")
2762                        + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
2763                } else {
2764                    if (outNextAvailGMT != SKDATA[i].expNextAvailGMT) {
2765                        dataerrln(UnicodeString("Fail: UCAL_WALLTIME_NEXT_VALID ") + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "] is parsed as "
2766                            + outNextAvailGMT.toString(buf, sizeof(buf)) + "[GMT]. Expected: " + SKDATA[i].expNextAvailGMT.toString(buf, sizeof(buf)) + "[GMT]");
2767                    }
2768                }
2769            } else if (U_SUCCESS(status)) {
2770                // strict, invalid wall time - must report an error
2771                dataerrln(UnicodeString("Fail: An error expected (UCAL_WALLTIME_NEXT_VALID)") +
2772                    + SKDATA[i].in.toString(buf, sizeof(buf)) + "[" + SKDATA[i].tzid + "]");
2773            }
2774        }
2775
2776        delete tz;
2777    }
2778}
2779
2780void CalendarTest::TestCloneLocale(void) {
2781  UErrorCode status = U_ZERO_ERROR;
2782  LocalPointer<Calendar>  cal(Calendar::createInstance(TimeZone::getGMT()->clone(),
2783                                                       Locale::createFromName("en"), status));
2784  TEST_CHECK_STATUS;
2785  Locale l0 = cal->getLocale(ULOC_VALID_LOCALE, status);
2786  TEST_CHECK_STATUS;
2787  LocalPointer<Calendar> cal2(cal->clone());
2788  Locale l = cal2->getLocale(ULOC_VALID_LOCALE, status);
2789  if(l0!=l) {
2790    errln("Error: cloned locale %s != original locale %s, status %s\n", l0.getName(), l.getName(), u_errorName(status));
2791  }
2792  TEST_CHECK_STATUS;
2793}
2794
2795void CalendarTest::setAndTestCalendar(Calendar* cal, int32_t initMonth, int32_t initDay, int32_t initYear, UErrorCode& status) {
2796        cal->clear();
2797        cal->setLenient(FALSE);
2798        cal->set(initYear, initMonth, initDay);
2799        int32_t day = cal->get(UCAL_DAY_OF_MONTH, status);
2800        int32_t month = cal->get(UCAL_MONTH, status);
2801        int32_t year = cal->get(UCAL_YEAR, status);
2802        if(U_FAILURE(status))
2803            return;
2804
2805        if(initDay != day || initMonth != month || initYear != year)
2806        {
2807            errln(" year init values:\tmonth %i\tday %i\tyear %i", initMonth, initDay, initYear);
2808            errln("values post set():\tmonth %i\tday %i\tyear %i",month, day, year);
2809        }
2810}
2811
2812void CalendarTest::setAndTestWholeYear(Calendar* cal, int32_t startYear, UErrorCode& status) {
2813        for(int32_t startMonth = 0; startMonth < 12; startMonth++) {
2814            for(int32_t startDay = 1; startDay < 31; startDay++ ) {
2815                    setAndTestCalendar(cal, startMonth, startDay, startYear, status);
2816                    if(U_FAILURE(status) && startDay == 30) {
2817                        status = U_ZERO_ERROR;
2818                        continue;
2819                    }
2820                    TEST_CHECK_STATUS;
2821            }
2822        }
2823}
2824
2825// =====================================================================
2826
2827typedef struct {
2828    int16_t  gYear;
2829    int8_t   gMon;
2830    int8_t   gDay;
2831    int16_t  uYear;
2832    int8_t   uMon;
2833    int8_t   uDay;
2834} GregoUmmAlQuraMap;
2835
2836// data from
2837// Official Umm-al-Qura calendar of SA:
2838// home, http://www.ummulqura.org.sa/default.aspx
2839// converter, http://www.ummulqura.org.sa/Index.aspx
2840static const GregoUmmAlQuraMap guMappings[] = {
2841//  gregorian,    ummAlQura
2842//  year mo da,   year mo da
2843//  (using 1-based months here)
2844  { 1882,11,12,   1300, 1, 1 },
2845  { 1892, 7,25,   1310, 1, 1 },
2846  { 1896, 6,12,   1314, 1, 1 },
2847  { 1898, 5,22,   1316, 1, 1 },
2848  { 1900, 4,30,   1318, 1, 1 },
2849  { 1901, 4,20,   1319, 1, 1 },
2850  { 1902, 4,10,   1320, 1, 1 },
2851  { 1903, 3,30,   1321, 1, 1 },
2852  { 1904, 3,19,   1322, 1, 1 },
2853  { 1905, 3, 8,   1323, 1, 1 },
2854  { 1906, 2,25,   1324, 1, 1 },
2855  { 1907, 2,14,   1325, 1, 1 },
2856  { 1908, 2, 4,   1326, 1, 1 },
2857  { 1909, 1,23,   1327, 1, 1 },
2858  { 1910, 1,13,   1328, 1, 1 },
2859  { 1911, 1, 2,   1329, 1, 1 },
2860  { 1911,12,22,   1330, 1, 1 },
2861  { 1912,12,10,   1331, 1, 1 },
2862  { 1913,11,30,   1332, 1, 1 },
2863  { 1914,11,19,   1333, 1, 1 },
2864  { 1915,11, 9,   1334, 1, 1 },
2865  { 1916,10,28,   1335, 1, 1 },
2866  { 1917,10,18,   1336, 1, 1 },
2867  { 1918,10, 7,   1337, 1, 1 },
2868  { 1919, 9,26,   1338, 1, 1 },
2869  { 1920, 9,14,   1339, 1, 1 },
2870  { 1921, 9, 4,   1340, 1, 1 },
2871  { 1922, 8,24,   1341, 1, 1 },
2872  { 1923, 8,14,   1342, 1, 1 },
2873  { 1924, 8, 2,   1343, 1, 1 },
2874  { 1925, 7,22,   1344, 1, 1 },
2875  { 1926, 7,11,   1345, 1, 1 },
2876  { 1927, 6,30,   1346, 1, 1 },
2877  { 1928, 6,19,   1347, 1, 1 },
2878  { 1929, 6, 9,   1348, 1, 1 },
2879  { 1930, 5,29,   1349, 1, 1 },
2880  { 1931, 5,19,   1350, 1, 1 },
2881  { 1932, 5, 7,   1351, 1, 1 },
2882  { 1933, 4,26,   1352, 1, 1 },
2883  { 1934, 4,15,   1353, 1, 1 },
2884  { 1935, 4, 5,   1354, 1, 1 },
2885  { 1936, 3,24,   1355, 1, 1 },
2886  { 1937, 3,14,   1356, 1, 1 },
2887  { 1938, 3, 4,   1357, 1, 1 },
2888  { 1939, 2,21,   1358, 1, 1 },
2889  { 1940, 2,10,   1359, 1, 1 },
2890  { 1941, 1,29,   1360, 1, 1 },
2891  { 1942, 1,18,   1361, 1, 1 },
2892  { 1943, 1, 8,   1362, 1, 1 },
2893  { 1943,12,28,   1363, 1, 1 },
2894  { 1944,12,17,   1364, 1, 1 },
2895  { 1945,12, 6,   1365, 1, 1 },
2896  { 1946,11,25,   1366, 1, 1 },
2897  { 1947,11,14,   1367, 1, 1 },
2898  { 1948,11, 3,   1368, 1, 1 },
2899  { 1949,10,23,   1369, 1, 1 },
2900  { 1950,10,13,   1370, 1, 1 },
2901  { 1951,10, 3,   1371, 1, 1 },
2902  { 1952, 9,21,   1372, 1, 1 },
2903  { 1953, 9,10,   1373, 1, 1 },
2904  { 1954, 8,30,   1374, 1, 1 },
2905  { 1955, 8,19,   1375, 1, 1 },
2906  { 1956, 8, 8,   1376, 1, 1 },
2907  { 1957, 7,29,   1377, 1, 1 },
2908  { 1958, 7,18,   1378, 1, 1 },
2909  { 1959, 7, 8,   1379, 1, 1 },
2910  { 1960, 6,26,   1380, 1, 1 },
2911  { 1961, 6,15,   1381, 1, 1 },
2912  { 1962, 6, 4,   1382, 1, 1 },
2913  { 1963, 5,24,   1383, 1, 1 },
2914  { 1964, 5,13,   1384, 1, 1 },
2915  { 1965, 5, 3,   1385, 1, 1 },
2916  { 1966, 4,22,   1386, 1, 1 },
2917  { 1967, 4,11,   1387, 1, 1 },
2918  { 1968, 3,30,   1388, 1, 1 },
2919  { 1969, 3,19,   1389, 1, 1 },
2920  { 1970, 3, 9,   1390, 1, 1 },
2921  { 1971, 2,27,   1391, 1, 1 },
2922  { 1972, 2,16,   1392, 1, 1 },
2923  { 1973, 2, 5,   1393, 1, 1 },
2924  { 1974, 1,25,   1394, 1, 1 },
2925  { 1975, 1,14,   1395, 1, 1 },
2926  { 1976, 1, 3,   1396, 1, 1 },
2927  { 1976,12,22,   1397, 1, 1 },
2928  { 1977,12,12,   1398, 1, 1 },
2929  { 1978,12, 1,   1399, 1, 1 },
2930  { 1979,11,21,   1400, 1, 1 },
2931  { 1980,11, 9,   1401, 1, 1 },
2932  { 1981,10,29,   1402, 1, 1 },
2933  { 1982,10,18,   1403, 1, 1 },
2934  { 1983,10, 8,   1404, 1, 1 },
2935  { 1984, 9,26,   1405, 1, 1 },
2936  { 1985, 9,16,   1406, 1, 1 },
2937  { 1986, 9, 6,   1407, 1, 1 },
2938  { 1987, 8,26,   1408, 1, 1 },
2939  { 1988, 8,14,   1409, 1, 1 },
2940  { 1989, 8, 3,   1410, 1, 1 },
2941  { 1990, 7,23,   1411, 1, 1 },
2942  { 1991, 7,13,   1412, 1, 1 },
2943  { 1992, 7, 2,   1413, 1, 1 },
2944  { 1993, 6,21,   1414, 1, 1 },
2945  { 1994, 6,11,   1415, 1, 1 },
2946  { 1995, 5,31,   1416, 1, 1 },
2947  { 1996, 5,19,   1417, 1, 1 },
2948  { 1997, 5, 8,   1418, 1, 1 },
2949  { 1998, 4,28,   1419, 1, 1 },
2950  { 1999, 4,17,   1420, 1, 1 },
2951  { 1999, 5,16,   1420, 2, 1 },
2952  { 1999, 6,15,   1420, 3, 1 },
2953  { 1999, 7,14,   1420, 4, 1 },
2954  { 1999, 8,12,   1420, 5, 1 },
2955  { 1999, 9,11,   1420, 6, 1 },
2956  { 1999,10,10,   1420, 7, 1 },
2957  { 1999,11, 9,   1420, 8, 1 },
2958  { 1999,12, 9,   1420, 9, 1 },
2959  { 2000, 1, 8,   1420,10, 1 },
2960  { 2000, 2, 7,   1420,11, 1 },
2961  { 2000, 3, 7,   1420,12, 1 },
2962  { 2000, 4, 6,   1421, 1, 1 },
2963  { 2000, 5, 5,   1421, 2, 1 },
2964  { 2000, 6, 3,   1421, 3, 1 },
2965  { 2000, 7, 3,   1421, 4, 1 },
2966  { 2000, 8, 1,   1421, 5, 1 },
2967  { 2000, 8,30,   1421, 6, 1 },
2968  { 2000, 9,28,   1421, 7, 1 },
2969  { 2000,10,28,   1421, 8, 1 },
2970  { 2000,11,27,   1421, 9, 1 },
2971  { 2000,12,27,   1421,10, 1 },
2972  { 2001, 1,26,   1421,11, 1 },
2973  { 2001, 2,24,   1421,12, 1 },
2974  { 2001, 3,26,   1422, 1, 1 },
2975  { 2001, 4,25,   1422, 2, 1 },
2976  { 2001, 5,24,   1422, 3, 1 },
2977  { 2001, 6,22,   1422, 4, 1 },
2978  { 2001, 7,22,   1422, 5, 1 },
2979  { 2001, 8,20,   1422, 6, 1 },
2980  { 2001, 9,18,   1422, 7, 1 },
2981  { 2001,10,17,   1422, 8, 1 },
2982  { 2001,11,16,   1422, 9, 1 },
2983  { 2001,12,16,   1422,10, 1 },
2984  { 2002, 1,15,   1422,11, 1 },
2985  { 2002, 2,13,   1422,12, 1 },
2986  { 2002, 3,15,   1423, 1, 1 },
2987  { 2002, 4,14,   1423, 2, 1 },
2988  { 2002, 5,13,   1423, 3, 1 },
2989  { 2002, 6,12,   1423, 4, 1 },
2990  { 2002, 7,11,   1423, 5, 1 },
2991  { 2002, 8,10,   1423, 6, 1 },
2992  { 2002, 9, 8,   1423, 7, 1 },
2993  { 2002,10, 7,   1423, 8, 1 },
2994  { 2002,11, 6,   1423, 9, 1 },
2995  { 2002,12, 5,   1423,10, 1 },
2996  { 2003, 1, 4,   1423,11, 1 },
2997  { 2003, 2, 2,   1423,12, 1 },
2998  { 2003, 3, 4,   1424, 1, 1 },
2999  { 2003, 4, 3,   1424, 2, 1 },
3000  { 2003, 5, 2,   1424, 3, 1 },
3001  { 2003, 6, 1,   1424, 4, 1 },
3002  { 2003, 7, 1,   1424, 5, 1 },
3003  { 2003, 7,30,   1424, 6, 1 },
3004  { 2003, 8,29,   1424, 7, 1 },
3005  { 2003, 9,27,   1424, 8, 1 },
3006  { 2003,10,26,   1424, 9, 1 },
3007  { 2003,11,25,   1424,10, 1 },
3008  { 2003,12,24,   1424,11, 1 },
3009  { 2004, 1,23,   1424,12, 1 },
3010  { 2004, 2,21,   1425, 1, 1 },
3011  { 2004, 3,22,   1425, 2, 1 },
3012  { 2004, 4,20,   1425, 3, 1 },
3013  { 2004, 5,20,   1425, 4, 1 },
3014  { 2004, 6,19,   1425, 5, 1 },
3015  { 2004, 7,18,   1425, 6, 1 },
3016  { 2004, 8,17,   1425, 7, 1 },
3017  { 2004, 9,15,   1425, 8, 1 },
3018  { 2004,10,15,   1425, 9, 1 },
3019  { 2004,11,14,   1425,10, 1 },
3020  { 2004,12,13,   1425,11, 1 },
3021  { 2005, 1,12,   1425,12, 1 },
3022  { 2005, 2,10,   1426, 1, 1 },
3023  { 2005, 3,11,   1426, 2, 1 },
3024  { 2005, 4,10,   1426, 3, 1 },
3025  { 2005, 5, 9,   1426, 4, 1 },
3026  { 2005, 6, 8,   1426, 5, 1 },
3027  { 2005, 7, 7,   1426, 6, 1 },
3028  { 2005, 8, 6,   1426, 7, 1 },
3029  { 2005, 9, 5,   1426, 8, 1 },
3030  { 2005,10, 4,   1426, 9, 1 },
3031  { 2005,11, 3,   1426,10, 1 },
3032  { 2005,12, 3,   1426,11, 1 },
3033  { 2006, 1, 1,   1426,12, 1 },
3034  { 2006, 1,31,   1427, 1, 1 },
3035  { 2006, 3, 1,   1427, 2, 1 },
3036  { 2006, 3,30,   1427, 3, 1 },
3037  { 2006, 4,29,   1427, 4, 1 },
3038  { 2006, 5,28,   1427, 5, 1 },
3039  { 2006, 6,27,   1427, 6, 1 },
3040  { 2006, 7,26,   1427, 7, 1 },
3041  { 2006, 8,25,   1427, 8, 1 },
3042  { 2006, 9,24,   1427, 9, 1 },
3043  { 2006,10,23,   1427,10, 1 },
3044  { 2006,11,22,   1427,11, 1 },
3045  { 2006,12,22,   1427,12, 1 },
3046  { 2007, 1,20,   1428, 1, 1 },
3047  { 2007, 2,19,   1428, 2, 1 },
3048  { 2007, 3,20,   1428, 3, 1 },
3049  { 2007, 4,18,   1428, 4, 1 },
3050  { 2007, 5,18,   1428, 5, 1 },
3051  { 2007, 6,16,   1428, 6, 1 },
3052  { 2007, 7,15,   1428, 7, 1 },
3053  { 2007, 8,14,   1428, 8, 1 },
3054  { 2007, 9,13,   1428, 9, 1 },
3055  { 2007,10,13,   1428,10, 1 },
3056  { 2007,11,11,   1428,11, 1 },
3057  { 2007,12,11,   1428,12, 1 },
3058  { 2008, 1,10,   1429, 1, 1 },
3059  { 2008, 2, 8,   1429, 2, 1 },
3060  { 2008, 3, 9,   1429, 3, 1 },
3061  { 2008, 4, 7,   1429, 4, 1 },
3062  { 2008, 5, 6,   1429, 5, 1 },
3063  { 2008, 6, 5,   1429, 6, 1 },
3064  { 2008, 7, 4,   1429, 7, 1 },
3065  { 2008, 8, 2,   1429, 8, 1 },
3066  { 2008, 9, 1,   1429, 9, 1 },
3067  { 2008,10, 1,   1429,10, 1 },
3068  { 2008,10,30,   1429,11, 1 },
3069  { 2008,11,29,   1429,12, 1 },
3070  { 2008,12,29,   1430, 1, 1 },
3071  { 2009, 1,27,   1430, 2, 1 },
3072  { 2009, 2,26,   1430, 3, 1 },
3073  { 2009, 3,28,   1430, 4, 1 },
3074  { 2009, 4,26,   1430, 5, 1 },
3075  { 2009, 5,25,   1430, 6, 1 },
3076  { 2009, 6,24,   1430, 7, 1 },
3077  { 2009, 7,23,   1430, 8, 1 },
3078  { 2009, 8,22,   1430, 9, 1 },
3079  { 2009, 9,20,   1430,10, 1 },
3080  { 2009,10,20,   1430,11, 1 },
3081  { 2009,11,18,   1430,12, 1 },
3082  { 2009,12,18,   1431, 1, 1 },
3083  { 2010, 1,16,   1431, 2, 1 },
3084  { 2010, 2,15,   1431, 3, 1 },
3085  { 2010, 3,17,   1431, 4, 1 },
3086  { 2010, 4,15,   1431, 5, 1 },
3087  { 2010, 5,15,   1431, 6, 1 },
3088  { 2010, 6,13,   1431, 7, 1 },
3089  { 2010, 7,13,   1431, 8, 1 },
3090  { 2010, 8,11,   1431, 9, 1 },
3091  { 2010, 9,10,   1431,10, 1 },
3092  { 2010,10, 9,   1431,11, 1 },
3093  { 2010,11, 7,   1431,12, 1 },
3094  { 2010,12, 7,   1432, 1, 1 },
3095  { 2011, 1, 5,   1432, 2, 1 },
3096  { 2011, 2, 4,   1432, 3, 1 },
3097  { 2011, 3, 6,   1432, 4, 1 },
3098  { 2011, 4, 5,   1432, 5, 1 },
3099  { 2011, 5, 4,   1432, 6, 1 },
3100  { 2011, 6, 3,   1432, 7, 1 },
3101  { 2011, 7, 2,   1432, 8, 1 },
3102  { 2011, 8, 1,   1432, 9, 1 },
3103  { 2011, 8,30,   1432,10, 1 },
3104  { 2011, 9,29,   1432,11, 1 },
3105  { 2011,10,28,   1432,12, 1 },
3106  { 2011,11,26,   1433, 1, 1 },
3107  { 2011,12,26,   1433, 2, 1 },
3108  { 2012, 1,24,   1433, 3, 1 },
3109  { 2012, 2,23,   1433, 4, 1 },
3110  { 2012, 3,24,   1433, 5, 1 },
3111  { 2012, 4,22,   1433, 6, 1 },
3112  { 2012, 5,22,   1433, 7, 1 },
3113  { 2012, 6,21,   1433, 8, 1 },
3114  { 2012, 7,20,   1433, 9, 1 },
3115  { 2012, 8,19,   1433,10, 1 },
3116  { 2012, 9,17,   1433,11, 1 },
3117  { 2012,10,17,   1433,12, 1 },
3118  { 2012,11,15,   1434, 1, 1 },
3119  { 2012,12,14,   1434, 2, 1 },
3120  { 2013, 1,13,   1434, 3, 1 },
3121  { 2013, 2,11,   1434, 4, 1 },
3122  { 2013, 3,13,   1434, 5, 1 },
3123  { 2013, 4,11,   1434, 6, 1 },
3124  { 2013, 5,11,   1434, 7, 1 },
3125  { 2013, 6,10,   1434, 8, 1 },
3126  { 2013, 7, 9,   1434, 9, 1 },
3127  { 2013, 8, 8,   1434,10, 1 },
3128  { 2013, 9, 7,   1434,11, 1 },
3129  { 2013,10, 6,   1434,12, 1 },
3130  { 2013,11, 4,   1435, 1, 1 },
3131  { 2013,12, 4,   1435, 2, 1 },
3132  { 2014, 1, 2,   1435, 3, 1 },
3133  { 2014, 2, 1,   1435, 4, 1 },
3134  { 2014, 3, 2,   1435, 5, 1 },
3135  { 2014, 4, 1,   1435, 6, 1 },
3136  { 2014, 4,30,   1435, 7, 1 },
3137  { 2014, 5,30,   1435, 8, 1 },
3138  { 2014, 6,28,   1435, 9, 1 },
3139  { 2014, 7,28,   1435,10, 1 },
3140  { 2014, 8,27,   1435,11, 1 },
3141  { 2014, 9,25,   1435,12, 1 },
3142  { 2014,10,25,   1436, 1, 1 },
3143  { 2014,11,23,   1436, 2, 1 },
3144  { 2014,12,23,   1436, 3, 1 },
3145  { 2015, 1,21,   1436, 4, 1 },
3146  { 2015, 2,20,   1436, 5, 1 },
3147  { 2015, 3,21,   1436, 6, 1 },
3148  { 2015, 4,20,   1436, 7, 1 },
3149  { 2015, 5,19,   1436, 8, 1 },
3150  { 2015, 6,18,   1436, 9, 1 },
3151  { 2015, 7,17,   1436,10, 1 },
3152  { 2015, 8,16,   1436,11, 1 },
3153  { 2015, 9,14,   1436,12, 1 },
3154  { 2015,10,14,   1437, 1, 1 },
3155  { 2015,11,13,   1437, 2, 1 },
3156  { 2015,12,12,   1437, 3, 1 },
3157  { 2016, 1,11,   1437, 4, 1 },
3158  { 2016, 2,10,   1437, 5, 1 },
3159  { 2016, 3,10,   1437, 6, 1 },
3160  { 2016, 4, 8,   1437, 7, 1 },
3161  { 2016, 5, 8,   1437, 8, 1 },
3162  { 2016, 6, 6,   1437, 9, 1 },
3163  { 2016, 7, 6,   1437,10, 1 },
3164  { 2016, 8, 4,   1437,11, 1 },
3165  { 2016, 9, 2,   1437,12, 1 },
3166  { 2016,10, 2,   1438, 1, 1 },
3167  { 2016,11, 1,   1438, 2, 1 },
3168  { 2016,11,30,   1438, 3, 1 },
3169  { 2016,12,30,   1438, 4, 1 },
3170  { 2017, 1,29,   1438, 5, 1 },
3171  { 2017, 2,28,   1438, 6, 1 },
3172  { 2017, 3,29,   1438, 7, 1 },
3173  { 2017, 4,27,   1438, 8, 1 },
3174  { 2017, 5,27,   1438, 9, 1 },
3175  { 2017, 6,25,   1438,10, 1 },
3176  { 2017, 7,24,   1438,11, 1 },
3177  { 2017, 8,23,   1438,12, 1 },
3178  { 2017, 9,21,   1439, 1, 1 },
3179  { 2017,10,21,   1439, 2, 1 },
3180  { 2017,11,19,   1439, 3, 1 },
3181  { 2017,12,19,   1439, 4, 1 },
3182  { 2018, 1,18,   1439, 5, 1 },
3183  { 2018, 2,17,   1439, 6, 1 },
3184  { 2018, 3,18,   1439, 7, 1 },
3185  { 2018, 4,17,   1439, 8, 1 },
3186  { 2018, 5,16,   1439, 9, 1 },
3187  { 2018, 6,15,   1439,10, 1 },
3188  { 2018, 7,14,   1439,11, 1 },
3189  { 2018, 8,12,   1439,12, 1 },
3190  { 2018, 9,11,   1440, 1, 1 },
3191  { 2019, 8,31,   1441, 1, 1 },
3192  { 2020, 8,20,   1442, 1, 1 },
3193  { 2021, 8, 9,   1443, 1, 1 },
3194  { 2022, 7,30,   1444, 1, 1 },
3195  { 2023, 7,19,   1445, 1, 1 },
3196  { 2024, 7, 7,   1446, 1, 1 },
3197  { 2025, 6,26,   1447, 1, 1 },
3198  { 2026, 6,16,   1448, 1, 1 },
3199  { 2027, 6, 6,   1449, 1, 1 },
3200  { 2028, 5,25,   1450, 1, 1 },
3201  { 2029, 5,14,   1451, 1, 1 },
3202  { 2030, 5, 4,   1452, 1, 1 },
3203  { 2031, 4,23,   1453, 1, 1 },
3204  { 2032, 4,11,   1454, 1, 1 },
3205  { 2033, 4, 1,   1455, 1, 1 },
3206  { 2034, 3,22,   1456, 1, 1 },
3207  { 2035, 3,11,   1457, 1, 1 },
3208  { 2036, 2,29,   1458, 1, 1 },
3209  { 2037, 2,17,   1459, 1, 1 },
3210  { 2038, 2, 6,   1460, 1, 1 },
3211  { 2039, 1,26,   1461, 1, 1 },
3212  { 2040, 1,15,   1462, 1, 1 },
3213  { 2041, 1, 4,   1463, 1, 1 },
3214  { 2041,12,25,   1464, 1, 1 },
3215  { 2042,12,14,   1465, 1, 1 },
3216  { 2043,12, 3,   1466, 1, 1 },
3217  { 2044,11,21,   1467, 1, 1 },
3218  { 2045,11,11,   1468, 1, 1 },
3219  { 2046,10,31,   1469, 1, 1 },
3220  { 2047,10,21,   1470, 1, 1 },
3221  { 2048,10, 9,   1471, 1, 1 },
3222  { 2049, 9,29,   1472, 1, 1 },
3223  { 2050, 9,18,   1473, 1, 1 },
3224  { 2051, 9, 7,   1474, 1, 1 },
3225  { 2052, 8,26,   1475, 1, 1 },
3226  { 2053, 8,15,   1476, 1, 1 },
3227  { 2054, 8, 5,   1477, 1, 1 },
3228  { 2055, 7,26,   1478, 1, 1 },
3229  { 2056, 7,14,   1479, 1, 1 },
3230  { 2057, 7, 3,   1480, 1, 1 },
3231  { 2058, 6,22,   1481, 1, 1 },
3232  { 2059, 6,11,   1482, 1, 1 },
3233  { 2061, 5,21,   1484, 1, 1 },
3234  { 2063, 4,30,   1486, 1, 1 },
3235  { 2065, 4, 7,   1488, 1, 1 },
3236  { 2067, 3,17,   1490, 1, 1 },
3237  { 2069, 2,23,   1492, 1, 1 },
3238  { 2071, 2, 2,   1494, 1, 1 },
3239  { 2073, 1,10,   1496, 1, 1 },
3240  { 2074,12,20,   1498, 1, 1 },
3241  { 2076,11,28,   1500, 1, 1 },
3242  {    0, 0, 0,      0, 0, 0 }, // terminator
3243};
3244
3245static const UChar zoneSA[] = {0x41,0x73,0x69,0x61,0x2F,0x52,0x69,0x79,0x61,0x64,0x68,0}; // "Asia/Riyadh"
3246
3247void CalendarTest::TestIslamicUmAlQura() {
3248
3249    UErrorCode status = U_ZERO_ERROR;
3250    Locale umalquraLoc("ar_SA@calendar=islamic-umalqura");
3251    Locale gregoLoc("ar_SA@calendar=gregorian");
3252    TimeZone* tzSA = TimeZone::createTimeZone(UnicodeString(TRUE, zoneSA, -1));
3253    Calendar* tstCal = Calendar::createInstance(*((const TimeZone *)tzSA), umalquraLoc, status);
3254    Calendar* gregCal = Calendar::createInstance(*((const TimeZone *)tzSA), gregoLoc, status);
3255
3256    IslamicCalendar* iCal = (IslamicCalendar*)tstCal;
3257    if(strcmp(iCal->getType(), "islamic-umalqura") != 0) {
3258        errln("wrong type of calendar created - %s", iCal->getType());
3259    }
3260
3261    int32_t firstYear = 1318;
3262    int32_t lastYear = 1368;    // just enough to be pretty sure
3263    //int32_t lastYear = 1480;    // the whole shootin' match
3264
3265    tstCal->clear();
3266    tstCal->setLenient(FALSE);
3267
3268    int32_t day=0, month=0, year=0, initDay = 27, initMonth = IslamicCalendar::RAJAB, initYear = 1434;
3269
3270    for( int32_t startYear = firstYear; startYear <= lastYear; startYear++) {
3271        setAndTestWholeYear(tstCal, startYear, status);
3272        status = U_ZERO_ERROR;
3273    }
3274
3275    initMonth = IslamicCalendar::RABI_2;
3276    initDay = 5;
3277    int32_t loopCnt = 25;
3278    tstCal->clear();
3279    setAndTestCalendar( tstCal, initMonth, initDay, initYear, status);
3280    TEST_CHECK_STATUS;
3281
3282    for(int x=1; x<=loopCnt; x++) {
3283        day = tstCal->get(UCAL_DAY_OF_MONTH,status);
3284        month = tstCal->get(UCAL_MONTH,status);
3285        year = tstCal->get(UCAL_YEAR,status);
3286        TEST_CHECK_STATUS;
3287        tstCal->roll(UCAL_DAY_OF_MONTH, (UBool)TRUE, status);
3288        TEST_CHECK_STATUS;
3289    }
3290
3291    if(day != (initDay + loopCnt - 1) || month != IslamicCalendar::RABI_2 || year != 1434)
3292      errln("invalid values for RABI_2 date after roll of %d", loopCnt);
3293
3294    status = U_ZERO_ERROR;
3295    tstCal->clear();
3296    initMonth = 2;
3297    initDay = 30;
3298    setAndTestCalendar( tstCal, initMonth, initDay, initYear, status);
3299    if(U_SUCCESS(status)) {
3300        errln("error NOT detected status %i",status);
3301        errln("      init values:\tmonth %i\tday %i\tyear %i", initMonth, initDay, initYear);
3302        int32_t day = tstCal->get(UCAL_DAY_OF_MONTH, status);
3303        int32_t month = tstCal->get(UCAL_MONTH, status);
3304        int32_t year = tstCal->get(UCAL_YEAR, status);
3305        errln("values post set():\tmonth %i\tday %i\tyear %i",month, day, year);
3306    }
3307
3308    status = U_ZERO_ERROR;
3309    tstCal->clear();
3310    initMonth = 3;
3311    initDay = 30;
3312    setAndTestCalendar( tstCal, initMonth, initDay, initYear, status);
3313    TEST_CHECK_STATUS;
3314
3315    SimpleDateFormat* formatter = new SimpleDateFormat("yyyy-MM-dd", Locale::getUS(), status);
3316    UDate date = formatter->parse("1975-05-06", status);
3317    Calendar* is_cal = Calendar::createInstance(umalquraLoc, status);
3318    is_cal->setTime(date, status);
3319    int32_t is_day = is_cal->get(UCAL_DAY_OF_MONTH,status);
3320    int32_t is_month = is_cal->get(UCAL_MONTH,status);
3321    int32_t is_year = is_cal->get(UCAL_YEAR,status);
3322    TEST_CHECK_STATUS;
3323    if(is_day != 24 || is_month != IslamicCalendar::RABI_2 || is_year != 1395)
3324        errln("unexpected conversion date month %i not %i or day %i not 24 or year %i not 1395", is_month, IslamicCalendar::RABI_2, is_day, is_year);
3325
3326    UDate date2 = is_cal->getTime(status);
3327    TEST_CHECK_STATUS;
3328    if(date2 != date) {
3329        errln("before(%f) and after(%f) dates don't match up!",date, date2);
3330    }
3331
3332    // check against data
3333    const GregoUmmAlQuraMap* guMapPtr;
3334    gregCal->clear();
3335    tstCal->clear();
3336    for (guMapPtr = guMappings; guMapPtr->gYear != 0; guMapPtr++) {
3337        status = U_ZERO_ERROR;
3338        gregCal->set(guMapPtr->gYear, guMapPtr->gMon - 1, guMapPtr->gDay, 12, 0);
3339        date = gregCal->getTime(status);
3340        tstCal->setTime(date, status);
3341        int32_t uYear = tstCal->get(UCAL_YEAR, status);
3342        int32_t uMon = tstCal->get(UCAL_MONTH, status) + 1;
3343        int32_t uDay = tstCal->get(UCAL_DATE, status);
3344        if(U_FAILURE(status)) {
3345            errln("For gregorian %4d-%02d-%02d, get status %s",
3346                    guMapPtr->gYear, guMapPtr->gMon, guMapPtr->gDay, u_errorName(status) );
3347        } else if (uYear != guMapPtr->uYear || uMon != guMapPtr->uMon || uDay != guMapPtr->uDay) {
3348            errln("For gregorian %4d-%02d-%02d, expect umalqura %4d-%02d-%02d, get %4d-%02d-%02d",
3349                    guMapPtr->gYear, guMapPtr->gMon, guMapPtr->gDay,
3350                    guMapPtr->uYear, guMapPtr->uMon, guMapPtr->uDay, uYear, uMon, uDay );
3351        }
3352    }
3353
3354    delete is_cal;
3355    delete formatter;
3356    delete gregCal;
3357    delete tstCal;
3358    delete tzSA;
3359}
3360
3361void CalendarTest::TestIslamicTabularDates() {
3362    UErrorCode status = U_ZERO_ERROR;
3363    Locale islamicLoc("ar_SA@calendar=islamic-civil");
3364    Locale tblaLoc("ar_SA@calendar=islamic-tbla");
3365    SimpleDateFormat* formatter = new SimpleDateFormat("yyyy-MM-dd", Locale::getUS(), status);
3366    UDate date = formatter->parse("1975-05-06", status);
3367
3368    Calendar* tstCal = Calendar::createInstance(islamicLoc, status);
3369    tstCal->setTime(date, status);
3370    int32_t is_day = tstCal->get(UCAL_DAY_OF_MONTH,status);
3371    int32_t is_month = tstCal->get(UCAL_MONTH,status);
3372    int32_t is_year = tstCal->get(UCAL_YEAR,status);
3373    TEST_CHECK_STATUS;
3374    delete tstCal;
3375
3376    tstCal = Calendar::createInstance(tblaLoc, status);
3377    tstCal->setTime(date, status);
3378    int32_t tbla_day = tstCal->get(UCAL_DAY_OF_MONTH,status);
3379    int32_t tbla_month = tstCal->get(UCAL_MONTH,status);
3380    int32_t tbla_year = tstCal->get(UCAL_YEAR,status);
3381    TEST_CHECK_STATUS;
3382
3383    if(tbla_month != is_month || tbla_year != is_year)
3384        errln("unexpected difference between islamic and tbla month %d : %d and/or year %d : %d",tbla_month,is_month,tbla_year,is_year);
3385
3386    if(tbla_day - is_day != 1)
3387        errln("unexpected day difference between islamic and tbla: %d : %d ",tbla_day,is_day);
3388    delete tstCal;
3389    delete formatter;
3390}
3391
3392void CalendarTest::TestHebrewMonthValidation() {
3393    UErrorCode status = U_ZERO_ERROR;
3394    LocalPointer<Calendar>  cal(Calendar::createInstance(Locale::createFromName("he_IL@calendar=hebrew"), status));
3395    if (failure(status, "Calendar::createInstance, locale:he_IL@calendar=hebrew", TRUE)) return;
3396    Calendar *pCal = cal.getAlias();
3397
3398    UDate d;
3399    pCal->setLenient(FALSE);
3400
3401    // 5776 is a leap year and has month Adar I
3402    pCal->set(5776, HebrewCalendar::ADAR_1, 1);
3403    d = pCal->getTime(status);
3404    if (U_FAILURE(status)) {
3405        errln("Fail: 5776 Adar I 1 is a valid date.");
3406    }
3407    status = U_ZERO_ERROR;
3408
3409    // 5777 is NOT a lear year and does not have month Adar I
3410    pCal->set(5777, HebrewCalendar::ADAR_1, 1);
3411    d = pCal->getTime(status);
3412    (void)d;
3413    if (status == U_ILLEGAL_ARGUMENT_ERROR) {
3414        logln("Info: U_ILLEGAL_ARGUMENT_ERROR, because 5777 Adar I 1 is not a valid date.");
3415    } else {
3416        errln("Fail: U_ILLEGAL_ARGUMENT_ERROR should be set for input date 5777 Adar I 1.");
3417    }
3418}
3419
3420void CalendarTest::TestWeekData() {
3421    // Each line contains two locales using the same set of week rule data.
3422    const char* LOCALE_PAIRS[] = {
3423        "en",       "en_US",
3424        "de",       "de_DE",
3425        "de_DE",    "en_DE",
3426        "en_GB",    "und_GB",
3427        "ar_EG",    "en_EG",
3428        "ar_SA",    "fr_SA",
3429        0
3430    };
3431
3432    UErrorCode status;
3433
3434    for (int32_t i = 0; LOCALE_PAIRS[i] != 0; i += 2) {
3435        status = U_ZERO_ERROR;
3436        LocalPointer<Calendar>  cal1(Calendar::createInstance(LOCALE_PAIRS[i], status));
3437        LocalPointer<Calendar>  cal2(Calendar::createInstance(LOCALE_PAIRS[i + 1], status));
3438        TEST_CHECK_STATUS_LOCALE(LOCALE_PAIRS[i]);
3439
3440        // First day of week
3441        UCalendarDaysOfWeek dow1 = cal1->getFirstDayOfWeek(status);
3442        UCalendarDaysOfWeek dow2 = cal2->getFirstDayOfWeek(status);
3443        TEST_CHECK_STATUS;
3444        TEST_ASSERT(dow1 == dow2);
3445
3446        // Minimum days in first week
3447        uint8_t minDays1 = cal1->getMinimalDaysInFirstWeek();
3448        uint8_t minDays2 = cal2->getMinimalDaysInFirstWeek();
3449        TEST_ASSERT(minDays1 == minDays2);
3450
3451        // Weekdays and Weekends
3452        for (int32_t d = UCAL_SUNDAY; d <= UCAL_SATURDAY; d++) {
3453            status = U_ZERO_ERROR;
3454            UCalendarWeekdayType wdt1 = cal1->getDayOfWeekType((UCalendarDaysOfWeek)d, status);
3455            UCalendarWeekdayType wdt2 = cal2->getDayOfWeekType((UCalendarDaysOfWeek)d, status);
3456            TEST_CHECK_STATUS;
3457            TEST_ASSERT(wdt1 == wdt2);
3458        }
3459    }
3460}
3461
3462typedef struct {
3463    const char* zone;
3464    const CalFields base;
3465    int32_t deltaDays;
3466    UCalendarWallTimeOption skippedWTOpt;
3467    const CalFields expected;
3468} TestAddAcrossZoneTransitionData;
3469
3470static const TestAddAcrossZoneTransitionData AAZTDATA[] =
3471{
3472    // Time zone                Base wall time                      day(s)  Skipped time options
3473    //                          Expected wall time
3474
3475    // Add 1 day, from the date before DST transition
3476    {"America/Los_Angeles",     CalFields(2014,3,8,1,59,59,999),    1,      UCAL_WALLTIME_FIRST,
3477                                CalFields(2014,3,9,1,59,59,999)},
3478
3479    {"America/Los_Angeles",     CalFields(2014,3,8,1,59,59,999),    1,      UCAL_WALLTIME_LAST,
3480                                CalFields(2014,3,9,1,59,59,999)},
3481
3482    {"America/Los_Angeles",     CalFields(2014,3,8,1,59,59,999),    1,      UCAL_WALLTIME_NEXT_VALID,
3483                                CalFields(2014,3,9,1,59,59,999)},
3484
3485
3486    {"America/Los_Angeles",     CalFields(2014,3,8,2,0,0,0),        1,      UCAL_WALLTIME_FIRST,
3487                                CalFields(2014,3,9,1,0,0,0)},
3488
3489    {"America/Los_Angeles",     CalFields(2014,3,8,2,0,0,0),        1,      UCAL_WALLTIME_LAST,
3490                                CalFields(2014,3,9,3,0,0,0)},
3491
3492    {"America/Los_Angeles",     CalFields(2014,3,8,2,0,0,0),        1,      UCAL_WALLTIME_NEXT_VALID,
3493                                CalFields(2014,3,9,3,0,0,0)},
3494
3495
3496    {"America/Los_Angeles",     CalFields(2014,3,8,2,30,0,0),       1,      UCAL_WALLTIME_FIRST,
3497                                CalFields(2014,3,9,1,30,0,0)},
3498
3499    {"America/Los_Angeles",     CalFields(2014,3,8,2,30,0,0),       1,      UCAL_WALLTIME_LAST,
3500                                CalFields(2014,3,9,3,30,0,0)},
3501
3502    {"America/Los_Angeles",     CalFields(2014,3,8,2,30,0,0),       1,      UCAL_WALLTIME_NEXT_VALID,
3503                                CalFields(2014,3,9,3,0,0,0)},
3504
3505
3506    {"America/Los_Angeles",     CalFields(2014,3,8,3,0,0,0),        1,      UCAL_WALLTIME_FIRST,
3507                                CalFields(2014,3,9,3,0,0,0)},
3508
3509    {"America/Los_Angeles",     CalFields(2014,3,8,3,0,0,0),        1,      UCAL_WALLTIME_LAST,
3510                                CalFields(2014,3,9,3,0,0,0)},
3511
3512    {"America/Los_Angeles",     CalFields(2014,3,8,3,0,0,0),        1,      UCAL_WALLTIME_NEXT_VALID,
3513                                CalFields(2014,3,9,3,0,0,0)},
3514
3515    // Subtract 1 day, from one day after DST transition
3516    {"America/Los_Angeles",     CalFields(2014,3,10,1,59,59,999),   -1,     UCAL_WALLTIME_FIRST,
3517                                CalFields(2014,3,9,1,59,59,999)},
3518
3519    {"America/Los_Angeles",     CalFields(2014,3,10,1,59,59,999),   -1,     UCAL_WALLTIME_LAST,
3520                                CalFields(2014,3,9,1,59,59,999)},
3521
3522    {"America/Los_Angeles",     CalFields(2014,3,10,1,59,59,999),   -1,     UCAL_WALLTIME_NEXT_VALID,
3523                                CalFields(2014,3,9,1,59,59,999)},
3524
3525
3526    {"America/Los_Angeles",     CalFields(2014,3,10,2,0,0,0),       -1,     UCAL_WALLTIME_FIRST,
3527                                CalFields(2014,3,9,1,0,0,0)},
3528
3529    {"America/Los_Angeles",     CalFields(2014,3,10,2,0,0,0),       -1,     UCAL_WALLTIME_LAST,
3530                                CalFields(2014,3,9,3,0,0,0)},
3531
3532    {"America/Los_Angeles",     CalFields(2014,3,10,2,0,0,0),       -1,     UCAL_WALLTIME_NEXT_VALID,
3533                                CalFields(2014,3,9,3,0,0,0)},
3534
3535
3536    {"America/Los_Angeles",     CalFields(2014,3,10,2,30,0,0),      -1,     UCAL_WALLTIME_FIRST,
3537                                CalFields(2014,3,9,1,30,0,0)},
3538
3539    {"America/Los_Angeles",     CalFields(2014,3,10,2,30,0,0),      -1,     UCAL_WALLTIME_LAST,
3540                                CalFields(2014,3,9,3,30,0,0)},
3541
3542    {"America/Los_Angeles",     CalFields(2014,3,10,2,30,0,0),      -1,     UCAL_WALLTIME_NEXT_VALID,
3543                                CalFields(2014,3,9,3,0,0,0)},
3544
3545
3546    {"America/Los_Angeles",     CalFields(2014,3,10,3,0,0,0),       -1,     UCAL_WALLTIME_FIRST,
3547                                CalFields(2014,3,9,3,0,0,0)},
3548
3549    {"America/Los_Angeles",     CalFields(2014,3,10,3,0,0,0),       -1,     UCAL_WALLTIME_LAST,
3550                                CalFields(2014,3,9,3,0,0,0)},
3551
3552    {"America/Los_Angeles",     CalFields(2014,3,10,3,0,0,0),       -1,     UCAL_WALLTIME_NEXT_VALID,
3553                                CalFields(2014,3,9,3,0,0,0)},
3554
3555
3556    // Test case for ticket#10544
3557    {"America/Santiago",        CalFields(2013,4,27,0,0,0,0),       134,    UCAL_WALLTIME_FIRST,
3558                                CalFields(2013,9,7,23,0,0,0)},
3559
3560    {"America/Santiago",        CalFields(2013,4,27,0,0,0,0),       134,    UCAL_WALLTIME_LAST,
3561                                CalFields(2013,9,8,1,0,0,0)},
3562
3563    {"America/Santiago",        CalFields(2013,4,27,0,0,0,0),       134,    UCAL_WALLTIME_NEXT_VALID,
3564                                CalFields(2013,9,8,1,0,0,0)},
3565
3566
3567    {"America/Santiago",        CalFields(2013,4,27,0,30,0,0),      134,    UCAL_WALLTIME_FIRST,
3568                                CalFields(2013,9,7,23,30,0,0)},
3569
3570    {"America/Santiago",        CalFields(2013,4,27,0,30,0,0),      134,    UCAL_WALLTIME_LAST,
3571                                CalFields(2013,9,8,1,30,0,0)},
3572
3573    {"America/Santiago",        CalFields(2013,4,27,0,30,0,0),      134,    UCAL_WALLTIME_NEXT_VALID,
3574                                CalFields(2013,9,8,1,0,0,0)},
3575
3576
3577    // Extreme transition - Pacific/Apia completely skips 2011-12-30
3578    {"Pacific/Apia",            CalFields(2011,12,29,0,0,0,0),      1,      UCAL_WALLTIME_FIRST,
3579                                CalFields(2011,12,31,0,0,0,0)},
3580
3581    {"Pacific/Apia",            CalFields(2011,12,29,0,0,0,0),      1,      UCAL_WALLTIME_LAST,
3582                                CalFields(2011,12,31,0,0,0,0)},
3583
3584    {"Pacific/Apia",            CalFields(2011,12,29,0,0,0,0),      1,      UCAL_WALLTIME_NEXT_VALID,
3585                                CalFields(2011,12,31,0,0,0,0)},
3586
3587
3588    {"Pacific/Apia",            CalFields(2011,12,31,12,0,0,0),     -1,     UCAL_WALLTIME_FIRST,
3589                                CalFields(2011,12,29,12,0,0,0)},
3590
3591    {"Pacific/Apia",            CalFields(2011,12,31,12,0,0,0),     -1,     UCAL_WALLTIME_LAST,
3592                                CalFields(2011,12,29,12,0,0,0)},
3593
3594    {"Pacific/Apia",            CalFields(2011,12,31,12,0,0,0),     -1,     UCAL_WALLTIME_NEXT_VALID,
3595                                CalFields(2011,12,29,12,0,0,0)},
3596
3597
3598    // 30 minutes DST - Australia/Lord_Howe
3599    {"Australia/Lord_Howe",     CalFields(2013,10,5,2,15,0,0),      1,      UCAL_WALLTIME_FIRST,
3600                                CalFields(2013,10,6,1,45,0,0)},
3601
3602    {"Australia/Lord_Howe",     CalFields(2013,10,5,2,15,0,0),      1,      UCAL_WALLTIME_LAST,
3603                                CalFields(2013,10,6,2,45,0,0)},
3604
3605    {"Australia/Lord_Howe",     CalFields(2013,10,5,2,15,0,0),      1,      UCAL_WALLTIME_NEXT_VALID,
3606                                CalFields(2013,10,6,2,30,0,0)},
3607
3608    {NULL, CalFields(0,0,0,0,0,0,0), 0, UCAL_WALLTIME_LAST, CalFields(0,0,0,0,0,0,0)}
3609};
3610
3611void CalendarTest::TestAddAcrossZoneTransition() {
3612    UErrorCode status = U_ZERO_ERROR;
3613    GregorianCalendar cal(status);
3614    TEST_CHECK_STATUS;
3615
3616    for (int32_t i = 0; AAZTDATA[i].zone; i++) {
3617        status = U_ZERO_ERROR;
3618        TimeZone *tz = TimeZone::createTimeZone(AAZTDATA[i].zone);
3619        cal.adoptTimeZone(tz);
3620        cal.setSkippedWallTimeOption(AAZTDATA[i].skippedWTOpt);
3621        AAZTDATA[i].base.setTo(cal);
3622        cal.add(UCAL_DATE, AAZTDATA[i].deltaDays, status);
3623        TEST_CHECK_STATUS;
3624
3625        if (!AAZTDATA[i].expected.isEquivalentTo(cal, status)) {
3626            CalFields res(cal, status);
3627            TEST_CHECK_STATUS;
3628            char buf[32];
3629            const char *optDisp = AAZTDATA[i].skippedWTOpt == UCAL_WALLTIME_FIRST ? "FIRST" :
3630                    AAZTDATA[i].skippedWTOpt == UCAL_WALLTIME_LAST ? "LAST" : "NEXT_VALID";
3631            dataerrln(UnicodeString("Error: base:") + AAZTDATA[i].base.toString(buf, sizeof(buf)) + ", tz:" + AAZTDATA[i].zone
3632                        + ", delta:" + AAZTDATA[i].deltaDays + " day(s), opt:" + optDisp
3633                        + ", result:" + res.toString(buf, sizeof(buf))
3634                        + " - expected:" + AAZTDATA[i].expected.toString(buf, sizeof(buf)));
3635        }
3636    }
3637}
3638
3639// Data in a separate file (Gregorian to Chinese lunar map)
3640#define INCLUDED_FROM_CALTEST_CPP
3641#include "caltestdata.h"
3642
3643void CalendarTest::TestChineseCalendarMapping() {
3644    UErrorCode status = U_ZERO_ERROR;
3645    LocalPointer<TimeZone> zone(TimeZone::createTimeZone(UnicodeString("China")));
3646    Locale locEnCalGregory = Locale::createFromName("en@calendar=gregorian");
3647    Locale locEnCalChinese = Locale::createFromName("en@calendar=chinese");
3648    LocalPointer<Calendar>  calGregory(Calendar::createInstance(zone->clone(), locEnCalGregory, status));
3649    LocalPointer<Calendar>  calChinese(Calendar::createInstance(zone.orphan(), locEnCalChinese, status));
3650    if ( U_FAILURE(status) ) {
3651        errln("Fail: Calendar::createInstance fails for en with calendar=gregorian or calendar=chinese: %s", u_errorName(status));
3652    } else {
3653        const GregoToLunar * mapPtr = gregoToLunar; // in "caltestdata.h" included above
3654        calGregory->clear();
3655        calChinese->clear();
3656        for (; mapPtr->gyr != 0; mapPtr++) {
3657            status = U_ZERO_ERROR;
3658            calGregory->set(mapPtr->gyr, mapPtr->gmo - 1, mapPtr->gda, 8, 0);
3659            UDate date = calGregory->getTime(status);
3660            calChinese->setTime(date, status);
3661            if ( U_FAILURE(status) ) {
3662                errln("Fail: for Gregorian %4d-%02d-%02d, calGregory->getTime or calChinese->setTime reports: %s",
3663                        mapPtr->gyr, mapPtr->gmo, mapPtr->gda, u_errorName(status));
3664                continue;
3665            }
3666            int32_t era = calChinese->get(UCAL_ERA, status);
3667            int32_t yr  = calChinese->get(UCAL_YEAR, status);
3668            int32_t mo  = calChinese->get(UCAL_MONTH, status) + 1;
3669            int32_t lp  = calChinese->get(UCAL_IS_LEAP_MONTH, status);
3670            int32_t da  = calChinese->get(UCAL_DATE, status);
3671            if ( U_FAILURE(status) ) {
3672                errln("Fail: for Gregorian %4d-%02d-%02d, calChinese->get (for era, yr, mo, leapmo, da) reports: %s",
3673                        mapPtr->gyr, mapPtr->gmo, mapPtr->gda, u_errorName(status));
3674                continue;
3675            }
3676            if (yr != mapPtr->cyr || mo != mapPtr->cmo || lp != mapPtr->clp || da != mapPtr->cda) {
3677                errln("Fail: for Gregorian %4d-%02d-%02d, expected Chinese %2d-%02d(%d)-%02d, got %2d-%02d(%d)-%02d",
3678                        mapPtr->gyr, mapPtr->gmo, mapPtr->gda, mapPtr->cyr, mapPtr->cmo, mapPtr->clp, mapPtr->cda, yr, mo, lp, da);
3679                continue;
3680            }
3681            // If Grego->Chinese worked, try reverse mapping
3682            calChinese->set(UCAL_ERA, era);
3683            calChinese->set(UCAL_YEAR, mapPtr->cyr);
3684            calChinese->set(UCAL_MONTH, mapPtr->cmo - 1);
3685            calChinese->set(UCAL_IS_LEAP_MONTH, mapPtr->clp);
3686            calChinese->set(UCAL_DATE, mapPtr->cda);
3687            calChinese->set(UCAL_HOUR_OF_DAY, 8);
3688            date = calChinese->getTime(status);
3689            calGregory->setTime(date, status);
3690            if ( U_FAILURE(status) ) {
3691                errln("Fail: for Chinese %2d-%02d(%d)-%02d, calChinese->getTime or calGregory->setTime reports: %s",
3692                        mapPtr->cyr, mapPtr->cmo, mapPtr->clp, mapPtr->cda, u_errorName(status));
3693                continue;
3694            }
3695            yr  = calGregory->get(UCAL_YEAR, status);
3696            mo  = calGregory->get(UCAL_MONTH, status) + 1;
3697            da  = calGregory->get(UCAL_DATE, status);
3698            if ( U_FAILURE(status) ) {
3699                errln("Fail: for Chinese %2d-%02d(%d)-%02d, calGregory->get (for yr, mo, da) reports: %s",
3700                        mapPtr->cyr, mapPtr->cmo, mapPtr->clp, mapPtr->cda, u_errorName(status));
3701                continue;
3702            }
3703            if (yr != mapPtr->gyr || mo != mapPtr->gmo || da != mapPtr->gda) {
3704                errln("Fail: for Chinese %2d-%02d(%d)-%02d, Gregorian %4d-%02d-%02d, got %4d-%02d-%02d",
3705                        mapPtr->cyr, mapPtr->cmo, mapPtr->clp, mapPtr->cda, mapPtr->gyr, mapPtr->gmo, mapPtr->gda, yr, mo, da);
3706                continue;
3707            }
3708        }
3709    }
3710}
3711
3712#endif /* #if !UCONFIG_NO_FORMATTING */
3713
3714//eof
3715