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