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