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