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