1 /************************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2010, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 ************************************************************************/
6
7 #include "unicode/utypes.h"
8
9 #if !UCONFIG_NO_FORMATTING
10
11 #include "caltest.h"
12 #include "unicode/dtfmtsym.h"
13 #include "unicode/gregocal.h"
14 #include "hebrwcal.h"
15 #include "unicode/smpdtfmt.h"
16 #include "unicode/simpletz.h"
17 #include "dbgutil.h"
18 #include "unicode/udat.h"
19 #include "unicode/ustring.h"
20
21 #define mkcstr(U) u_austrcpy(calloc(8, u_strlen(U) + 1), U)
22
23 // *****************************************************************************
24 // class CalendarTest
25 // *****************************************************************************
26
calToStr(const Calendar & cal)27 UnicodeString CalendarTest::calToStr(const Calendar & cal)
28 {
29 UnicodeString out;
30 UErrorCode status = U_ZERO_ERROR;
31 int i;
32 UDate d;
33 for(i = 0;i<UCAL_FIELD_COUNT;i++) {
34 out += (UnicodeString("") + fieldName((UCalendarDateFields)i) + "=" + cal.get((UCalendarDateFields)i, status) + UnicodeString(" "));
35 }
36 out += "[" + UnicodeString(cal.getType()) + "]";
37
38 if(cal.inDaylightTime(status)) {
39 out += UnicodeString(" (in DST), zone=");
40 }
41 else {
42 out += UnicodeString(", zone=");
43 }
44
45 UnicodeString str2;
46 out += cal.getTimeZone().getDisplayName(str2);
47 d = cal.getTime(status);
48 out += UnicodeString(" :","") + d;
49
50 return out;
51 }
52
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)53 void CalendarTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
54 {
55 if (exec) logln("TestSuite TestCalendar");
56 switch (index) {
57 case 0:
58 name = "TestDOW943";
59 if (exec) {
60 logln("TestDOW943---"); logln("");
61 TestDOW943();
62 }
63 break;
64 case 1:
65 name = "TestClonesUnique908";
66 if (exec) {
67 logln("TestClonesUnique908---"); logln("");
68 TestClonesUnique908();
69 }
70 break;
71 case 2:
72 name = "TestGregorianChange768";
73 if (exec) {
74 logln("TestGregorianChange768---"); logln("");
75 TestGregorianChange768();
76 }
77 break;
78 case 3:
79 name = "TestDisambiguation765";
80 if (exec) {
81 logln("TestDisambiguation765---"); logln("");
82 TestDisambiguation765();
83 }
84 break;
85 case 4:
86 name = "TestGMTvsLocal4064654";
87 if (exec) {
88 logln("TestGMTvsLocal4064654---"); logln("");
89 TestGMTvsLocal4064654();
90 }
91 break;
92 case 5:
93 name = "TestAddSetOrder621";
94 if (exec) {
95 logln("TestAddSetOrder621---"); logln("");
96 TestAddSetOrder621();
97 }
98 break;
99 case 6:
100 name = "TestAdd520";
101 if (exec) {
102 logln("TestAdd520---"); logln("");
103 TestAdd520();
104 }
105 break;
106 case 7:
107 name = "TestFieldSet4781";
108 if (exec) {
109 logln("TestFieldSet4781---"); logln("");
110 TestFieldSet4781();
111 }
112 break;
113 case 8:
114 name = "TestSerialize337";
115 if (exec) {
116 logln("TestSerialize337---"); logln("");
117 // TestSerialize337();
118 }
119 break;
120 case 9:
121 name = "TestSecondsZero121";
122 if (exec) {
123 logln("TestSecondsZero121---"); logln("");
124 TestSecondsZero121();
125 }
126 break;
127 case 10:
128 name = "TestAddSetGet0610";
129 if (exec) {
130 logln("TestAddSetGet0610---"); logln("");
131 TestAddSetGet0610();
132 }
133 break;
134 case 11:
135 name = "TestFields060";
136 if (exec) {
137 logln("TestFields060---"); logln("");
138 TestFields060();
139 }
140 break;
141 case 12:
142 name = "TestEpochStartFields";
143 if (exec) {
144 logln("TestEpochStartFields---"); logln("");
145 TestEpochStartFields();
146 }
147 break;
148 case 13:
149 name = "TestDOWProgression";
150 if (exec) {
151 logln("TestDOWProgression---"); logln("");
152 TestDOWProgression();
153 }
154 break;
155 case 14:
156 name = "TestGenericAPI";
157 if (exec) {
158 logln("TestGenericAPI---"); logln("");
159 TestGenericAPI();
160 }
161 break;
162 case 15:
163 name = "TestAddRollExtensive";
164 if (exec) {
165 logln("TestAddRollExtensive---"); logln("");
166 TestAddRollExtensive();
167 }
168 break;
169 case 16:
170 name = "TestDOW_LOCALandYEAR_WOY";
171 if (exec) {
172 logln("TestDOW_LOCALandYEAR_WOY---"); logln("");
173 TestDOW_LOCALandYEAR_WOY();
174 }
175 break;
176 case 17:
177 name = "TestWOY";
178 if (exec) {
179 logln("TestWOY---"); logln("");
180 TestWOY();
181 }
182 break;
183 case 18:
184 name = "TestRog";
185 if (exec) {
186 logln("TestRog---"); logln("");
187 TestRog();
188 }
189 break;
190 case 19:
191 name = "TestYWOY";
192 if (exec) {
193 logln("TestYWOY---"); logln("");
194 TestYWOY();
195 }
196 break;
197 case 20:
198 name = "TestJD";
199 if(exec) {
200 logln("TestJD---"); logln("");
201 TestJD();
202 }
203 break;
204 case 21:
205 name = "TestDebug";
206 if(exec) {
207 logln("TestDebug---"); logln("");
208 TestDebug();
209 }
210 break;
211 case 22:
212 name = "Test6703";
213 if(exec) {
214 logln("Test6703---"); logln("");
215 Test6703();
216 }
217 break;
218 case 23:
219 name = "Test3785";
220 if(exec) {
221 logln("Test3785---"); logln("");
222 Test3785();
223 }
224 break;
225 case 24:
226 name = "Test1624";
227 if(exec) {
228 logln("Test1624---"); logln("");
229 Test1624();
230 }
231 break;
232 default: name = ""; break;
233 }
234 }
235
236 // ---------------------------------------------------------------------------------
237
fieldName(UCalendarDateFields f)238 UnicodeString CalendarTest::fieldName(UCalendarDateFields f) {
239 switch (f) {
240 #define FIELD_NAME_STR(x) case x: return (#x+5)
241 FIELD_NAME_STR( UCAL_ERA );
242 FIELD_NAME_STR( UCAL_YEAR );
243 FIELD_NAME_STR( UCAL_MONTH );
244 FIELD_NAME_STR( UCAL_WEEK_OF_YEAR );
245 FIELD_NAME_STR( UCAL_WEEK_OF_MONTH );
246 FIELD_NAME_STR( UCAL_DATE );
247 FIELD_NAME_STR( UCAL_DAY_OF_YEAR );
248 FIELD_NAME_STR( UCAL_DAY_OF_WEEK );
249 FIELD_NAME_STR( UCAL_DAY_OF_WEEK_IN_MONTH );
250 FIELD_NAME_STR( UCAL_AM_PM );
251 FIELD_NAME_STR( UCAL_HOUR );
252 FIELD_NAME_STR( UCAL_HOUR_OF_DAY );
253 FIELD_NAME_STR( UCAL_MINUTE );
254 FIELD_NAME_STR( UCAL_SECOND );
255 FIELD_NAME_STR( UCAL_MILLISECOND );
256 FIELD_NAME_STR( UCAL_ZONE_OFFSET );
257 FIELD_NAME_STR( UCAL_DST_OFFSET );
258 FIELD_NAME_STR( UCAL_YEAR_WOY );
259 FIELD_NAME_STR( UCAL_DOW_LOCAL );
260 FIELD_NAME_STR( UCAL_EXTENDED_YEAR );
261 FIELD_NAME_STR( UCAL_JULIAN_DAY );
262 FIELD_NAME_STR( UCAL_MILLISECONDS_IN_DAY );
263 #undef FIELD_NAME_STR
264 default:
265 return UnicodeString("") + ((int32_t)f);
266 }
267 }
268
269 /**
270 * Test various API methods for API completeness.
271 */
272 void
TestGenericAPI()273 CalendarTest::TestGenericAPI()
274 {
275 UErrorCode status = U_ZERO_ERROR;
276 UDate d;
277 UnicodeString str;
278 UBool eq = FALSE,b4 = FALSE,af = FALSE;
279
280 UDate when = date(90, UCAL_APRIL, 15);
281
282 UnicodeString tzid("TestZone");
283 int32_t tzoffset = 123400;
284
285 SimpleTimeZone *zone = new SimpleTimeZone(tzoffset, tzid);
286 Calendar *cal = Calendar::createInstance(zone->clone(), status);
287 if (failure(status, "Calendar::createInstance", TRUE)) return;
288
289 if (*zone != cal->getTimeZone()) errln("FAIL: Calendar::getTimeZone failed");
290
291 Calendar *cal2 = Calendar::createInstance(cal->getTimeZone(), status);
292 if (failure(status, "Calendar::createInstance")) return;
293 cal->setTime(when, status);
294 cal2->setTime(when, status);
295 if (failure(status, "Calendar::setTime")) return;
296
297 if (!(*cal == *cal2)) errln("FAIL: Calendar::operator== failed");
298 if ((*cal != *cal2)) errln("FAIL: Calendar::operator!= failed");
299 if (!cal->equals(*cal2, status) ||
300 cal->before(*cal2, status) ||
301 cal->after(*cal2, status) ||
302 U_FAILURE(status)) errln("FAIL: equals/before/after failed");
303
304 logln(UnicodeString("cal=") +cal->getTime(status) + UnicodeString(calToStr(*cal)));
305 logln(UnicodeString("cal2=") +cal2->getTime(status) + UnicodeString(calToStr(*cal2)));
306 logln("cal2->setTime(when+1000)");
307 cal2->setTime(when + 1000, status);
308 logln(UnicodeString("cal2=") +cal2->getTime(status) + UnicodeString(calToStr(*cal2)));
309
310 if (failure(status, "Calendar::setTime")) return;
311 if (cal->equals(*cal2, status) ||
312 cal2->before(*cal, status) ||
313 cal->after(*cal2, status) ||
314 U_FAILURE(status)) errln("FAIL: equals/before/after failed after setTime(+1000)");
315
316 logln("cal->roll(UCAL_SECOND)");
317 cal->roll(UCAL_SECOND, (UBool) TRUE, status);
318 logln(UnicodeString("cal=") +cal->getTime(status) + UnicodeString(calToStr(*cal)));
319 cal->roll(UCAL_SECOND, (int32_t)0, status);
320 logln(UnicodeString("cal=") +cal->getTime(status) + UnicodeString(calToStr(*cal)));
321 if (failure(status, "Calendar::roll")) return;
322
323 if (!(eq=cal->equals(*cal2, status)) ||
324 (b4=cal->before(*cal2, status)) ||
325 (af=cal->after(*cal2, status)) ||
326 U_FAILURE(status)) {
327 errln("FAIL: equals[%c]/before[%c]/after[%c] failed after roll 1 second [should be T/F/F]",
328 eq?'T':'F',
329 b4?'T':'F',
330 af?'T':'F');
331 logln(UnicodeString("cal=") +cal->getTime(status) + UnicodeString(calToStr(*cal)));
332 logln(UnicodeString("cal2=") +cal2->getTime(status) + UnicodeString(calToStr(*cal2)));
333 }
334
335 // Roll back to January
336 cal->roll(UCAL_MONTH, (int32_t)(1 + UCAL_DECEMBER - cal->get(UCAL_MONTH, status)), status);
337 if (failure(status, "Calendar::roll")) return;
338 if (cal->equals(*cal2, status) ||
339 cal2->before(*cal, status) ||
340 cal->after(*cal2, status) ||
341 U_FAILURE(status)) errln("FAIL: equals/before/after failed after rollback to January");
342
343 TimeZone *z = cal->orphanTimeZone();
344 if (z->getID(str) != tzid ||
345 z->getRawOffset() != tzoffset)
346 errln("FAIL: orphanTimeZone failed");
347
348 int32_t i;
349 for (i=0; i<2; ++i)
350 {
351 UBool lenient = ( i > 0 );
352 cal->setLenient(lenient);
353 if (lenient != cal->isLenient()) errln("FAIL: setLenient/isLenient failed");
354 // Later: Check for lenient behavior
355 }
356
357 for (i=UCAL_SUNDAY; i<=UCAL_SATURDAY; ++i)
358 {
359 cal->setFirstDayOfWeek((UCalendarDaysOfWeek)i);
360 if (cal->getFirstDayOfWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
361 UErrorCode aStatus = U_ZERO_ERROR;
362 if (cal->getFirstDayOfWeek(aStatus) != i || U_FAILURE(aStatus)) errln("FAIL: getFirstDayOfWeek(status) failed");
363 }
364
365 for (i=1; i<=7; ++i)
366 {
367 cal->setMinimalDaysInFirstWeek((uint8_t)i);
368 if (cal->getMinimalDaysInFirstWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
369 }
370
371 for (i=0; i<UCAL_FIELD_COUNT; ++i)
372 {
373 if (cal->getMinimum((UCalendarDateFields)i) > cal->getGreatestMinimum((UCalendarDateFields)i))
374 errln("FAIL: getMinimum larger than getGreatestMinimum for field " + i);
375 if (cal->getLeastMaximum((UCalendarDateFields)i) > cal->getMaximum((UCalendarDateFields)i))
376 errln("FAIL: getLeastMaximum larger than getMaximum for field " + i);
377 if (cal->getMinimum((UCalendarDateFields)i) >= cal->getMaximum((UCalendarDateFields)i))
378 errln("FAIL: getMinimum not less than getMaximum for field " + i);
379 }
380
381 cal->adoptTimeZone(TimeZone::createDefault());
382 cal->clear();
383 cal->set(1984, 5, 24);
384 if (cal->getTime(status) != date(84, 5, 24) || U_FAILURE(status))
385 errln("FAIL: Calendar::set(3 args) failed");
386
387 cal->clear();
388 cal->set(1985, 3, 2, 11, 49);
389 if (cal->getTime(status) != date(85, 3, 2, 11, 49) || U_FAILURE(status))
390 errln("FAIL: Calendar::set(5 args) failed");
391
392 cal->clear();
393 cal->set(1995, 9, 12, 1, 39, 55);
394 if (cal->getTime(status) != date(95, 9, 12, 1, 39, 55) || U_FAILURE(status))
395 errln("FAIL: Calendar::set(6 args) failed");
396
397 cal->getTime(status);
398 if (failure(status, "Calendar::getTime")) return;
399 for (i=0; i<UCAL_FIELD_COUNT; ++i)
400 {
401 switch(i) {
402 case UCAL_YEAR: case UCAL_MONTH: case UCAL_DATE:
403 case UCAL_HOUR_OF_DAY: case UCAL_MINUTE: case UCAL_SECOND:
404 case UCAL_EXTENDED_YEAR:
405 if (!cal->isSet((UCalendarDateFields)i)) errln("FAIL: Calendar::isSet F, should be T " + fieldName((UCalendarDateFields)i));
406 break;
407 default:
408 if (cal->isSet((UCalendarDateFields)i)) errln("FAIL: Calendar::isSet = T, should be F " + fieldName((UCalendarDateFields)i));
409 }
410 cal->clear((UCalendarDateFields)i);
411 if (cal->isSet((UCalendarDateFields)i)) errln("FAIL: Calendar::clear/isSet failed " + fieldName((UCalendarDateFields)i));
412 }
413
414 if(cal->getActualMinimum(Calendar::SECOND, status) != 0){
415 errln("Calendar is suppose to return 0 for getActualMinimum");
416 }
417
418 Calendar *cal3 = Calendar::createInstance(status);
419 cal3->roll(Calendar::SECOND, (int32_t)0, status);
420 if (failure(status, "Calendar::roll(EDateFields, int32_t, UErrorCode)")) return;
421
422 delete cal;
423 delete cal2;
424 delete cal3;
425
426 int32_t count;
427 const Locale* loc = Calendar::getAvailableLocales(count);
428 if (count < 1 || loc == 0)
429 {
430 dataerrln("FAIL: getAvailableLocales failed");
431 }
432 else
433 {
434 for (i=0; i<count; ++i)
435 {
436 cal = Calendar::createInstance(loc[i], status);
437 if (failure(status, "Calendar::createInstance")) return;
438 delete cal;
439 }
440 }
441
442 cal = Calendar::createInstance(TimeZone::createDefault(), Locale::getEnglish(), status);
443 if (failure(status, "Calendar::createInstance")) return;
444 delete cal;
445
446 cal = Calendar::createInstance(*zone, Locale::getEnglish(), status);
447 if (failure(status, "Calendar::createInstance")) return;
448 delete cal;
449
450 GregorianCalendar *gc = new GregorianCalendar(*zone, status);
451 if (failure(status, "new GregorianCalendar")) return;
452 delete gc;
453
454 gc = new GregorianCalendar(Locale::getEnglish(), status);
455 if (failure(status, "new GregorianCalendar")) return;
456 delete gc;
457
458 gc = new GregorianCalendar(Locale::getEnglish(), status);
459 delete gc;
460
461 gc = new GregorianCalendar(*zone, Locale::getEnglish(), status);
462 if (failure(status, "new GregorianCalendar")) return;
463 delete gc;
464
465 gc = new GregorianCalendar(zone, status);
466 if (failure(status, "new GregorianCalendar")) return;
467 delete gc;
468
469 gc = new GregorianCalendar(1998, 10, 14, 21, 43, status);
470 if (gc->getTime(status) != (d =date(98, 10, 14, 21, 43) )|| U_FAILURE(status))
471 errln("FAIL: new GregorianCalendar(ymdhm) failed with " + UnicodeString(u_errorName(status)) + ", cal=" + gc->getTime(status) + UnicodeString(calToStr(*gc)) + ", d=" + d);
472 else
473 logln(UnicodeString("GOOD: cal=") +gc->getTime(status) + UnicodeString(calToStr(*gc)) + ", d=" + d);
474 delete gc;
475
476 gc = new GregorianCalendar(1998, 10, 14, 21, 43, 55, status);
477 if (gc->getTime(status) != (d=date(98, 10, 14, 21, 43, 55)) || U_FAILURE(status))
478 errln("FAIL: new GregorianCalendar(ymdhms) failed with " + UnicodeString(u_errorName(status)));
479
480 GregorianCalendar gc2(Locale::getEnglish(), status);
481 if (failure(status, "new GregorianCalendar")) return;
482 gc2 = *gc;
483 if (gc2 != *gc || !(gc2 == *gc)) errln("FAIL: GregorianCalendar assignment/operator==/operator!= failed");
484 delete gc;
485 delete z;
486
487 /* Code coverage for Calendar class. */
488 cal = Calendar::createInstance(status);
489 if (failure(status, "Calendar::createInstance")) {
490 return;
491 }else {
492 ((Calendar *)cal)->roll(UCAL_HOUR, (int32_t)100, status);
493 ((Calendar *)cal)->clear(UCAL_HOUR);
494 #if !UCONFIG_NO_SERVICE
495 URegistryKey key = cal->registerFactory(NULL, status);
496 cal->unregister(key, status);
497 #endif
498 }
499 delete cal;
500
501 status = U_ZERO_ERROR;
502 cal = Calendar::createInstance(Locale("he_IL@calendar=hebrew"), status);
503 if (failure(status, "Calendar::createInstance")) {
504 return;
505 } else {
506 cal->roll(Calendar::MONTH, (int32_t)100, status);
507 }
508
509 StringEnumeration *en = Calendar::getKeywordValuesForLocale(NULL, Locale::getDefault(),FALSE, status);
510 if (en == NULL || U_FAILURE(status)) {
511 dataerrln("FAIL: getKeywordValuesForLocale for Calendar. : %s", u_errorName(status));
512 }
513 delete en;
514 delete cal;
515 }
516
517 // -------------------------------------
518
519 /**
520 * This test confirms the correct behavior of add when incrementing
521 * through subsequent days.
522 */
523 void
TestRog()524 CalendarTest::TestRog()
525 {
526 UErrorCode status = U_ZERO_ERROR;
527 GregorianCalendar* gc = new GregorianCalendar(status);
528 if (failure(status, "new GregorianCalendar", TRUE)) return;
529 int32_t year = 1997, month = UCAL_APRIL, date = 1;
530 gc->set(year, month, date);
531 gc->set(UCAL_HOUR_OF_DAY, 23);
532 gc->set(UCAL_MINUTE, 0);
533 gc->set(UCAL_SECOND, 0);
534 gc->set(UCAL_MILLISECOND, 0);
535 for (int32_t i = 0; i < 9; i++, gc->add(UCAL_DATE, 1, status)) {
536 if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
537 if (gc->get(UCAL_YEAR, status) != year ||
538 gc->get(UCAL_MONTH, status) != month ||
539 gc->get(UCAL_DATE, status) != (date + i)) errln("FAIL: Date wrong");
540 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
541 }
542 delete gc;
543 }
544
545 // -------------------------------------
546
547 /**
548 * Test the handling of the day of the week, checking for correctness and
549 * for correct minimum and maximum values.
550 */
551 void
TestDOW943()552 CalendarTest::TestDOW943()
553 {
554 dowTest(FALSE);
555 dowTest(TRUE);
556 }
557
dowTest(UBool lenient)558 void CalendarTest::dowTest(UBool lenient)
559 {
560 UErrorCode status = U_ZERO_ERROR;
561 GregorianCalendar* cal = new GregorianCalendar(status);
562 if (failure(status, "new GregorianCalendar", TRUE)) return;
563 logln("cal - Aug 12, 1997\n");
564 cal->set(1997, UCAL_AUGUST, 12);
565 cal->getTime(status);
566 if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
567 logln((lenient?UnicodeString("LENIENT0: "):UnicodeString("nonlenient0: ")) + UnicodeString(calToStr(*cal)));
568 cal->setLenient(lenient);
569 logln("cal - Dec 1, 1996\n");
570 cal->set(1996, UCAL_DECEMBER, 1);
571 logln((lenient?UnicodeString("LENIENT: "):UnicodeString("nonlenient: ")) + UnicodeString(calToStr(*cal)));
572 int32_t dow = cal->get(UCAL_DAY_OF_WEEK, status);
573 if (U_FAILURE(status)) { errln("Calendar::get failed [%s]", u_errorName(status)); return; }
574 int32_t min = cal->getMinimum(UCAL_DAY_OF_WEEK);
575 int32_t max = cal->getMaximum(UCAL_DAY_OF_WEEK);
576 if (dow < min ||
577 dow > max) errln(UnicodeString("FAIL: Day of week ") + (int32_t)dow + " out of range");
578 if (dow != UCAL_SUNDAY) errln("FAIL: Day of week should be SUNDAY[%d] not %d", UCAL_SUNDAY, dow);
579 if (min != UCAL_SUNDAY ||
580 max != UCAL_SATURDAY) errln("FAIL: Min/max bad");
581 delete cal;
582 }
583
584 // -------------------------------------
585
586 /**
587 * Confirm that cloned Calendar objects do not inadvertently share substructures.
588 */
589 void
TestClonesUnique908()590 CalendarTest::TestClonesUnique908()
591 {
592 UErrorCode status = U_ZERO_ERROR;
593 Calendar *c = Calendar::createInstance(status);
594 if (failure(status, "Calendar::createInstance", TRUE)) return;
595 Calendar *d = (Calendar*) c->clone();
596 c->set(UCAL_MILLISECOND, 123);
597 d->set(UCAL_MILLISECOND, 456);
598 if (c->get(UCAL_MILLISECOND, status) != 123 ||
599 d->get(UCAL_MILLISECOND, status) != 456) {
600 errln("FAIL: Clones share fields");
601 }
602 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
603 delete c;
604 delete d;
605 }
606
607 // -------------------------------------
608
609 /**
610 * Confirm that the Gregorian cutoff value works as advertised.
611 */
612 void
TestGregorianChange768()613 CalendarTest::TestGregorianChange768()
614 {
615 UBool b;
616 UErrorCode status = U_ZERO_ERROR;
617 UnicodeString str;
618 GregorianCalendar* c = new GregorianCalendar(status);
619 if (failure(status, "new GregorianCalendar", TRUE)) return;
620 logln(UnicodeString("With cutoff ") + dateToString(c->getGregorianChange(), str));
621 b = c->isLeapYear(1800);
622 logln(UnicodeString(" isLeapYear(1800) = ") + (b ? "true" : "false"));
623 logln(UnicodeString(" (should be FALSE)"));
624 if (b) errln("FAIL");
625 c->setGregorianChange(date(0, 0, 1), status);
626 if (U_FAILURE(status)) { errln("GregorianCalendar::setGregorianChange failed"); return; }
627 logln(UnicodeString("With cutoff ") + dateToString(c->getGregorianChange(), str));
628 b = c->isLeapYear(1800);
629 logln(UnicodeString(" isLeapYear(1800) = ") + (b ? "true" : "false"));
630 logln(UnicodeString(" (should be TRUE)"));
631 if (!b) errln("FAIL");
632 delete c;
633 }
634
635 // -------------------------------------
636
637 /**
638 * Confirm the functioning of the field disambiguation algorithm.
639 */
640 void
TestDisambiguation765()641 CalendarTest::TestDisambiguation765()
642 {
643 UErrorCode status = U_ZERO_ERROR;
644 Calendar *c = Calendar::createInstance("en_US", status);
645 if (failure(status, "Calendar::createInstance", TRUE)) return;
646 c->setLenient(FALSE);
647 c->clear();
648 c->set(UCAL_YEAR, 1997);
649 c->set(UCAL_MONTH, UCAL_JUNE);
650 c->set(UCAL_DATE, 3);
651 verify765("1997 third day of June = ", c, 1997, UCAL_JUNE, 3);
652 c->clear();
653 c->set(UCAL_YEAR, 1997);
654 c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
655 c->set(UCAL_MONTH, UCAL_JUNE);
656 c->set(UCAL_DAY_OF_WEEK_IN_MONTH, 1);
657 verify765("1997 first Tuesday in June = ", c, 1997, UCAL_JUNE, 3);
658 c->clear();
659 c->set(UCAL_YEAR, 1997);
660 c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
661 c->set(UCAL_MONTH, UCAL_JUNE);
662 c->set(UCAL_DAY_OF_WEEK_IN_MONTH, - 1);
663 verify765("1997 last Tuesday in June = ", c, 1997, UCAL_JUNE, 24);
664
665 status = U_ZERO_ERROR;
666 c->clear();
667 c->set(UCAL_YEAR, 1997);
668 c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
669 c->set(UCAL_MONTH, UCAL_JUNE);
670 c->set(UCAL_DAY_OF_WEEK_IN_MONTH, 0);
671 c->getTime(status);
672 verify765("1997 zero-th Tuesday in June = ", status);
673
674 c->clear();
675 c->set(UCAL_YEAR, 1997);
676 c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
677 c->set(UCAL_MONTH, UCAL_JUNE);
678 c->set(UCAL_WEEK_OF_MONTH, 1);
679 verify765("1997 Tuesday in week 1 of June = ", c, 1997, UCAL_JUNE, 3);
680 c->clear();
681 c->set(UCAL_YEAR, 1997);
682 c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
683 c->set(UCAL_MONTH, UCAL_JUNE);
684 c->set(UCAL_WEEK_OF_MONTH, 5);
685 verify765("1997 Tuesday in week 5 of June = ", c, 1997, UCAL_JULY, 1);
686
687 status = U_ZERO_ERROR;
688 c->clear();
689 c->set(UCAL_YEAR, 1997);
690 c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
691 c->set(UCAL_MONTH, UCAL_JUNE);
692 c->set(UCAL_WEEK_OF_MONTH, 0);
693 c->setMinimalDaysInFirstWeek(1);
694 c->getTime(status);
695 verify765("1997 Tuesday in week 0 of June = ", status);
696
697 /* Note: The following test used to expect YEAR 1997, WOY 1 to
698 * resolve to a date in Dec 1996; that is, to behave as if
699 * YEAR_WOY were 1997. With the addition of a new explicit
700 * YEAR_WOY field, YEAR_WOY must itself be set if that is what is
701 * desired. Using YEAR in combination with WOY is ambiguous, and
702 * results in the first WOY/DOW day of the year satisfying the
703 * given fields (there may be up to two such days). In this case,
704 * it propertly resolves to Tue Dec 30 1997, which has a WOY value
705 * of 1 (for YEAR_WOY 1998) and a DOW of Tuesday, and falls in the
706 * _calendar_ year 1997, as specified. - aliu */
707 c->clear();
708 c->set(UCAL_YEAR_WOY, 1997); // aliu
709 c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
710 c->set(UCAL_WEEK_OF_YEAR, 1);
711 verify765("1997 Tuesday in week 1 of yearWOY = ", c, 1996, UCAL_DECEMBER, 31);
712 c->clear(); // - add test for YEAR
713 c->setMinimalDaysInFirstWeek(1);
714 c->set(UCAL_YEAR, 1997);
715 c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
716 c->set(UCAL_WEEK_OF_YEAR, 1);
717 verify765("1997 Tuesday in week 1 of year = ", c, 1997, UCAL_DECEMBER, 30);
718 c->clear();
719 c->set(UCAL_YEAR, 1997);
720 c->set(UCAL_DAY_OF_WEEK, UCAL_TUESDAY);
721 c->set(UCAL_WEEK_OF_YEAR, 10);
722 verify765("1997 Tuesday in week 10 of year = ", c, 1997, UCAL_MARCH, 4);
723 //try {
724
725 // {sfb} week 0 is no longer a valid week of year
726 /*c->clear();
727 c->set(Calendar::YEAR, 1997);
728 c->set(Calendar::DAY_OF_WEEK, Calendar::TUESDAY);
729 //c->set(Calendar::WEEK_OF_YEAR, 0);
730 c->set(Calendar::WEEK_OF_YEAR, 1);
731 verify765("1997 Tuesday in week 0 of year = ", c, 1996, Calendar::DECEMBER, 24);*/
732
733 //}
734 //catch(IllegalArgumentException ex) {
735 // errln("FAIL: Exception seen:");
736 // ex.printStackTrace(log);
737 //}
738 delete c;
739 }
740
741 // -------------------------------------
742
743 void
verify765(const UnicodeString & msg,Calendar * c,int32_t year,int32_t month,int32_t day)744 CalendarTest::verify765(const UnicodeString& msg, Calendar* c, int32_t year, int32_t month, int32_t day)
745 {
746 UnicodeString str;
747 UErrorCode status = U_ZERO_ERROR;
748 int32_t y = c->get(UCAL_YEAR, status);
749 int32_t m = c->get(UCAL_MONTH, status);
750 int32_t d = c->get(UCAL_DATE, status);
751 if ( y == year &&
752 m == month &&
753 d == day) {
754 if (U_FAILURE(status)) { errln("FAIL: Calendar::get failed"); return; }
755 logln("PASS: " + msg + dateToString(c->getTime(status), str));
756 if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
757 }
758 else {
759 errln("FAIL: " + msg + dateToString(c->getTime(status), str) + "; expected " + (int32_t)year + "/" + (int32_t)(month + 1) + "/" + (int32_t)day +
760 "; got " + (int32_t)y + "/" + (int32_t)(m + 1) + "/" + (int32_t)d + " for Locale: " + c->getLocaleID(ULOC_ACTUAL_LOCALE,status));
761 if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
762 }
763 }
764
765 // -------------------------------------
766
767 void
verify765(const UnicodeString & msg,UErrorCode status)768 CalendarTest::verify765(const UnicodeString& msg/*, IllegalArgumentException e*/, UErrorCode status)
769 {
770 if (status != U_ILLEGAL_ARGUMENT_ERROR) errln("FAIL: No IllegalArgumentException for " + msg);
771 else logln("PASS: " + msg + "IllegalArgument as expected");
772 }
773
774 // -------------------------------------
775
776 /**
777 * Confirm that the offset between local time and GMT behaves as expected.
778 */
779 void
TestGMTvsLocal4064654()780 CalendarTest::TestGMTvsLocal4064654()
781 {
782 test4064654(1997, 1, 1, 12, 0, 0);
783 test4064654(1997, 4, 16, 18, 30, 0);
784 }
785
786 // -------------------------------------
787
788 void
test4064654(int32_t yr,int32_t mo,int32_t dt,int32_t hr,int32_t mn,int32_t sc)789 CalendarTest::test4064654(int32_t yr, int32_t mo, int32_t dt, int32_t hr, int32_t mn, int32_t sc)
790 {
791 UDate date;
792 UErrorCode status = U_ZERO_ERROR;
793 UnicodeString str;
794 Calendar *gmtcal = Calendar::createInstance(status);
795 if (failure(status, "Calendar::createInstance", TRUE)) return;
796 gmtcal->adoptTimeZone(TimeZone::createTimeZone("Africa/Casablanca"));
797 gmtcal->set(yr, mo - 1, dt, hr, mn, sc);
798 gmtcal->set(UCAL_MILLISECOND, 0);
799 date = gmtcal->getTime(status);
800 if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
801 logln("date = " + dateToString(date, str));
802 Calendar *cal = Calendar::createInstance(status);
803 if (U_FAILURE(status)) { errln("Calendar::createInstance failed"); return; }
804 cal->setTime(date, status);
805 if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
806 int32_t offset = cal->getTimeZone().getOffset((uint8_t)cal->get(UCAL_ERA, status),
807 cal->get(UCAL_YEAR, status),
808 cal->get(UCAL_MONTH, status),
809 cal->get(UCAL_DATE, status),
810 (uint8_t)cal->get(UCAL_DAY_OF_WEEK, status),
811 cal->get(UCAL_MILLISECOND, status), status);
812 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
813 logln("offset for " + dateToString(date, str) + "= " + (offset / 1000 / 60 / 60.0) + "hr");
814 int32_t utc = ((cal->get(UCAL_HOUR_OF_DAY, status) * 60 +
815 cal->get(UCAL_MINUTE, status)) * 60 +
816 cal->get(UCAL_SECOND, status)) * 1000 +
817 cal->get(UCAL_MILLISECOND, status) - offset;
818 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
819 int32_t expected = ((hr * 60 + mn) * 60 + sc) * 1000;
820 if (utc != expected) errln(UnicodeString("FAIL: Discrepancy of ") + (utc - expected) +
821 " millis = " + ((utc - expected) / 1000 / 60 / 60.0) + " hr");
822 delete gmtcal;
823 delete cal;
824 }
825
826 // -------------------------------------
827
828 /**
829 * The operations of adding and setting should not exhibit pathological
830 * dependence on the order of operations. This test checks for this.
831 */
832 void
TestAddSetOrder621()833 CalendarTest::TestAddSetOrder621()
834 {
835 UDate d = date(97, 4, 14, 13, 23, 45);
836 UErrorCode status = U_ZERO_ERROR;
837 Calendar *cal = Calendar::createInstance(status);
838 if (failure(status, "Calendar::createInstance", TRUE)) return;
839
840 cal->setTime(d, status);
841 if (U_FAILURE(status)) {
842 errln("Calendar::setTime failed");
843 delete cal;
844 return;
845 }
846 cal->add(UCAL_DATE, - 5, status);
847 if (U_FAILURE(status)) {
848 errln("Calendar::add failed");
849 delete cal;
850 return;
851 }
852 cal->set(UCAL_HOUR_OF_DAY, 0);
853 cal->set(UCAL_MINUTE, 0);
854 cal->set(UCAL_SECOND, 0);
855 UnicodeString s;
856 dateToString(cal->getTime(status), s);
857 if (U_FAILURE(status)) {
858 errln("Calendar::getTime failed");
859 delete cal;
860 return;
861 }
862 delete cal;
863
864 cal = Calendar::createInstance(status);
865 if (U_FAILURE(status)) {
866 errln("Calendar::createInstance failed");
867 delete cal;
868 return;
869 }
870 cal->setTime(d, status);
871 if (U_FAILURE(status)) {
872 errln("Calendar::setTime failed");
873 delete cal;
874 return;
875 }
876 cal->set(UCAL_HOUR_OF_DAY, 0);
877 cal->set(UCAL_MINUTE, 0);
878 cal->set(UCAL_SECOND, 0);
879 cal->add(UCAL_DATE, - 5, status);
880 if (U_FAILURE(status)) {
881 errln("Calendar::add failed");
882 delete cal;
883 return;
884 }
885 UnicodeString s2;
886 dateToString(cal->getTime(status), s2);
887 if (U_FAILURE(status)) {
888 errln("Calendar::getTime failed");
889 delete cal;
890 return;
891 }
892 if (s == s2)
893 logln("Pass: " + s + " == " + s2);
894 else
895 errln("FAIL: " + s + " != " + s2);
896 delete cal;
897 }
898
899 // -------------------------------------
900
901 /**
902 * Confirm that adding to various fields works.
903 */
904 void
TestAdd520()905 CalendarTest::TestAdd520()
906 {
907 int32_t y = 1997, m = UCAL_FEBRUARY, d = 1;
908 UErrorCode status = U_ZERO_ERROR;
909 GregorianCalendar *temp = new GregorianCalendar(y, m, d, status);
910 if (failure(status, "new GregorianCalendar", TRUE)) return;
911 check520(temp, y, m, d);
912 temp->add(UCAL_YEAR, 1, status);
913 if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
914 y++;
915 check520(temp, y, m, d);
916 temp->add(UCAL_MONTH, 1, status);
917 if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
918 m++;
919 check520(temp, y, m, d);
920 temp->add(UCAL_DATE, 1, status);
921 if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
922 d++;
923 check520(temp, y, m, d);
924 temp->add(UCAL_DATE, 2, status);
925 if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
926 d += 2;
927 check520(temp, y, m, d);
928 temp->add(UCAL_DATE, 28, status);
929 if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
930 d = 1;++m;
931 check520(temp, y, m, d);
932 delete temp;
933 }
934
935 // -------------------------------------
936
937 /**
938 * Execute adding and rolling in GregorianCalendar extensively,
939 */
940 void
TestAddRollExtensive()941 CalendarTest::TestAddRollExtensive()
942 {
943 int32_t maxlimit = 40;
944 int32_t y = 1997, m = UCAL_FEBRUARY, d = 1, hr = 1, min = 1, sec = 0, ms = 0;
945 UErrorCode status = U_ZERO_ERROR;
946 GregorianCalendar *temp = new GregorianCalendar(y, m, d, status);
947 if (failure(status, "new GregorianCalendar", TRUE)) return;
948
949 temp->set(UCAL_HOUR, hr);
950 temp->set(UCAL_MINUTE, min);
951 temp->set(UCAL_SECOND, sec);
952 temp->set(UCAL_MILLISECOND, ms);
953 temp->setMinimalDaysInFirstWeek(1);
954
955 UCalendarDateFields e;
956
957 logln("Testing GregorianCalendar add...");
958 e = UCAL_YEAR;
959 while (e < UCAL_FIELD_COUNT) {
960 int32_t i;
961 int32_t limit = maxlimit;
962 status = U_ZERO_ERROR;
963 for (i = 0; i < limit; i++) {
964 temp->add(e, 1, status);
965 if (U_FAILURE(status)) { limit = i; status = U_ZERO_ERROR; }
966 }
967 for (i = 0; i < limit; i++) {
968 temp->add(e, -1, status);
969 if (U_FAILURE(status)) { errln("GregorianCalendar::add -1 failed"); return; }
970 }
971 check520(temp, y, m, d, hr, min, sec, ms, e);
972
973 e = (UCalendarDateFields) ((int32_t) e + 1);
974 }
975
976 logln("Testing GregorianCalendar roll...");
977 e = UCAL_YEAR;
978 while (e < UCAL_FIELD_COUNT) {
979 int32_t i;
980 int32_t limit = maxlimit;
981 status = U_ZERO_ERROR;
982 for (i = 0; i < limit; i++) {
983 logln(calToStr(*temp) + UnicodeString(" " ) + fieldName(e) + UnicodeString("++") );
984 temp->roll(e, 1, status);
985 if (U_FAILURE(status)) {
986 logln("caltest.cpp:%d e=%d, i=%d - roll(+) err %s\n", __LINE__, (int) e, (int) i, u_errorName(status));
987 logln(calToStr(*temp));
988 limit = i; status = U_ZERO_ERROR;
989 }
990 }
991 for (i = 0; i < limit; i++) {
992 logln("caltest.cpp:%d e=%d, i=%d\n", __LINE__, (int) e, (int) i);
993 logln(calToStr(*temp) + UnicodeString(" " ) + fieldName(e) + UnicodeString("--") );
994 temp->roll(e, -1, status);
995 if (U_FAILURE(status)) { errln(UnicodeString("GregorianCalendar::roll ") + CalendarTest::fieldName(e) + " count=" + UnicodeString('@'+i) + " by -1 failed with " + u_errorName(status) ); return; }
996 }
997 check520(temp, y, m, d, hr, min, sec, ms, e);
998
999 e = (UCalendarDateFields) ((int32_t) e + 1);
1000 }
1001
1002 delete temp;
1003 }
1004
1005 // -------------------------------------
1006 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)1007 CalendarTest::check520(Calendar* c,
1008 int32_t y, int32_t m, int32_t d,
1009 int32_t hr, int32_t min, int32_t sec,
1010 int32_t ms, UCalendarDateFields field)
1011
1012 {
1013 UErrorCode status = U_ZERO_ERROR;
1014 if (c->get(UCAL_YEAR, status) != y ||
1015 c->get(UCAL_MONTH, status) != m ||
1016 c->get(UCAL_DATE, status) != d ||
1017 c->get(UCAL_HOUR, status) != hr ||
1018 c->get(UCAL_MINUTE, status) != min ||
1019 c->get(UCAL_SECOND, status) != sec ||
1020 c->get(UCAL_MILLISECOND, status) != ms) {
1021 errln(UnicodeString("U_FAILURE for field ") + (int32_t)field +
1022 ": Expected y/m/d h:m:s:ms of " +
1023 y + "/" + (m + 1) + "/" + d + " " +
1024 hr + ":" + min + ":" + sec + ":" + ms +
1025 "; got " + c->get(UCAL_YEAR, status) +
1026 "/" + (c->get(UCAL_MONTH, status) + 1) +
1027 "/" + c->get(UCAL_DATE, status) +
1028 " " + c->get(UCAL_HOUR, status) + ":" +
1029 c->get(UCAL_MINUTE, status) + ":" +
1030 c->get(UCAL_SECOND, status) + ":" +
1031 c->get(UCAL_MILLISECOND, status)
1032 );
1033
1034 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1035 }
1036 else
1037 logln(UnicodeString("Confirmed: ") + y + "/" +
1038 (m + 1) + "/" + d + " " +
1039 hr + ":" + min + ":" + sec + ":" + ms);
1040 }
1041
1042 // -------------------------------------
1043 void
check520(Calendar * c,int32_t y,int32_t m,int32_t d)1044 CalendarTest::check520(Calendar* c,
1045 int32_t y, int32_t m, int32_t d)
1046
1047 {
1048 UErrorCode status = U_ZERO_ERROR;
1049 if (c->get(UCAL_YEAR, status) != y ||
1050 c->get(UCAL_MONTH, status) != m ||
1051 c->get(UCAL_DATE, status) != d) {
1052 errln(UnicodeString("FAILURE: Expected y/m/d of ") +
1053 y + "/" + (m + 1) + "/" + d + " " +
1054 "; got " + c->get(UCAL_YEAR, status) +
1055 "/" + (c->get(UCAL_MONTH, status) + 1) +
1056 "/" + c->get(UCAL_DATE, status)
1057 );
1058
1059 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1060 }
1061 else
1062 logln(UnicodeString("Confirmed: ") + y + "/" +
1063 (m + 1) + "/" + d);
1064 }
1065
1066 // -------------------------------------
1067
1068 /**
1069 * Test that setting of fields works. In particular, make sure that all instances
1070 * of GregorianCalendar don't share a static instance of the fields array.
1071 */
1072 void
TestFieldSet4781()1073 CalendarTest::TestFieldSet4781()
1074 {
1075 // try {
1076 UErrorCode status = U_ZERO_ERROR;
1077 GregorianCalendar *g = new GregorianCalendar(status);
1078 if (failure(status, "new GregorianCalendar", TRUE)) return;
1079 GregorianCalendar *g2 = new GregorianCalendar(status);
1080 if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
1081 g2->set(UCAL_HOUR, 12, status);
1082 g2->set(UCAL_MINUTE, 0, status);
1083 g2->set(UCAL_SECOND, 0, status);
1084 if (U_FAILURE(status)) { errln("Calendar::set failed"); return; }
1085 if (*g == *g2) logln("Same");
1086 else logln("Different");
1087 //}
1088 //catch(IllegalArgumentException e) {
1089 //errln("Unexpected exception seen: " + e);
1090 //}
1091 delete g;
1092 delete g2;
1093 }
1094
1095 // -------------------------------------
1096
1097 /* We don't support serialization on C++
1098 void
1099 CalendarTest::TestSerialize337()
1100 {
1101 Calendar cal = Calendar::getInstance();
1102 UBool ok = FALSE;
1103 try {
1104 FileOutputStream f = new FileOutputStream(FILENAME);
1105 ObjectOutput s = new ObjectOutputStream(f);
1106 s.writeObject(PREFIX);
1107 s.writeObject(cal);
1108 s.writeObject(POSTFIX);
1109 f.close();
1110 FileInputStream in = new FileInputStream(FILENAME);
1111 ObjectInputStream t = new ObjectInputStream(in);
1112 UnicodeString& pre = (UnicodeString&) t.readObject();
1113 Calendar c = (Calendar) t.readObject();
1114 UnicodeString& post = (UnicodeString&) t.readObject();
1115 in.close();
1116 ok = pre.equals(PREFIX) &&
1117 post.equals(POSTFIX) &&
1118 cal->equals(c);
1119 File fl = new File(FILENAME);
1120 fl.delete();
1121 }
1122 catch(IOException e) {
1123 errln("FAIL: Exception received:");
1124 e.printStackTrace(log);
1125 }
1126 catch(ClassNotFoundException e) {
1127 errln("FAIL: Exception received:");
1128 e.printStackTrace(log);
1129 }
1130 if (!ok) errln("Serialization of Calendar object failed.");
1131 }
1132
1133 UnicodeString& CalendarTest::PREFIX = "abc";
1134
1135 UnicodeString& CalendarTest::POSTFIX = "def";
1136
1137 UnicodeString& CalendarTest::FILENAME = "tmp337.bin";
1138 */
1139
1140 // -------------------------------------
1141
1142 /**
1143 * Verify that the seconds of a Calendar can be zeroed out through the
1144 * expected sequence of operations.
1145 */
1146 void
TestSecondsZero121()1147 CalendarTest::TestSecondsZero121()
1148 {
1149 UErrorCode status = U_ZERO_ERROR;
1150 Calendar *cal = new GregorianCalendar(status);
1151 if (failure(status, "new GregorianCalendar", TRUE)) return;
1152 cal->setTime(Calendar::getNow(), status);
1153 if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
1154 cal->set(UCAL_SECOND, 0);
1155 if (U_FAILURE(status)) { errln("Calendar::set failed"); return; }
1156 UDate d = cal->getTime(status);
1157 if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
1158 UnicodeString s;
1159 dateToString(d, s);
1160 if (s.indexOf("DATE_FORMAT_FAILURE") >= 0) {
1161 dataerrln("Got: \"DATE_FORMAT_FAILURE\".");
1162 } else if (s.indexOf(":00 ") < 0) {
1163 errln("Expected to see :00 in " + s);
1164 }
1165 delete cal;
1166 }
1167
1168 // -------------------------------------
1169
1170 /**
1171 * Verify that a specific sequence of adding and setting works as expected;
1172 * it should not vary depending on when and whether the get method is
1173 * called.
1174 */
1175 void
TestAddSetGet0610()1176 CalendarTest::TestAddSetGet0610()
1177 {
1178 UnicodeString EXPECTED_0610("1993/0/5", "");
1179 UErrorCode status = U_ZERO_ERROR;
1180 {
1181 Calendar *calendar = new GregorianCalendar(status);
1182 if (failure(status, "new GregorianCalendar", TRUE)) return;
1183 calendar->set(1993, UCAL_JANUARY, 4);
1184 logln("1A) " + value(calendar));
1185 calendar->add(UCAL_DATE, 1, status);
1186 if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1187 UnicodeString v = value(calendar);
1188 logln("1B) " + v);
1189 logln("--) 1993/0/5");
1190 if (!(v == EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + "; saw " + v);
1191 delete calendar;
1192 }
1193 {
1194 Calendar *calendar = new GregorianCalendar(1993, UCAL_JANUARY, 4, status);
1195 if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
1196 logln("2A) " + value(calendar));
1197 calendar->add(UCAL_DATE, 1, status);
1198 if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1199 UnicodeString v = value(calendar);
1200 logln("2B) " + v);
1201 logln("--) 1993/0/5");
1202 if (!(v == EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + "; saw " + v);
1203 delete calendar;
1204 }
1205 {
1206 Calendar *calendar = new GregorianCalendar(1993, UCAL_JANUARY, 4, status);
1207 if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
1208 logln("3A) " + value(calendar));
1209 calendar->getTime(status);
1210 if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
1211 calendar->add(UCAL_DATE, 1, status);
1212 if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1213 UnicodeString v = value(calendar);
1214 logln("3B) " + v);
1215 logln("--) 1993/0/5");
1216 if (!(v == EXPECTED_0610)) errln("Expected " + EXPECTED_0610 + "; saw " + v);
1217 delete calendar;
1218 }
1219 }
1220
1221 // -------------------------------------
1222
1223 UnicodeString
value(Calendar * calendar)1224 CalendarTest::value(Calendar* calendar)
1225 {
1226 UErrorCode status = U_ZERO_ERROR;
1227 return UnicodeString("") + (int32_t)calendar->get(UCAL_YEAR, status) +
1228 "/" + (int32_t)calendar->get(UCAL_MONTH, status) +
1229 "/" + (int32_t)calendar->get(UCAL_DATE, status) +
1230 (U_FAILURE(status) ? " FAIL: Calendar::get failed" : "");
1231 }
1232
1233
1234 // -------------------------------------
1235
1236 /**
1237 * Verify that various fields on a known date are set correctly.
1238 */
1239 void
TestFields060()1240 CalendarTest::TestFields060()
1241 {
1242 UErrorCode status = U_ZERO_ERROR;
1243 int32_t year = 1997;
1244 int32_t month = UCAL_OCTOBER;
1245 int32_t dDate = 22;
1246 GregorianCalendar *calendar = 0;
1247 calendar = new GregorianCalendar(year, month, dDate, status);
1248 if (failure(status, "new GregorianCalendar", TRUE)) return;
1249 for (int32_t i = 0; i < EXPECTED_FIELDS_length;) {
1250 UCalendarDateFields field = (UCalendarDateFields)EXPECTED_FIELDS[i++];
1251 int32_t expected = EXPECTED_FIELDS[i++];
1252 if (calendar->get(field, status) != expected) {
1253 errln(UnicodeString("Expected field ") + (int32_t)field + " to have value " + (int32_t)expected +
1254 "; received " + (int32_t)calendar->get(field, status) + " instead");
1255 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1256 }
1257 }
1258 delete calendar;
1259 }
1260
1261 int32_t CalendarTest::EXPECTED_FIELDS[] = {
1262 UCAL_YEAR, 1997,
1263 UCAL_MONTH, UCAL_OCTOBER,
1264 UCAL_DATE, 22,
1265 UCAL_DAY_OF_WEEK, UCAL_WEDNESDAY,
1266 UCAL_DAY_OF_WEEK_IN_MONTH, 4,
1267 UCAL_DAY_OF_YEAR, 295
1268 };
1269
1270 const int32_t CalendarTest::EXPECTED_FIELDS_length = (int32_t)(sizeof(CalendarTest::EXPECTED_FIELDS) /
1271 sizeof(CalendarTest::EXPECTED_FIELDS[0]));
1272
1273 // -------------------------------------
1274
1275 /**
1276 * Verify that various fields on a known date are set correctly. In this
1277 * case, the start of the epoch (January 1 1970).
1278 */
1279 void
TestEpochStartFields()1280 CalendarTest::TestEpochStartFields()
1281 {
1282 UErrorCode status = U_ZERO_ERROR;
1283 TimeZone *z = TimeZone::createDefault();
1284 Calendar *c = Calendar::createInstance(status);
1285 if (failure(status, "Calendar::createInstance", TRUE)) return;
1286 UDate d = - z->getRawOffset();
1287 GregorianCalendar *gc = new GregorianCalendar(status);
1288 if (U_FAILURE(status)) { errln("Couldn't create GregorianCalendar"); return; }
1289 gc->setTimeZone(*z);
1290 gc->setTime(d, status);
1291 if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
1292 UBool idt = gc->inDaylightTime(status);
1293 if (U_FAILURE(status)) { errln("GregorianCalendar::inDaylightTime failed"); return; }
1294 if (idt) {
1295 UnicodeString str;
1296 logln("Warning: Skipping test because " + dateToString(d, str) + " is in DST.");
1297 }
1298 else {
1299 c->setTime(d, status);
1300 if (U_FAILURE(status)) { errln("Calendar::setTime failed"); return; }
1301 for (int32_t i = 0; i < UCAL_ZONE_OFFSET;++i) {
1302 if (c->get((UCalendarDateFields)i, status) != EPOCH_FIELDS[i])
1303 errln(UnicodeString("Expected field ") + i + " to have value " + EPOCH_FIELDS[i] +
1304 "; saw " + c->get((UCalendarDateFields)i, status) + " instead");
1305 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1306 }
1307 if (c->get(UCAL_ZONE_OFFSET, status) != z->getRawOffset())
1308 {
1309 errln(UnicodeString("Expected field ZONE_OFFSET to have value ") + z->getRawOffset() +
1310 "; saw " + c->get(UCAL_ZONE_OFFSET, status) + " instead");
1311 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1312 }
1313 if (c->get(UCAL_DST_OFFSET, status) != 0)
1314 {
1315 errln(UnicodeString("Expected field DST_OFFSET to have value 0") +
1316 "; saw " + c->get(UCAL_DST_OFFSET, status) + " instead");
1317 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1318 }
1319 }
1320 delete c;
1321 delete z;
1322 delete gc;
1323 }
1324
1325 int32_t CalendarTest::EPOCH_FIELDS[] = {
1326 1, 1970, 0, 53, 0, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, - 28800000, 0
1327 };
1328
1329 // -------------------------------------
1330
1331 /**
1332 * Test that the days of the week progress properly when add is called repeatedly
1333 * for increments of 24 days.
1334 */
1335 void
TestDOWProgression()1336 CalendarTest::TestDOWProgression()
1337 {
1338 UErrorCode status = U_ZERO_ERROR;
1339 Calendar *cal = new GregorianCalendar(1972, UCAL_OCTOBER, 26, status);
1340 if (failure(status, "new GregorianCalendar", TRUE)) return;
1341 marchByDelta(cal, 24);
1342 delete cal;
1343 }
1344
1345 // -------------------------------------
1346
1347 void
TestDOW_LOCALandYEAR_WOY()1348 CalendarTest::TestDOW_LOCALandYEAR_WOY()
1349 {
1350 /* Note: I've commented out the loop_addroll tests for YEAR and
1351 * YEAR_WOY below because these two fields should NOT behave
1352 * identically when adding. YEAR should keep the month/dom
1353 * invariant. YEAR_WOY should keep the woy/dow invariant. I've
1354 * added a new test that checks for this in place of the old call
1355 * to loop_addroll. - aliu */
1356 UErrorCode status = U_ZERO_ERROR;
1357 int32_t times = 20;
1358 Calendar *cal=Calendar::createInstance(Locale::getGermany(), status);
1359 if (failure(status, "Calendar::createInstance", TRUE)) return;
1360 SimpleDateFormat *sdf=new SimpleDateFormat(UnicodeString("YYYY'-W'ww-ee"), Locale::getGermany(), status);
1361 if (U_FAILURE(status)) { errcheckln(status, "Couldn't create SimpleDateFormat - %s", u_errorName(status)); return; }
1362
1363 // ICU no longer use localized date-time pattern characters by default.
1364 // So we set pattern chars using 'J' instead of 'Y'.
1365 DateFormatSymbols *dfs = new DateFormatSymbols(Locale::getGermany(), status);
1366 dfs->setLocalPatternChars(UnicodeString("GyMdkHmsSEDFwWahKzJeugAZvcLQq"));
1367 sdf->adoptDateFormatSymbols(dfs);
1368 sdf->applyLocalizedPattern(UnicodeString("JJJJ'-W'ww-ee"), status);
1369 if (U_FAILURE(status)) { errln("Couldn't apply localized pattern"); return; }
1370
1371 cal->clear();
1372 cal->set(1997, UCAL_DECEMBER, 25);
1373 doYEAR_WOYLoop(cal, sdf, times, status);
1374 //loop_addroll(cal, /*sdf,*/ times, UCAL_YEAR_WOY, UCAL_YEAR, status);
1375 yearAddTest(*cal, status); // aliu
1376 loop_addroll(cal, /*sdf,*/ times, UCAL_DOW_LOCAL, UCAL_DAY_OF_WEEK, status);
1377 if (U_FAILURE(status)) { errln("Error in parse/calculate test for 1997"); return; }
1378
1379 cal->clear();
1380 cal->set(1998, UCAL_DECEMBER, 25);
1381 doYEAR_WOYLoop(cal, sdf, times, status);
1382 //loop_addroll(cal, /*sdf,*/ times, UCAL_YEAR_WOY, UCAL_YEAR, status);
1383 yearAddTest(*cal, status); // aliu
1384 loop_addroll(cal, /*sdf,*/ times, UCAL_DOW_LOCAL, UCAL_DAY_OF_WEEK, status);
1385 if (U_FAILURE(status)) { errln("Error in parse/calculate test for 1998"); return; }
1386
1387 cal->clear();
1388 cal->set(1582, UCAL_OCTOBER, 1);
1389 doYEAR_WOYLoop(cal, sdf, times, status);
1390 //loop_addroll(cal, /*sdf,*/ times, Calendar::YEAR_WOY, Calendar::YEAR, status);
1391 yearAddTest(*cal, status); // aliu
1392 loop_addroll(cal, /*sdf,*/ times, UCAL_DOW_LOCAL, UCAL_DAY_OF_WEEK, status);
1393 if (U_FAILURE(status)) { errln("Error in parse/calculate test for 1582"); return; }
1394 delete sdf;
1395 delete cal;
1396
1397 return;
1398 }
1399
1400 /**
1401 * Confirm that adding a YEAR and adding a YEAR_WOY work properly for
1402 * the given Calendar at its current setting.
1403 */
yearAddTest(Calendar & cal,UErrorCode & status)1404 void CalendarTest::yearAddTest(Calendar& cal, UErrorCode& status) {
1405 /**
1406 * When adding the YEAR, the month and day should remain constant.
1407 * When adding the YEAR_WOY, the WOY and DOW should remain constant. - aliu
1408 * Examples:
1409 * Wed Jan 14 1998 / 1998-W03-03 Add(YEAR_WOY, 1) -> Wed Jan 20 1999 / 1999-W03-03
1410 * Add(YEAR, 1) -> Thu Jan 14 1999 / 1999-W02-04
1411 * Thu Jan 14 1999 / 1999-W02-04 Add(YEAR_WOY, 1) -> Thu Jan 13 2000 / 2000-W02-04
1412 * Add(YEAR, 1) -> Fri Jan 14 2000 / 2000-W02-05
1413 * Sun Oct 31 1582 / 1582-W42-07 Add(YEAR_WOY, 1) -> Sun Oct 23 1583 / 1583-W42-07
1414 * Add(YEAR, 1) -> Mon Oct 31 1583 / 1583-W44-01
1415 */
1416 int32_t y = cal.get(UCAL_YEAR, status);
1417 int32_t mon = cal.get(UCAL_MONTH, status);
1418 int32_t day = cal.get(UCAL_DATE, status);
1419 int32_t ywy = cal.get(UCAL_YEAR_WOY, status);
1420 int32_t woy = cal.get(UCAL_WEEK_OF_YEAR, status);
1421 int32_t dow = cal.get(UCAL_DOW_LOCAL, status);
1422 UDate t = cal.getTime(status);
1423
1424 if(U_FAILURE(status)){
1425 errln(UnicodeString("Failed to create Calendar for locale. Error: ") + UnicodeString(u_errorName(status)));
1426 return;
1427 }
1428 UnicodeString str, str2;
1429 SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"), status);
1430 fmt.setCalendar(cal);
1431
1432 fmt.format(t, str.remove());
1433 str += ".add(YEAR, 1) =>";
1434 cal.add(UCAL_YEAR, 1, status);
1435 int32_t y2 = cal.get(UCAL_YEAR, status);
1436 int32_t mon2 = cal.get(UCAL_MONTH, status);
1437 int32_t day2 = cal.get(UCAL_DATE, status);
1438 fmt.format(cal.getTime(status), str);
1439 if (y2 != (y+1) || mon2 != mon || day2 != day) {
1440 str += (UnicodeString)", expected year " +
1441 (y+1) + ", month " + (mon+1) + ", day " + day;
1442 errln((UnicodeString)"FAIL: " + str);
1443 logln( UnicodeString(" -> ") + CalendarTest::calToStr(cal) );
1444 } else {
1445 logln(str);
1446 }
1447
1448 fmt.format(t, str.remove());
1449 str += ".add(YEAR_WOY, 1)=>";
1450 cal.setTime(t, status);
1451 logln( UnicodeString(" <- ") + CalendarTest::calToStr(cal) );
1452 cal.add(UCAL_YEAR_WOY, 1, status);
1453 int32_t ywy2 = cal.get(UCAL_YEAR_WOY, status);
1454 int32_t woy2 = cal.get(UCAL_WEEK_OF_YEAR, status);
1455 int32_t dow2 = cal.get(UCAL_DOW_LOCAL, status);
1456 fmt.format(cal.getTime(status), str);
1457 if (ywy2 != (ywy+1) || woy2 != woy || dow2 != dow) {
1458 str += (UnicodeString)", expected yearWOY " +
1459 (ywy+1) + ", woy " + woy + ", dowLocal " + dow;
1460 errln((UnicodeString)"FAIL: " + str);
1461 logln( UnicodeString(" -> ") + CalendarTest::calToStr(cal) );
1462 } else {
1463 logln(str);
1464 }
1465 }
1466
1467 // -------------------------------------
1468
loop_addroll(Calendar * cal,int times,UCalendarDateFields field,UCalendarDateFields field2,UErrorCode & errorCode)1469 void CalendarTest::loop_addroll(Calendar *cal, /*SimpleDateFormat *sdf,*/ int times, UCalendarDateFields field, UCalendarDateFields field2, UErrorCode& errorCode) {
1470 Calendar *calclone;
1471 SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy / YYYY'-W'ww-ee"), errorCode);
1472 fmt.setCalendar(*cal);
1473 int i;
1474
1475 for(i = 0; i<times; i++) {
1476 calclone = cal->clone();
1477 UDate start = cal->getTime(errorCode);
1478 cal->add(field,1,errorCode);
1479 if (U_FAILURE(errorCode)) { errln("Error in add"); delete calclone; return; }
1480 calclone->add(field2,1,errorCode);
1481 if (U_FAILURE(errorCode)) { errln("Error in add"); delete calclone; return; }
1482 if(cal->getTime(errorCode) != calclone->getTime(errorCode)) {
1483 UnicodeString str("FAIL: Results of add differ. "), str2;
1484 str += fmt.format(start, str2) + " ";
1485 str += UnicodeString("Add(") + fieldName(field) + ", 1) -> " +
1486 fmt.format(cal->getTime(errorCode), str2.remove()) + "; ";
1487 str += UnicodeString("Add(") + fieldName(field2) + ", 1) -> " +
1488 fmt.format(calclone->getTime(errorCode), str2.remove());
1489 errln(str);
1490 delete calclone;
1491 return;
1492 }
1493 delete calclone;
1494 }
1495
1496 for(i = 0; i<times; i++) {
1497 calclone = cal->clone();
1498 cal->roll(field,(int32_t)1,errorCode);
1499 if (U_FAILURE(errorCode)) { errln("Error in roll"); delete calclone; return; }
1500 calclone->roll(field2,(int32_t)1,errorCode);
1501 if (U_FAILURE(errorCode)) { errln("Error in roll"); delete calclone; return; }
1502 if(cal->getTime(errorCode) != calclone->getTime(errorCode)) {
1503 delete calclone;
1504 errln("Results of roll differ!");
1505 return;
1506 }
1507 delete calclone;
1508 }
1509 }
1510
1511 // -------------------------------------
1512
1513 void
doYEAR_WOYLoop(Calendar * cal,SimpleDateFormat * sdf,int32_t times,UErrorCode & errorCode)1514 CalendarTest::doYEAR_WOYLoop(Calendar *cal, SimpleDateFormat *sdf,
1515 int32_t times, UErrorCode& errorCode) {
1516
1517 UnicodeString us;
1518 UDate tst, original;
1519 Calendar *tstres = new GregorianCalendar(Locale::getGermany(), errorCode);
1520 for(int i=0; i<times; ++i) {
1521 sdf->format(Formattable(cal->getTime(errorCode),Formattable::kIsDate), us, errorCode);
1522 //logln("expected: "+us);
1523 if (U_FAILURE(errorCode)) { errln("Format error"); return; }
1524 tst=sdf->parse(us,errorCode);
1525 if (U_FAILURE(errorCode)) { errln("Parse error"); return; }
1526 tstres->clear();
1527 tstres->setTime(tst, errorCode);
1528 //logln((UnicodeString)"Parsed week of year is "+tstres->get(UCAL_WEEK_OF_YEAR, errorCode));
1529 if (U_FAILURE(errorCode)) { errln("Set time error"); return; }
1530 original = cal->getTime(errorCode);
1531 us.remove();
1532 sdf->format(Formattable(tst,Formattable::kIsDate), us, errorCode);
1533 //logln("got: "+us);
1534 if (U_FAILURE(errorCode)) { errln("Get time error"); return; }
1535 if(original!=tst) {
1536 us.remove();
1537 sdf->format(Formattable(original, Formattable::kIsDate), us, errorCode);
1538 errln("FAIL: Parsed time doesn't match with regular");
1539 logln("expected "+us + " " + calToStr(*cal));
1540 us.remove();
1541 sdf->format(Formattable(tst, Formattable::kIsDate), us, errorCode);
1542 logln("got "+us + " " + calToStr(*tstres));
1543 }
1544 tstres->clear();
1545 tstres->set(UCAL_YEAR_WOY, cal->get(UCAL_YEAR_WOY, errorCode));
1546 tstres->set(UCAL_WEEK_OF_YEAR, cal->get(UCAL_WEEK_OF_YEAR, errorCode));
1547 tstres->set(UCAL_DOW_LOCAL, cal->get(UCAL_DOW_LOCAL, errorCode));
1548 if(cal->get(UCAL_YEAR, errorCode) != tstres->get(UCAL_YEAR, errorCode)) {
1549 errln("FAIL: Different Year!");
1550 logln((UnicodeString)"Expected "+cal->get(UCAL_YEAR, errorCode));
1551 logln((UnicodeString)"Got "+tstres->get(UCAL_YEAR, errorCode));
1552 return;
1553 }
1554 if(cal->get(UCAL_DAY_OF_YEAR, errorCode) != tstres->get(UCAL_DAY_OF_YEAR, errorCode)) {
1555 errln("FAIL: Different Day Of Year!");
1556 logln((UnicodeString)"Expected "+cal->get(UCAL_DAY_OF_YEAR, errorCode));
1557 logln((UnicodeString)"Got "+tstres->get(UCAL_DAY_OF_YEAR, errorCode));
1558 return;
1559 }
1560 //logln(calToStr(*cal));
1561 cal->add(UCAL_DATE, 1, errorCode);
1562 if (U_FAILURE(errorCode)) { errln("Add error"); return; }
1563 us.remove();
1564 }
1565 delete (tstres);
1566 }
1567 // -------------------------------------
1568
1569 void
marchByDelta(Calendar * cal,int32_t delta)1570 CalendarTest::marchByDelta(Calendar* cal, int32_t delta)
1571 {
1572 UErrorCode status = U_ZERO_ERROR;
1573 Calendar *cur = (Calendar*) cal->clone();
1574 int32_t initialDOW = cur->get(UCAL_DAY_OF_WEEK, status);
1575 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1576 int32_t DOW, newDOW = initialDOW;
1577 do {
1578 UnicodeString str;
1579 DOW = newDOW;
1580 logln(UnicodeString("DOW = ") + DOW + " " + dateToString(cur->getTime(status), str));
1581 if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
1582 cur->add(UCAL_DAY_OF_WEEK, delta, status);
1583 if (U_FAILURE(status)) { errln("Calendar::add failed"); return; }
1584 newDOW = cur->get(UCAL_DAY_OF_WEEK, status);
1585 if (U_FAILURE(status)) { errln("Calendar::get failed"); return; }
1586 int32_t expectedDOW = 1 + (DOW + delta - 1) % 7;
1587 if (newDOW != expectedDOW) {
1588 errln(UnicodeString("Day of week should be ") + expectedDOW + " instead of " + newDOW +
1589 " on " + dateToString(cur->getTime(status), str));
1590 if (U_FAILURE(status)) { errln("Calendar::getTime failed"); return; }
1591 return;
1592 }
1593 }
1594 while (newDOW != initialDOW);
1595 delete cur;
1596 }
1597
1598 #define CHECK(status, msg) \
1599 if (U_FAILURE(status)) { \
1600 errcheckln(status, msg); \
1601 return; \
1602 }
1603
TestWOY(void)1604 void CalendarTest::TestWOY(void) {
1605 /*
1606 FDW = Mon, MDFW = 4:
1607 Sun Dec 26 1999, WOY 51
1608 Mon Dec 27 1999, WOY 52
1609 Tue Dec 28 1999, WOY 52
1610 Wed Dec 29 1999, WOY 52
1611 Thu Dec 30 1999, WOY 52
1612 Fri Dec 31 1999, WOY 52
1613 Sat Jan 01 2000, WOY 52 ***
1614 Sun Jan 02 2000, WOY 52 ***
1615 Mon Jan 03 2000, WOY 1
1616 Tue Jan 04 2000, WOY 1
1617 Wed Jan 05 2000, WOY 1
1618 Thu Jan 06 2000, WOY 1
1619 Fri Jan 07 2000, WOY 1
1620 Sat Jan 08 2000, WOY 1
1621 Sun Jan 09 2000, WOY 1
1622 Mon Jan 10 2000, WOY 2
1623
1624 FDW = Mon, MDFW = 2:
1625 Sun Dec 26 1999, WOY 52
1626 Mon Dec 27 1999, WOY 1 ***
1627 Tue Dec 28 1999, WOY 1 ***
1628 Wed Dec 29 1999, WOY 1 ***
1629 Thu Dec 30 1999, WOY 1 ***
1630 Fri Dec 31 1999, WOY 1 ***
1631 Sat Jan 01 2000, WOY 1
1632 Sun Jan 02 2000, WOY 1
1633 Mon Jan 03 2000, WOY 2
1634 Tue Jan 04 2000, WOY 2
1635 Wed Jan 05 2000, WOY 2
1636 Thu Jan 06 2000, WOY 2
1637 Fri Jan 07 2000, WOY 2
1638 Sat Jan 08 2000, WOY 2
1639 Sun Jan 09 2000, WOY 2
1640 Mon Jan 10 2000, WOY 3
1641 */
1642
1643 UnicodeString str;
1644 UErrorCode status = U_ZERO_ERROR;
1645 int32_t i;
1646
1647 GregorianCalendar cal(status);
1648 SimpleDateFormat fmt(UnicodeString("EEE MMM dd yyyy', WOY' w"), status);
1649 if (failure(status, "Cannot construct calendar/format", TRUE)) return;
1650
1651 UCalendarDaysOfWeek fdw = (UCalendarDaysOfWeek) 0;
1652
1653 //for (int8_t pass=2; pass<=2; ++pass) {
1654 for (int8_t pass=1; pass<=2; ++pass) {
1655 switch (pass) {
1656 case 1:
1657 fdw = UCAL_MONDAY;
1658 cal.setFirstDayOfWeek(fdw);
1659 cal.setMinimalDaysInFirstWeek(4);
1660 fmt.adoptCalendar(cal.clone());
1661 break;
1662 case 2:
1663 fdw = UCAL_MONDAY;
1664 cal.setFirstDayOfWeek(fdw);
1665 cal.setMinimalDaysInFirstWeek(2);
1666 fmt.adoptCalendar(cal.clone());
1667 break;
1668 }
1669
1670 //for (i=2; i<=6; ++i) {
1671 for (i=0; i<16; ++i) {
1672 UDate t, t2;
1673 int32_t t_y, t_woy, t_dow;
1674 cal.clear();
1675 cal.set(1999, UCAL_DECEMBER, 26 + i);
1676 fmt.format(t = cal.getTime(status), str.remove());
1677 CHECK(status, "Fail: getTime failed");
1678 logln(UnicodeString("* ") + str);
1679 int32_t dow = cal.get(UCAL_DAY_OF_WEEK, status);
1680 int32_t woy = cal.get(UCAL_WEEK_OF_YEAR, status);
1681 int32_t year = cal.get(UCAL_YEAR, status);
1682 int32_t mon = cal.get(UCAL_MONTH, status);
1683 logln(calToStr(cal));
1684 CHECK(status, "Fail: get failed");
1685 int32_t dowLocal = dow - fdw;
1686 if (dowLocal < 0) dowLocal += 7;
1687 dowLocal++;
1688 int32_t yearWoy = year;
1689 if (mon == UCAL_JANUARY) {
1690 if (woy >= 52) --yearWoy;
1691 } else {
1692 if (woy == 1) ++yearWoy;
1693 }
1694
1695 // Basic fields->time check y/woy/dow
1696 // Since Y/WOY is ambiguous, we do a check of the fields,
1697 // not of the specific time.
1698 cal.clear();
1699 cal.set(UCAL_YEAR, year);
1700 cal.set(UCAL_WEEK_OF_YEAR, woy);
1701 cal.set(UCAL_DAY_OF_WEEK, dow);
1702 t_y = cal.get(UCAL_YEAR, status);
1703 t_woy = cal.get(UCAL_WEEK_OF_YEAR, status);
1704 t_dow = cal.get(UCAL_DAY_OF_WEEK, status);
1705 CHECK(status, "Fail: get failed");
1706 if (t_y != year || t_woy != woy || t_dow != dow) {
1707 str = "Fail: y/woy/dow fields->time => ";
1708 fmt.format(cal.getTime(status), str);
1709 errln(str);
1710 logln(calToStr(cal));
1711 logln("[get!=set] Y%d!=%d || woy%d!=%d || dow%d!=%d\n",
1712 t_y, year, t_woy, woy, t_dow, dow);
1713 } else {
1714 logln("y/woy/dow fields->time OK");
1715 }
1716
1717 // Basic fields->time check y/woy/dow_local
1718 // Since Y/WOY is ambiguous, we do a check of the fields,
1719 // not of the specific time.
1720 cal.clear();
1721 cal.set(UCAL_YEAR, year);
1722 cal.set(UCAL_WEEK_OF_YEAR, woy);
1723 cal.set(UCAL_DOW_LOCAL, dowLocal);
1724 t_y = cal.get(UCAL_YEAR, status);
1725 t_woy = cal.get(UCAL_WEEK_OF_YEAR, status);
1726 t_dow = cal.get(UCAL_DOW_LOCAL, status);
1727 CHECK(status, "Fail: get failed");
1728 if (t_y != year || t_woy != woy || t_dow != dowLocal) {
1729 str = "Fail: y/woy/dow_local fields->time => ";
1730 fmt.format(cal.getTime(status), str);
1731 errln(str);
1732 }
1733
1734 // Basic fields->time check y_woy/woy/dow
1735 cal.clear();
1736 cal.set(UCAL_YEAR_WOY, yearWoy);
1737 cal.set(UCAL_WEEK_OF_YEAR, woy);
1738 cal.set(UCAL_DAY_OF_WEEK, dow);
1739 t2 = cal.getTime(status);
1740 CHECK(status, "Fail: getTime failed");
1741 if (t != t2) {
1742 str = "Fail: y_woy/woy/dow fields->time => ";
1743 fmt.format(t2, str);
1744 errln(str);
1745 logln(calToStr(cal));
1746 logln("%.f != %.f\n", t, t2);
1747 } else {
1748 logln("y_woy/woy/dow OK");
1749 }
1750
1751 // Basic fields->time check y_woy/woy/dow_local
1752 cal.clear();
1753 cal.set(UCAL_YEAR_WOY, yearWoy);
1754 cal.set(UCAL_WEEK_OF_YEAR, woy);
1755 cal.set(UCAL_DOW_LOCAL, dowLocal);
1756 t2 = cal.getTime(status);
1757 CHECK(status, "Fail: getTime failed");
1758 if (t != t2) {
1759 str = "Fail: y_woy/woy/dow_local fields->time => ";
1760 fmt.format(t2, str);
1761 errln(str);
1762 }
1763
1764 logln("Testing DOW_LOCAL.. dow%d\n", dow);
1765 // Make sure DOW_LOCAL disambiguates over DOW
1766 int32_t wrongDow = dow - 3;
1767 if (wrongDow < 1) wrongDow += 7;
1768 cal.setTime(t, status);
1769 cal.set(UCAL_DAY_OF_WEEK, wrongDow);
1770 cal.set(UCAL_DOW_LOCAL, dowLocal);
1771 t2 = cal.getTime(status);
1772 CHECK(status, "Fail: set/getTime failed");
1773 if (t != t2) {
1774 str = "Fail: DOW_LOCAL fields->time => ";
1775 fmt.format(t2, str);
1776 errln(str);
1777 logln(calToStr(cal));
1778 logln("%.f : DOW%d, DOW_LOCAL%d -> %.f\n",
1779 t, wrongDow, dowLocal, t2);
1780 }
1781
1782 // Make sure DOW disambiguates over DOW_LOCAL
1783 int32_t wrongDowLocal = dowLocal - 3;
1784 if (wrongDowLocal < 1) wrongDowLocal += 7;
1785 cal.setTime(t, status);
1786 cal.set(UCAL_DOW_LOCAL, wrongDowLocal);
1787 cal.set(UCAL_DAY_OF_WEEK, dow);
1788 t2 = cal.getTime(status);
1789 CHECK(status, "Fail: set/getTime failed");
1790 if (t != t2) {
1791 str = "Fail: DOW fields->time => ";
1792 fmt.format(t2, str);
1793 errln(str);
1794 }
1795
1796 // Make sure YEAR_WOY disambiguates over YEAR
1797 cal.setTime(t, status);
1798 cal.set(UCAL_YEAR, year - 2);
1799 cal.set(UCAL_YEAR_WOY, yearWoy);
1800 t2 = cal.getTime(status);
1801 CHECK(status, "Fail: set/getTime failed");
1802 if (t != t2) {
1803 str = "Fail: YEAR_WOY fields->time => ";
1804 fmt.format(t2, str);
1805 errln(str);
1806 }
1807
1808 // Make sure YEAR disambiguates over YEAR_WOY
1809 cal.setTime(t, status);
1810 cal.set(UCAL_YEAR_WOY, yearWoy - 2);
1811 cal.set(UCAL_YEAR, year);
1812 t2 = cal.getTime(status);
1813 CHECK(status, "Fail: set/getTime failed");
1814 if (t != t2) {
1815 str = "Fail: YEAR fields->time => ";
1816 fmt.format(t2, str);
1817 errln(str);
1818 }
1819 }
1820 }
1821
1822 /*
1823 FDW = Mon, MDFW = 4:
1824 Sun Dec 26 1999, WOY 51
1825 Mon Dec 27 1999, WOY 52
1826 Tue Dec 28 1999, WOY 52
1827 Wed Dec 29 1999, WOY 52
1828 Thu Dec 30 1999, WOY 52
1829 Fri Dec 31 1999, WOY 52
1830 Sat Jan 01 2000, WOY 52
1831 Sun Jan 02 2000, WOY 52
1832 */
1833
1834 // Roll the DOW_LOCAL within week 52
1835 for (i=27; i<=33; ++i) {
1836 int32_t amount;
1837 for (amount=-7; amount<=7; ++amount) {
1838 str = "roll(";
1839 cal.set(1999, UCAL_DECEMBER, i);
1840 UDate t, t2;
1841 fmt.format(cal.getTime(status), str);
1842 CHECK(status, "Fail: getTime failed");
1843 str += UnicodeString(", ") + amount + ") = ";
1844
1845 cal.roll(UCAL_DOW_LOCAL, amount, status);
1846 CHECK(status, "Fail: roll failed");
1847
1848 t = cal.getTime(status);
1849 int32_t newDom = i + amount;
1850 while (newDom < 27) newDom += 7;
1851 while (newDom > 33) newDom -= 7;
1852 cal.set(1999, UCAL_DECEMBER, newDom);
1853 t2 = cal.getTime(status);
1854 CHECK(status, "Fail: getTime failed");
1855 fmt.format(t, str);
1856
1857 if (t != t2) {
1858 str.append(", exp ");
1859 fmt.format(t2, str);
1860 errln(str);
1861 } else {
1862 logln(str);
1863 }
1864 }
1865 }
1866 }
1867
TestYWOY()1868 void CalendarTest::TestYWOY()
1869 {
1870 UnicodeString str;
1871 UErrorCode status = U_ZERO_ERROR;
1872
1873 GregorianCalendar cal(status);
1874 if (failure(status, "construct GregorianCalendar", TRUE)) return;
1875
1876 cal.setFirstDayOfWeek(UCAL_SUNDAY);
1877 cal.setMinimalDaysInFirstWeek(1);
1878
1879 logln("Setting: ywoy=2004, woy=1, dow=MONDAY");
1880 cal.clear();
1881 cal.set(UCAL_YEAR_WOY,2004);
1882 cal.set(UCAL_WEEK_OF_YEAR,1);
1883 cal.set(UCAL_DAY_OF_WEEK, UCAL_MONDAY);
1884
1885 logln(calToStr(cal));
1886 if(cal.get(UCAL_YEAR, status) != 2003) {
1887 errln("year not 2003");
1888 }
1889
1890 logln("+ setting DOW to THURSDAY");
1891 cal.clear();
1892 cal.set(UCAL_YEAR_WOY,2004);
1893 cal.set(UCAL_WEEK_OF_YEAR,1);
1894 cal.set(UCAL_DAY_OF_WEEK, UCAL_THURSDAY);
1895
1896 logln(calToStr(cal));
1897 if(cal.get(UCAL_YEAR, status) != 2004) {
1898 errln("year not 2004");
1899 }
1900
1901 logln("+ setting DOW_LOCAL to 1");
1902 cal.clear();
1903 cal.set(UCAL_YEAR_WOY,2004);
1904 cal.set(UCAL_WEEK_OF_YEAR,1);
1905 cal.set(UCAL_DAY_OF_WEEK, UCAL_THURSDAY);
1906 cal.set(UCAL_DOW_LOCAL, 1);
1907
1908 logln(calToStr(cal));
1909 if(cal.get(UCAL_YEAR, status) != 2003) {
1910 errln("year not 2003");
1911 }
1912
1913 cal.setFirstDayOfWeek(UCAL_MONDAY);
1914 cal.setMinimalDaysInFirstWeek(4);
1915 UDate t = 946713600000.;
1916 cal.setTime(t, status);
1917 cal.set(UCAL_DAY_OF_WEEK, 4);
1918 cal.set(UCAL_DOW_LOCAL, 6);
1919 if(cal.getTime(status) != t) {
1920 logln(calToStr(cal));
1921 errln("FAIL: DOW_LOCAL did not take precedence");
1922 }
1923
1924 }
1925
TestJD()1926 void CalendarTest::TestJD()
1927 {
1928 int32_t jd;
1929 static const int32_t kEpochStartAsJulianDay = 2440588;
1930 UErrorCode status = U_ZERO_ERROR;
1931 GregorianCalendar cal(status);
1932 if (failure(status, "construct GregorianCalendar", TRUE)) return;
1933 cal.setTimeZone(*TimeZone::getGMT());
1934 cal.clear();
1935 jd = cal.get(UCAL_JULIAN_DAY, status);
1936 if(jd != kEpochStartAsJulianDay) {
1937 errln("Wanted JD of %d at time=0, [epoch 1970] but got %d\n", kEpochStartAsJulianDay, jd);
1938 } else {
1939 logln("Wanted JD of %d at time=0, [epoch 1970], got %d\n", kEpochStartAsJulianDay, jd);
1940 }
1941
1942 cal.setTime(Calendar::getNow(), status);
1943 cal.clear();
1944 cal.set(UCAL_JULIAN_DAY, kEpochStartAsJulianDay);
1945 UDate epochTime = cal.getTime(status);
1946 if(epochTime != 0) {
1947 errln("Wanted time of 0 at jd=%d, got %.1lf\n", kEpochStartAsJulianDay, epochTime);
1948 } else {
1949 logln("Wanted time of 0 at jd=%d, got %.1lf\n", kEpochStartAsJulianDay, epochTime);
1950 }
1951
1952 }
1953
1954 // make sure the ctestfw utilities are in sync with the Calendar
TestDebug()1955 void CalendarTest::TestDebug()
1956 {
1957 for(int32_t t=0;t<=UDBG_ENUM_COUNT;t++) {
1958 int32_t count = udbg_enumCount((UDebugEnumType)t);
1959 if(count == -1) {
1960 logln("enumCount(%d) returned -1", count);
1961 continue;
1962 }
1963 for(int32_t i=0;i<=count;i++) {
1964 if(t<=UDBG_HIGHEST_CONTIGUOUS_ENUM && i<count) {
1965 if( i!=udbg_enumArrayValue((UDebugEnumType)t, i)) {
1966 errln("FAIL: udbg_enumArrayValue(%d,%d) returned %d, expected %d", t, i, udbg_enumArrayValue((UDebugEnumType)t,i), i);
1967 }
1968 } else {
1969 logln("Testing count+1:");
1970 }
1971 const char *name = udbg_enumName((UDebugEnumType)t,i);
1972 if(name==NULL) {
1973 if(i==count || t>UDBG_HIGHEST_CONTIGUOUS_ENUM ) {
1974 logln(" null name - expected.\n");
1975 } else {
1976 errln("FAIL: udbg_enumName(%d,%d) returned NULL", t, i);
1977 }
1978 name = "(null)";
1979 }
1980 logln("udbg_enumArrayValue(%d,%d) = %s, returned %d", t, i,
1981 name, udbg_enumArrayValue((UDebugEnumType)t,i));
1982 logln("udbg_enumString = " + udbg_enumString((UDebugEnumType)t,i));
1983 }
1984 if(udbg_enumExpectedCount((UDebugEnumType)t) != count && t<=UDBG_HIGHEST_CONTIGUOUS_ENUM) {
1985 errln("FAIL: udbg_enumExpectedCount(%d): %d, != UCAL_FIELD_COUNT=%d ", t, udbg_enumExpectedCount((UDebugEnumType)t), count);
1986 } else {
1987 logln("udbg_ucal_fieldCount: %d, UCAL_FIELD_COUNT=udbg_enumCount %d ", udbg_enumExpectedCount((UDebugEnumType)t), count);
1988 }
1989 }
1990 }
1991
1992
1993 #undef CHECK
1994
1995 // List of interesting locales
testLocaleID(int32_t i)1996 const char *CalendarTest::testLocaleID(int32_t i)
1997 {
1998 switch(i) {
1999 case 0: return "he_IL@calendar=hebrew";
2000 case 1: return "en_US@calendar=hebrew";
2001 case 2: return "fr_FR@calendar=hebrew";
2002 case 3: return "fi_FI@calendar=hebrew";
2003 case 4: return "nl_NL@calendar=hebrew";
2004 case 5: return "hu_HU@calendar=hebrew";
2005 case 6: return "nl_BE@currency=MTL;calendar=islamic";
2006 case 7: return "th_TH_TRADITIONAL@calendar=gregorian";
2007 case 8: return "ar_JO@calendar=islamic-civil";
2008 case 9: return "fi_FI@calendar=islamic";
2009 case 10: return "fr_CH@calendar=islamic-civil";
2010 case 11: return "he_IL@calendar=islamic-civil";
2011 case 12: return "hu_HU@calendar=buddhist";
2012 case 13: return "hu_HU@calendar=islamic";
2013 case 14: return "en_US@calendar=japanese";
2014 default: return NULL;
2015 }
2016 }
2017
testLocaleCount()2018 int32_t CalendarTest::testLocaleCount()
2019 {
2020 static int32_t gLocaleCount = -1;
2021 if(gLocaleCount < 0) {
2022 int32_t i;
2023 for(i=0;testLocaleID(i) != NULL;i++) {
2024 ;
2025 }
2026 gLocaleCount = i;
2027 }
2028 return gLocaleCount;
2029 }
2030
doMinDateOfCalendar(Calendar * adopt,UBool & isGregorian,UErrorCode & status)2031 static UDate doMinDateOfCalendar(Calendar* adopt, UBool &isGregorian, UErrorCode& status) {
2032 if(U_FAILURE(status)) return 0.0;
2033
2034 adopt->clear();
2035 adopt->set(UCAL_EXTENDED_YEAR, adopt->getActualMinimum(UCAL_EXTENDED_YEAR, status));
2036 UDate ret = adopt->getTime(status);
2037 isGregorian = dynamic_cast<GregorianCalendar*>(adopt) != NULL;
2038 delete adopt;
2039 return ret;
2040 }
2041
minDateOfCalendar(const Locale & locale,UBool & isGregorian,UErrorCode & status)2042 UDate CalendarTest::minDateOfCalendar(const Locale& locale, UBool &isGregorian, UErrorCode& status) {
2043 if(U_FAILURE(status)) return 0.0;
2044 return doMinDateOfCalendar(Calendar::createInstance(locale, status), isGregorian, status);
2045 }
2046
minDateOfCalendar(const Calendar & cal,UBool & isGregorian,UErrorCode & status)2047 UDate CalendarTest::minDateOfCalendar(const Calendar& cal, UBool &isGregorian, UErrorCode& status) {
2048 if(U_FAILURE(status)) return 0.0;
2049 return doMinDateOfCalendar(cal.clone(), isGregorian, status);
2050 }
2051
Test6703()2052 void CalendarTest::Test6703()
2053 {
2054 UErrorCode status = U_ZERO_ERROR;
2055 Calendar *cal;
2056
2057 Locale loc1("en@calendar=fubar");
2058 cal = Calendar::createInstance(loc1, status);
2059 if (failure(status, "Calendar::createInstance", TRUE)) return;
2060 delete cal;
2061
2062 status = U_ZERO_ERROR;
2063 Locale loc2("en");
2064 cal = Calendar::createInstance(loc2, status);
2065 if (failure(status, "Calendar::createInstance")) return;
2066 delete cal;
2067
2068 status = U_ZERO_ERROR;
2069 Locale loc3("en@calendar=roc");
2070 cal = Calendar::createInstance(loc3, status);
2071 if (failure(status, "Calendar::createInstance")) return;
2072 delete cal;
2073
2074 return;
2075 }
2076
Test3785()2077 void CalendarTest::Test3785()
2078 {
2079 UErrorCode status = U_ZERO_ERROR;
2080 UnicodeString uzone = UNICODE_STRING_SIMPLE("Europe/Paris");
2081 UnicodeString exp1 = UNICODE_STRING_SIMPLE("Mon 30 Jumada II 1433 AH, 01:47:03");
2082 UnicodeString exp2 = UNICODE_STRING_SIMPLE("Mon 1 Rajab 1433 AH, 01:47:04");
2083
2084 LocalUDateFormatPointer df(udat_open(UDAT_NONE, UDAT_NONE, "en@calendar=islamic", uzone.getTerminatedBuffer(),
2085 uzone.length(), NULL, 0, &status));
2086 if (df.isNull() || U_FAILURE(status)) return;
2087
2088 UChar upattern[64];
2089 u_uastrcpy(upattern, "EEE d MMMM y G, HH:mm:ss");
2090 udat_applyPattern(df.getAlias(), FALSE, upattern, u_strlen(upattern));
2091
2092 UChar ubuffer[1024];
2093 UDate ud0 = 1337557623000.0;
2094
2095 status = U_ZERO_ERROR;
2096 udat_format(df.getAlias(), ud0, ubuffer, 1024, NULL, &status);
2097 if (U_FAILURE(status)) {
2098 errln("Error formatting date 1\n");
2099 return;
2100 }
2101 //printf("formatted: '%s'\n", mkcstr(ubuffer));
2102
2103 UnicodeString act1(ubuffer);
2104 if ( act1 != exp1 ) {
2105 errln("Unexpected result from date 1 format\n");
2106 }
2107 ud0 += 1000.0; // add one second
2108
2109 status = U_ZERO_ERROR;
2110 udat_format(df.getAlias(), ud0, ubuffer, 1024, NULL, &status);
2111 if (U_FAILURE(status)) {
2112 errln("Error formatting date 2\n");
2113 return;
2114 }
2115 //printf("formatted: '%s'\n", mkcstr(ubuffer));
2116 UnicodeString act2(ubuffer);
2117 if ( act2 != exp2 ) {
2118 errln("Unexpected result from date 2 format\n");
2119 }
2120
2121 return;
2122 }
2123
Test1624()2124 void CalendarTest::Test1624() {
2125 UErrorCode status = U_ZERO_ERROR;
2126 Locale loc("he_IL@calendar=hebrew");
2127 HebrewCalendar hc(loc,status);
2128
2129 for (int32_t year = 5600; year < 5800; year++ ) {
2130
2131 for (int32_t month = HebrewCalendar::TISHRI; month <= HebrewCalendar::ELUL; month++) {
2132 // skip the adar 1 month if year is not a leap year
2133 if (HebrewCalendar::isLeapYear(year) == FALSE && month == HebrewCalendar::ADAR_1) {
2134 continue;
2135 }
2136 int32_t day = 15;
2137 hc.set(year,month,day);
2138 int32_t dayHC = hc.get(UCAL_DATE,status);
2139 int32_t monthHC = hc.get(UCAL_MONTH,status);
2140 int32_t yearHC = hc.get(UCAL_YEAR,status);
2141
2142 if (failure(status, "HebrewCalendar.get()", TRUE)) continue;
2143
2144 if (dayHC != day) {
2145 errln(" ==> day %d incorrect, should be: %d\n",dayHC,day);
2146 break;
2147 }
2148 if (monthHC != month) {
2149 errln(" ==> month %d incorrect, should be: %d\n",monthHC,month);
2150 break;
2151 }
2152 if (yearHC != year) {
2153 errln(" ==> day %d incorrect, should be: %d\n",yearHC,year);
2154 break;
2155 }
2156 }
2157 }
2158 return;
2159 }
2160
2161 #endif /* #if !UCONFIG_NO_FORMATTING */
2162
2163 //eof
2164