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