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