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