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