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