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