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