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 "calregts.h"
12
13 #include "unicode/gregocal.h"
14 #include "unicode/simpletz.h"
15 #include "unicode/smpdtfmt.h"
16 #include "unicode/strenum.h"
17 #include "cmemory.h"
18 #include "caltest.h"
19
20 #include <float.h>
21
22 // *****************************************************************************
23 // class CalendarRegressionTest
24 // *****************************************************************************
25
26 // these numbers correspond to using LONG_MIN and LONG_MAX in Java
27 // this is 2^52 - 1, the largest allowable mantissa with a 0 exponent in a 64-bit double
28 const UDate CalendarRegressionTest::EARLIEST_SUPPORTED_MILLIS = - 4503599627370495.0;
29 const UDate CalendarRegressionTest::LATEST_SUPPORTED_MILLIS = 4503599627370495.0;
30
31 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
32
33 void
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)34 CalendarRegressionTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
35 {
36 // if (exec) logln((UnicodeString)"TestSuite NumberFormatRegressionTest");
37 switch (index) {
38 CASE(0,test4100311);
39 CASE(1,test4074758);
40 CASE(2,test4028518);
41 CASE(3,test4031502);
42 CASE(4,test4035301);
43 CASE(5,test4040996);
44 CASE(6,test4051765);
45 CASE(7,test4061476);
46 CASE(8,test4070502);
47 CASE(9,test4071197);
48 CASE(10,test4071385);
49 CASE(11,test4073929);
50 CASE(12,test4083167);
51 CASE(13,test4086724);
52 CASE(14,test4095407);
53 CASE(15,test4096231);
54 CASE(16,test4096539);
55 CASE(17,test41003112);
56 CASE(18,test4103271);
57 CASE(19,test4106136);
58 CASE(20,test4108764);
59 CASE(21,test4114578);
60 CASE(22,test4118384);
61 CASE(23,test4125881);
62 CASE(24,test4125892);
63 CASE(25,test4141665);
64 CASE(26,test4142933);
65 CASE(27,test4145158);
66 CASE(28,test4145983);
67 CASE(29,test4147269);
68
69 CASE(30,Test4149677);
70 CASE(31,Test4162587);
71 CASE(32,Test4165343);
72 CASE(33,Test4166109);
73 CASE(34,Test4167060);
74 CASE(35,Test4197699);
75 CASE(36,TestJ81);
76 CASE(37,TestJ438);
77 CASE(38,TestLeapFieldDifference);
78 CASE(39,TestMalaysianInstance);
79 CASE(40,test4059654);
80 CASE(41,test4092362);
81 CASE(42,TestWeekShift);
82 CASE(43,TestTimeZoneTransitionAdd);
83 CASE(44,TestDeprecates);
84 CASE(45,TestT5555);
85 CASE(46,TestT6745);
86 default: name = ""; break;
87 }
88 }
89
90 const char* CalendarRegressionTest::FIELD_NAME [] = {
91 "ERA",
92 "YEAR",
93 "MONTH",
94 "WEEK_OF_YEAR",
95 "WEEK_OF_MONTH",
96 "DAY_OF_MONTH",
97 "DAY_OF_YEAR",
98 "DAY_OF_WEEK",
99 "DAY_OF_WEEK_IN_MONTH",
100 "AM_PM",
101 "HOUR",
102 "HOUR_OF_DAY",
103 "MINUTE",
104 "SECOND",
105 "MILLISECOND",
106 "ZONE_OFFSET",
107 "DST_OFFSET",
108 "YEAR_WOY",
109 "DOW_LOCAL"
110 };
111
112 UBool
failure(UErrorCode status,const char * msg)113 CalendarRegressionTest::failure(UErrorCode status, const char* msg)
114 {
115 if(U_FAILURE(status)) {
116 errcheckln(status, UnicodeString("FAIL: ") + msg + " failed, error " + u_errorName(status));
117 return TRUE;
118 }
119
120 return FALSE;
121 }
122
123 /*
124 * bug 4100311
125 */
126 void
test4100311()127 CalendarRegressionTest::test4100311()
128 {
129 UErrorCode status = U_ZERO_ERROR;
130 GregorianCalendar *cal = (GregorianCalendar*)Calendar::createInstance(status);
131 if(U_FAILURE(status)) {
132 dataerrln("Error creating Calendar: %s", u_errorName(status));
133 delete cal;
134 return;
135 }
136 failure(status, "Calendar::createInstance(status)");
137 cal->set(UCAL_YEAR, 1997);
138 cal->set(UCAL_DAY_OF_YEAR, 1);
139 UDate d = cal->getTime(status); // Should be Jan 1
140 failure(status, "cal->getTime");
141 logln(UnicodeString("") + d);
142 delete cal;
143 }
144
145
146 /**
147 * @bug 4074758
148 */
149 void
test4074758()150 CalendarRegressionTest::test4074758()
151 { //Set system time to between 12-1 (am or pm) and then run
152 UErrorCode status = U_ZERO_ERROR;
153 GregorianCalendar *cal = new GregorianCalendar(status);
154 if(U_FAILURE(status)) {
155 dataerrln("Error creating Calendar: %s", u_errorName(status));
156 delete cal;
157 return;
158 }
159 failure(status, "new GregorianCalendar");
160 for (int32_t h=0; h<25; ++h) {
161 cal->set(97, UCAL_JANUARY, 1, h, 34);
162 //System.out.print(d);
163 logln(UnicodeString("HOUR=") + cal->get(UCAL_HOUR, status)); //prints 0
164 failure(status, "cal->get");
165 logln(UnicodeString("HOUR_OF_DAY=") + cal->get(UCAL_HOUR_OF_DAY, status));
166 failure(status, "cal->get");
167 }
168
169 delete cal;
170 }
171
172 void
test4028518()173 CalendarRegressionTest::test4028518()
174 {
175 UErrorCode status = U_ZERO_ERROR;
176 GregorianCalendar *cal1 = new GregorianCalendar(status) ;
177 if(U_FAILURE(status)) {
178 dataerrln("Error creating Calendar: %s", u_errorName(status));
179 delete cal1;
180 return;
181 }
182 failure(status, "new GregorianCalendar");
183 GregorianCalendar *cal2 = (GregorianCalendar*) cal1->clone() ;
184
185 printdate(cal1, "cal1: ") ;
186 printdate(cal2, "cal2 - cloned(): ") ;
187 cal1->add(UCAL_DATE, 1, status) ;
188 failure(status, "cal1->add");
189 printdate(cal1, "cal1 after adding 1 day:") ;
190 printdate(cal2, "cal2 should be unmodified:") ;
191 delete cal1;
192 delete cal2;
193 }
194
195 void
printdate(GregorianCalendar * cal,const char * string)196 CalendarRegressionTest::printdate(GregorianCalendar *cal, const char *string)
197 {
198 UErrorCode status = U_ZERO_ERROR;
199 logln(UnicodeString(string, ""));
200 log(UnicodeString("") + cal->get(UCAL_MONTH, status)) ;
201 failure(status, "cal->get");
202 int32_t date = cal->get(UCAL_DATE, status) + 1 ;
203 failure(status, "cal->get");
204 log(UnicodeString("/") + date) ;
205 logln(UnicodeString("/") + cal->get(UCAL_YEAR, status)) ;
206 failure(status, "cal->get");
207 }
208
209 /**
210 * @bug 4031502
211 */
212 void
test4031502()213 CalendarRegressionTest::test4031502()
214 {
215 // This bug actually occurs on Windows NT as well, and doesn't
216 // require the host zone to be set; it can be set in Java.
217 UErrorCode status = U_ZERO_ERROR;
218 StringEnumeration* ids = TimeZone::createEnumeration();
219 UBool bad = FALSE;
220 TimeZone* tz =TimeZone::createTimeZone("Asia/Riyadh87");
221 failure(status, "new TimeZone");
222 GregorianCalendar *cl = new GregorianCalendar(tz, status);
223 if (U_FAILURE(status)) {
224 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
225 delete tz;
226 return;
227 }
228 cl->clear();
229 cl->set(1900, 15, 5, 5, 8, 13);
230 cl->get(UCAL_HOUR, status);
231 failure(status, "cl->get(UCAL_HOUR, status)");
232 status = U_ZERO_ERROR;
233 delete cl;
234 for (int32_t i=0; i<ids->count(status); ++i) {
235 TimeZone *zone = TimeZone::createTimeZone(*ids->snext(status));
236 GregorianCalendar *cal = new GregorianCalendar(zone, status);
237 failure(status, "new GregorianCalendar");
238 cal->clear();
239 cal->set(1900, 15, 5, 5, 8, 13);
240 if (cal->get(UCAL_HOUR, status) != 5 || U_FAILURE(status)) {
241 UnicodeString temp;
242 logln(zone->getID(temp) + " " +
243 //zone.useDaylightTime() + " " +
244 cal->get(UCAL_DST_OFFSET,status) / (60*60*1000) + " " +
245 zone->getRawOffset() / (60*60*1000) +
246 ": HOUR = " + cal->get(UCAL_HOUR,status));
247 bad = TRUE;
248 }
249 delete cal;
250 }
251 if (bad)
252 errln("TimeZone problems with GC");
253 // delete [] ids; // TODO: bad APIs
254 delete ids;
255 }
256
257 /**
258 * @bug 4035301
259 */
test4035301()260 void CalendarRegressionTest::test4035301()
261 {
262 UErrorCode status = U_ZERO_ERROR;
263 GregorianCalendar *c = new GregorianCalendar(98, 8, 7,status);
264 GregorianCalendar *d = new GregorianCalendar(98, 8, 7,status);
265 if (c->after(*d,status) ||
266 c->after(*c,status) ||
267 c->before(*d,status) ||
268 c->before(*c,status) ||
269 *c != *c ||
270 *c != *d)
271 dataerrln("Fail");
272 delete c;
273 delete d;
274 }
275
276 /**
277 * @bug 4040996
278 */
test4040996()279 void CalendarRegressionTest::test4040996()
280 {
281 int32_t count = 0;
282 StringEnumeration* ids = TimeZone::createEnumeration(-8 * 60 * 60 * 1000);
283 UErrorCode status = U_ZERO_ERROR;
284 count = ids->count(status);
285 SimpleTimeZone *pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, *ids->snext(status));
286 pdt->setStartRule(UCAL_APRIL, 1, UCAL_SUNDAY, 2 * 60 * 60 * 1000, status);
287 pdt->setEndRule(UCAL_OCTOBER, -1, UCAL_SUNDAY, 2 * 60 * 60 * 1000, status);
288 Calendar *calendar = new GregorianCalendar(pdt, status);
289 if (U_FAILURE(status)) {
290 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
291 return;
292 }
293 calendar->set(UCAL_MONTH,3);
294 calendar->set(UCAL_DATE,18);
295 calendar->set(UCAL_SECOND, 30);
296
297 logln(UnicodeString("MONTH: ") + calendar->get(UCAL_MONTH, status));
298 logln(UnicodeString("DAY_OF_MONTH: ") +
299 calendar->get(UCAL_DATE, status));
300 logln(UnicodeString("MINUTE: ") + calendar->get(UCAL_MINUTE, status));
301 logln(UnicodeString("SECOND: ") + calendar->get(UCAL_SECOND, status));
302
303 calendar->add(UCAL_SECOND,6, status);
304 //This will print out todays date for MONTH and DAY_OF_MONTH
305 //instead of the date it was set to.
306 //This happens when adding MILLISECOND or MINUTE also
307 logln(UnicodeString("MONTH: ") + calendar->get(UCAL_MONTH, status));
308 logln(UnicodeString("DAY_OF_MONTH: ") +
309 calendar->get(UCAL_DATE, status));
310 logln(UnicodeString("MINUTE: ") + calendar->get(UCAL_MINUTE, status));
311 logln(UnicodeString("SECOND: ") + calendar->get(UCAL_SECOND, status));
312 if (calendar->get(UCAL_MONTH, status) != 3 ||
313 calendar->get(UCAL_DATE, status) != 18 ||
314 calendar->get(UCAL_SECOND, status) != 36)
315 errln(UnicodeString("Fail: Calendar::add misbehaves"));
316
317 delete calendar;
318 delete ids;
319 // delete ids; // TODO: BAD API
320 }
321
322 /**
323 * @bug 4051765
324 */
test4051765()325 void CalendarRegressionTest::test4051765()
326 {
327 UErrorCode status = U_ZERO_ERROR;
328 Calendar *cal = Calendar::createInstance(status);
329 if(U_FAILURE(status)) {
330 dataerrln("Error creating Calendar: %s", u_errorName(status));
331 delete cal;
332 return;
333 }
334 cal->setLenient(FALSE);
335 cal->set(UCAL_DAY_OF_WEEK, 0);
336 //try {
337 cal->getTime(status);
338 if( ! U_FAILURE(status))
339 errln("Fail: DAY_OF_WEEK 0 should be disallowed");
340 /*}
341 catch (IllegalArgumentException e) {
342 return;
343 }*/
344
345 delete cal;
346 }
347
348 /* User error - no bug here
349 void CalendarRegressionTest::test4059524() {
350 // Create calendar for April 10, 1997
351 GregorianCalendar calendar = new GregorianCalendar(status);
352 // print out a bunch of interesting things
353 logln("ERA: " + Calendar::get(Calendar::ERA));
354 logln("YEAR: " + Calendar::get(Calendar::YEAR));
355 logln("MONTH: " + Calendar::get(Calendar::MONTH));
356 logln("WEEK_OF_YEAR: " +
357 Calendar::get(Calendar::WEEK_OF_YEAR));
358 logln("WEEK_OF_MONTH: " +
359 Calendar::get(Calendar::WEEK_OF_MONTH));
360 logln("DATE: " + Calendar::get(Calendar::DATE));
361 logln("DAY_OF_MONTH: " +
362 Calendar::get(Calendar::DAY_OF_MONTH));
363 logln("DAY_OF_YEAR: " + Calendar::get(Calendar::DAY_OF_YEAR));
364 logln("DAY_OF_WEEK: " + Calendar::get(Calendar::DAY_OF_WEEK));
365 logln("DAY_OF_WEEK_IN_MONTH: " +
366 Calendar::get(Calendar::DAY_OF_WEEK_IN_MONTH));
367 logln("AM_PM: " + Calendar::get(Calendar::AM_PM));
368 logln("HOUR: " + Calendar::get(Calendar::HOUR));
369 logln("HOUR_OF_DAY: " + Calendar::get(Calendar::HOUR_OF_DAY));
370 logln("MINUTE: " + Calendar::get(Calendar::MINUTE));
371 logln("SECOND: " + Calendar::get(Calendar::SECOND));
372 logln("MILLISECOND: " + Calendar::get(Calendar::MILLISECOND));
373 logln("ZONE_OFFSET: "
374 + (Calendar::get(Calendar::ZONE_OFFSET)/(60*60*1000)));
375 logln("DST_OFFSET: "
376 + (Calendar::get(Calendar::DST_OFFSET)/(60*60*1000)));
377 calendar = new GregorianCalendar(1997,3,10);
378 Calendar::getTime();
379 logln("April 10, 1997");
380 logln("ERA: " + Calendar::get(Calendar::ERA));
381 logln("YEAR: " + Calendar::get(Calendar::YEAR));
382 logln("MONTH: " + Calendar::get(Calendar::MONTH));
383 logln("WEEK_OF_YEAR: " +
384 Calendar::get(Calendar::WEEK_OF_YEAR));
385 logln("WEEK_OF_MONTH: " +
386 Calendar::get(Calendar::WEEK_OF_MONTH));
387 logln("DATE: " + Calendar::get(Calendar::DATE));
388 logln("DAY_OF_MONTH: " +
389 Calendar::get(Calendar::DAY_OF_MONTH));
390 logln("DAY_OF_YEAR: " + Calendar::get(Calendar::DAY_OF_YEAR));
391 logln("DAY_OF_WEEK: " + Calendar::get(Calendar::DAY_OF_WEEK));
392 logln("DAY_OF_WEEK_IN_MONTH: " + Calendar::get(Calendar::DAY_OF_WEEK_IN_MONTH));
393 logln("AM_PM: " + Calendar::get(Calendar::AM_PM));
394 logln("HOUR: " + Calendar::get(Calendar::HOUR));
395 logln("HOUR_OF_DAY: " + Calendar::get(Calendar::HOUR_OF_DAY));
396 logln("MINUTE: " + Calendar::get(Calendar::MINUTE));
397 logln("SECOND: " + Calendar::get(Calendar::SECOND));
398 logln("MILLISECOND: " + Calendar::get(Calendar::MILLISECOND));
399 logln("ZONE_OFFSET: "
400 + (Calendar::get(Calendar::ZONE_OFFSET)/(60*60*1000))); // in hours
401 logln("DST_OFFSET: "
402 + (Calendar::get(Calendar::DST_OFFSET)/(60*60*1000))); // in hours
403 }
404 */
405
406 /**
407 * @bug 4059654
408 */
test4059654()409 void CalendarRegressionTest::test4059654() {
410 UErrorCode status = U_ZERO_ERROR;
411 GregorianCalendar *gc = new GregorianCalendar(status);
412 if(U_FAILURE(status)) {
413 dataerrln("Error creating Calendar: %s", u_errorName(status));
414 delete gc;
415 return;
416 }
417
418 gc->set(1997, 3, 1, 15, 16, 17); // April 1, 1997
419
420 gc->set(UCAL_HOUR, 0);
421 gc->set(UCAL_AM_PM, UCAL_AM);
422 gc->set(UCAL_MINUTE, 0);
423 gc->set(UCAL_SECOND, 0);
424 gc->set(UCAL_MILLISECOND, 0);
425
426 UDate cd = gc->getTime(status);
427 GregorianCalendar *exp = new GregorianCalendar(1997, 3, 1, 0, 0, 0, status);
428 if (cd != exp->getTime(status))
429 errln(UnicodeString("Fail: Calendar::set broken. Got ") + cd + " Want " + exp->getTime(status));
430
431 delete gc;
432 delete exp;
433 }
434
435 /**
436 * @bug 4061476
437 */
test4061476()438 void CalendarRegressionTest::test4061476()
439 {
440 UErrorCode status = U_ZERO_ERROR;
441 SimpleDateFormat *fmt = new SimpleDateFormat(UnicodeString("ddMMMyy"), Locale::getUK(),status);
442 Calendar *cal = Calendar::createInstance(TimeZone::createTimeZone("GMT"),
443 Locale::getUK(),status);
444 if(U_FAILURE(status)) {
445 dataerrln("Error creating Calendar: %s", u_errorName(status));
446 delete cal;
447 delete fmt;
448 return;
449 }
450 fmt->adoptCalendar(cal);
451 // try {
452 UDate date = fmt->parse("29MAY97", status);
453 failure(status, "fmt->parse");
454 cal->setTime(date, status);
455 failure(status, "cal->setTime");
456 // }
457 //catch (Exception e) {;}
458 cal->set(UCAL_HOUR_OF_DAY, 13);
459 logln(UnicodeString("Hour: ")+cal->get(UCAL_HOUR_OF_DAY, status));
460 cal->add(UCAL_HOUR_OF_DAY, 6,status);
461 logln(UnicodeString("Hour: ")+cal->get(UCAL_HOUR_OF_DAY, status));
462 if (cal->get(UCAL_HOUR_OF_DAY, status) != 19)
463 errln(UnicodeString("Fail: Want 19 Got ") + cal->get(UCAL_HOUR_OF_DAY, status));
464
465 delete fmt;
466 }
467
468 /**
469 * @bug 4070502
470 */
test4070502()471 void CalendarRegressionTest::test4070502()
472 {
473 UErrorCode status = U_ZERO_ERROR;
474 Calendar *cal = new GregorianCalendar(status);
475 if(status == U_USING_FALLBACK_WARNING || U_FAILURE(status)) {
476 dataerrln("Error creating Calendar: %s", u_errorName(status));
477 delete cal;
478 return;
479 }
480 UDate d = getAssociatedDate(makeDate(1998,0,30), status);
481 cal->setTime(d,status);
482 if (cal->get(UCAL_DAY_OF_WEEK,status) == UCAL_SATURDAY ||
483 cal->get(UCAL_DAY_OF_WEEK,status) == UCAL_SUNDAY)
484 errln(UnicodeString("Fail: Want weekday Got ") + d);
485
486 delete cal;
487 }
488
489 /**
490 * Get the associated date starting from a specified date
491 * NOTE: the unnecessary "getTime()'s" below are a work-around for a
492 * bug in jdk 1.1.3 (and probably earlier versions also)
493 * <p>
494 * @param date The date to start from
495 */
496 UDate
getAssociatedDate(UDate d,UErrorCode & status)497 CalendarRegressionTest::getAssociatedDate(UDate d, UErrorCode& status)
498 {
499 GregorianCalendar *cal = new GregorianCalendar(status);
500 cal->setTime(d,status);
501 //cal.add(field, amount); //<-- PROBLEM SEEN WITH field = DATE,MONTH
502 // cal.getTime(); // <--- REMOVE THIS TO SEE BUG
503 for (;;) {
504 int32_t wd = cal->get(UCAL_DAY_OF_WEEK, status);
505 if (wd == UCAL_SATURDAY || wd == UCAL_SUNDAY) {
506 cal->add(UCAL_DATE, 1, status);
507 // cal.getTime();
508 }
509 else
510 break;
511 }
512
513 UDate dd = cal->getTime(status);
514 delete cal;
515 return dd;
516 }
517
518 /**
519 * @bug 4071197
520 */
test4071197()521 void CalendarRegressionTest::test4071197()
522 {
523 dowTest(FALSE);
524 dowTest(TRUE);
525 }
526
dowTest(UBool lenient)527 void CalendarRegressionTest::dowTest(UBool lenient)
528 {
529 UErrorCode status = U_ZERO_ERROR;
530 GregorianCalendar *cal = new GregorianCalendar(status);
531 if(U_FAILURE(status)) {
532 dataerrln("Error creating Calendar: %s", u_errorName(status));
533 delete cal;
534 return;
535 }
536 cal->set(1997, UCAL_AUGUST, 12); // Wednesday
537 // cal.getTime(); // Force update
538 cal->setLenient(lenient);
539 cal->set(1996, UCAL_DECEMBER, 1); // Set the date to be December 1, 1996
540 int32_t dow = cal->get(UCAL_DAY_OF_WEEK, status);
541 int32_t min = cal->getMinimum(UCAL_DAY_OF_WEEK);
542 int32_t max = cal->getMaximum(UCAL_DAY_OF_WEEK);
543 //logln(cal.getTime().toString());
544 if (min != UCAL_SUNDAY || max != UCAL_SATURDAY)
545 errln("FAIL: Min/max bad");
546 if (dow < min || dow > max)
547 errln("FAIL: Day of week %d out of range [%d,%d]\n", dow, min, max);
548 if (dow != UCAL_SUNDAY)
549 errln("FAIL: Day of week should be SUNDAY Got " + dow);
550
551 if(U_FAILURE(status)) {
552 errln("Error checking Calendar: %s", u_errorName(status));
553 delete cal;
554 return;
555 }
556
557 if(cal->getActualMinimum(UCAL_DAY_OF_WEEK, status) != min) {
558 errln("FAIL: actual minimum differs from minimum");
559 }
560 if(cal->getActualMinimum(Calendar::DAY_OF_WEEK, status) != min) {
561 errln("FAIL: actual minimum (Calendar::DAY_OF_WEEK, status) differs from minimum");
562 }
563 if(cal->getActualMinimum(Calendar::DAY_OF_WEEK) != min) {
564 errln("FAIL: actual minimum (Calendar::DAY_OF_WEEK) differs from minimum");
565 }
566 if(((Calendar*)cal)->getActualMinimum(UCAL_DAY_OF_WEEK, status) != min) {
567 errln("FAIL: actual minimum (UCAL_DAY_OF_WEEK, status) differs from minimum");
568 }
569 // NOTE: This function does not exist! jitterbug #3016
570 // if(((Calendar*)cal)->getActualMinimum(Calendar::DAY_OF_WEEK, status) != min) {
571 // errln("FAIL: actual minimum (Calendar::DAY_OF_WEEK, status) differs from minimum");
572 // }
573 if(U_FAILURE(status)) {
574 errln("Error getting actual minimum: %s", u_errorName(status));
575 return;
576 }
577
578 delete cal;
579 }
580
581 /**
582 * @bug 4071385
583 */
test4071385()584 void CalendarRegressionTest::test4071385()
585 {
586 UErrorCode status = U_ZERO_ERROR;
587 Calendar *cal = Calendar::createInstance(status);
588 if(U_FAILURE(status)) {
589 dataerrln("Error creating Calendar: %s", u_errorName(status));
590 delete cal;
591 return;
592 }
593 cal->setTime(makeDate(1998, UCAL_JUNE, 24),status);
594 cal->set(UCAL_MONTH, UCAL_NOVEMBER); // change a field
595 //logln(cal.getTime().toString());
596 if (cal->getTime(status) != makeDate(1998, UCAL_NOVEMBER, 24))
597 errln("Fail");
598
599 delete cal;
600 }
601
602 /**
603 * @bug 4073929
604 */
test4073929()605 void CalendarRegressionTest::test4073929()
606 {
607 UErrorCode status = U_ZERO_ERROR;
608 GregorianCalendar *foo1 = new GregorianCalendar(1997, 8, 27,status);
609 if(U_FAILURE(status)) {
610 dataerrln("Error creating Calendar: %s", u_errorName(status));
611 delete foo1;
612 return;
613 }
614 logln("foo1@%.0f - %d-%d-%d %d:%d:%d.%ds\n", foo1->getTime(status),
615 foo1->get(UCAL_YEAR, status),
616 foo1->get(UCAL_MONTH, status),
617 foo1->get(UCAL_DATE, status),
618 foo1->get(UCAL_HOUR, status),
619 foo1->get(UCAL_MINUTE, status),
620 foo1->get(UCAL_SECOND, status),
621 foo1->get(UCAL_MILLISECOND,status));
622 foo1->add(UCAL_DATE, + 1, status);
623 logln("foo1@%.0f - %d-%d-%d %d:%d:%d.%ds after +\n", foo1->getTime(status),
624 foo1->get(UCAL_YEAR, status),
625 foo1->get(UCAL_MONTH, status),
626 foo1->get(UCAL_DATE, status),
627 foo1->get(UCAL_HOUR, status),
628 foo1->get(UCAL_MINUTE, status),
629 foo1->get(UCAL_SECOND, status),
630 foo1->get(UCAL_MILLISECOND ,status));
631 foo1->add(UCAL_DATE, - 1, status);
632 logln("foo1@%.0f - %d-%d-%d %d:%d:%d.%ds after -\n", foo1->getTime(status),
633 foo1->get(UCAL_YEAR, status),
634 foo1->get(UCAL_MONTH, status),
635 foo1->get(UCAL_DATE, status),
636 foo1->get(UCAL_HOUR, status),
637 foo1->get(UCAL_MINUTE, status),
638 foo1->get(UCAL_SECOND, status),
639 foo1->get(UCAL_MILLISECOND, status));
640
641 foo1->add(UCAL_DATE, + 1, status);
642 int32_t testyear = foo1->get(UCAL_YEAR, status);
643 int32_t testmonth = foo1->get(UCAL_MONTH, status);
644 int32_t testday = foo1->get(UCAL_DATE, status);
645 if (testyear != 1997 ||
646 testmonth != 8 ||
647 testday != 28)
648 errln("Fail: Calendar not initialized");
649
650 delete foo1;
651 }
652
653 /**
654 * @bug 4083167
655 */
test4083167()656 void CalendarRegressionTest::test4083167()
657 {
658 UErrorCode status = U_ZERO_ERROR;
659 TimeZone *saveZone = TimeZone::createDefault();
660 //try {
661 TimeZone *newZone = TimeZone::createTimeZone("UTC");
662 TimeZone::setDefault(*newZone);
663 UDate firstDate = Calendar::getNow();
664 Calendar *cal = new GregorianCalendar(status);
665 if(U_FAILURE(status)) {
666 dataerrln("Error creating Calendar: %s", u_errorName(status));
667 delete cal;
668 return;
669 }
670 cal->setTime(firstDate,status);
671 int32_t hr = cal->get(UCAL_HOUR_OF_DAY, status);
672 int32_t min = cal->get(UCAL_MINUTE, status);
673 int32_t sec = cal->get(UCAL_SECOND, status);
674 int32_t msec = cal->get(UCAL_MILLISECOND, status);
675 double firstMillisInDay = hr * 3600000 + min * 60000 + sec * 1000 + msec;
676
677 //logln("Current time: " + firstDate.toString());
678
679 for (int32_t validity=0; validity<30; validity++) {
680 UDate lastDate = firstDate + validity*1000*24*60*60.0;
681 cal->setTime(lastDate, status);
682 hr = cal->get(UCAL_HOUR_OF_DAY, status);
683 min = cal->get(UCAL_MINUTE, status);
684 sec = cal->get(UCAL_SECOND, status);
685 msec = cal->get(UCAL_MILLISECOND, status);
686 double millisInDay = hr * 3600000.0 + min * 60000.0 + sec * 1000.0 + msec;
687 if (firstMillisInDay != millisInDay)
688 errln(UnicodeString("Day has shifted ") + lastDate);
689 }
690 //}
691 //finally {
692 TimeZone::setDefault(*saveZone);
693 //}
694
695 delete saveZone;
696 delete newZone;
697 delete cal;
698 }
699
700 /**
701 * @bug 4086724
702 */
test4086724()703 void CalendarRegressionTest::test4086724()
704 {
705 UErrorCode status = U_ZERO_ERROR;
706 SimpleDateFormat *date;
707 TimeZone *saveZone = TimeZone::createDefault();
708 Locale saveLocale = Locale::getDefault();
709 //try {
710 Locale::setDefault(Locale::getUK(),status);
711 TimeZone *newZone = TimeZone::createTimeZone("GMT");
712 TimeZone::setDefault(*newZone);
713 date = new SimpleDateFormat(UnicodeString("dd MMM yyy (zzzz) 'is in week' ww"),status);
714 Calendar *cal = Calendar::createInstance(status);
715 if(U_FAILURE(status)) {
716 dataerrln("Error creating Calendar: %s", u_errorName(status));
717 delete cal;
718 delete newZone;
719 delete date;
720 return;
721 }
722 cal->set(1997,UCAL_SEPTEMBER,30);
723 UDate now = cal->getTime(status);
724 UnicodeString temp;
725 FieldPosition pos(FieldPosition::DONT_CARE);
726 logln(date->format(now, temp, pos));
727 cal->set(1997,UCAL_JANUARY,1);
728 now=cal->getTime(status);
729 logln(date->format(now,temp, pos));
730 cal->set(1997,UCAL_JANUARY,8);
731 now=cal->getTime(status);
732 logln(date->format(now,temp, pos));
733 cal->set(1996,UCAL_DECEMBER,31);
734 now=cal->getTime(status);
735 logln(date->format(now,temp, pos));
736 //}
737 //finally {
738 Locale::setDefault(saveLocale,status);
739 TimeZone::setDefault(*saveZone);
740 //}
741 logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
742
743 delete newZone;
744 delete cal;
745 delete date;
746 delete saveZone;
747 }
748
749 /**
750 * @bug 4092362
751 */
test4092362()752 void CalendarRegressionTest::test4092362() {
753 UErrorCode status = U_ZERO_ERROR;
754 GregorianCalendar *cal1 = new GregorianCalendar(1997, 10, 11, 10, 20, 40,status);
755 if (U_FAILURE(status)) {
756 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
757 delete cal1;
758 return;
759 }
760 /*cal1.set( Calendar::YEAR, 1997 );
761 cal1.set( Calendar::MONTH, 10 );
762 cal1.set( Calendar::DATE, 11 );
763 cal1.set( Calendar::HOUR, 10 );
764 cal1.set( Calendar::MINUTE, 20 );
765 cal1.set( Calendar::SECOND, 40 ); */
766
767 logln( UnicodeString(" Cal1 = ") + cal1->getTime(status) );
768 logln( UnicodeString(" Cal1 time in ms = ") + cal1->get(UCAL_MILLISECOND,status) );
769 for( int32_t k = 0; k < 100 ; k++ );
770
771 GregorianCalendar *cal2 = new GregorianCalendar(1997, 10, 11, 10, 20, 40,status);
772 /*cal2.set( Calendar::YEAR, 1997 );
773 cal2.set( Calendar::MONTH, 10 );
774 cal2.set( Calendar::DATE, 11 );
775 cal2.set( Calendar::HOUR, 10 );
776 cal2.set( Calendar::MINUTE, 20 );
777 cal2.set( Calendar::SECOND, 40 ); */
778
779 logln( UnicodeString(" Cal2 = ") + cal2->getTime(status) );
780 logln( UnicodeString(" Cal2 time in ms = ") + cal2->get(UCAL_MILLISECOND,status) );
781 if( *cal1 != *cal2 )
782 errln("Fail: Milliseconds randomized");
783
784 delete cal1;
785 delete cal2;
786 }
787
788 /**
789 * @bug 4095407
790 */
test4095407()791 void CalendarRegressionTest::test4095407()
792 {
793 UErrorCode status = U_ZERO_ERROR;
794 GregorianCalendar *a = new GregorianCalendar(1997,UCAL_NOVEMBER, 13,status);
795 if (U_FAILURE(status)) {
796 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
797 delete a;
798 return;
799 }
800 int32_t dow = a->get(UCAL_DAY_OF_WEEK, status);
801 if (dow != UCAL_THURSDAY)
802 errln("Fail: Want THURSDAY Got " + dow);
803
804 delete a;
805 }
806
807 /**
808 * @bug 4096231
809 */
test4096231()810 void CalendarRegressionTest::test4096231()
811 {
812 UErrorCode status = U_ZERO_ERROR;
813 TimeZone *GMT = TimeZone::createTimeZone("GMT");
814 TimeZone *PST = TimeZone::createTimeZone("PST");
815 int32_t sec = 0, min = 0, hr = 0, day = 1, month = 10, year = 1997;
816
817 Calendar *cal1 = new GregorianCalendar(*PST,status);
818 if (U_FAILURE(status)) {
819 dataerrln("Failure new GregorianCalendar: %s", u_errorName(status));
820 delete GMT;
821 delete PST;
822 delete cal1;
823 return;
824 }
825 cal1->setTime(880698639000.0,status);
826 // Issue 1: Changing the timezone doesn't change the
827 // represented time. The old API, pre 1.2.2a requires
828 // setTime to be called in order to update the time fields after the time
829 // zone has been set.
830 int32_t h1,h2;
831 logln(UnicodeString("PST 1 is: ") + (h1=cal1->get(UCAL_HOUR_OF_DAY, status)));
832 cal1->setTimeZone(*GMT);
833 logln(UnicodeString("GMT 2 is: ") + (h2=cal1->get(UCAL_HOUR_OF_DAY, status)));
834 if ((*GMT != *PST) && (h1 == h2))
835 errln("Fail: Hour same in different zones");
836
837 Calendar *cal2 = new GregorianCalendar(*GMT,status);
838 Calendar *cal3 = new GregorianCalendar(*PST,status);
839 cal2->set(UCAL_MILLISECOND, 0);
840 cal3->set(UCAL_MILLISECOND, 0);
841
842 cal2->set(cal1->get(UCAL_YEAR,status),
843 cal1->get(UCAL_MONTH,status),
844 cal1->get(UCAL_DATE,status),
845 cal1->get(UCAL_HOUR_OF_DAY,status),
846 cal1->get(UCAL_MINUTE,status),
847 cal1->get(UCAL_SECOND,status));
848
849 double t1,t2,t3,t4;
850 logln(UnicodeString("RGMT 1 is: ") + (t1=cal2->getTime(status)));
851 cal3->set(year, month, day, hr, min, sec);
852 logln(UnicodeString("RPST 1 is: ") + (t2=cal3->getTime(status)));
853 cal3->setTimeZone(*GMT);
854 logln(UnicodeString("RGMT 2 is: ") + (t3=cal3->getTime(status)));
855 cal3->set(cal1->get(UCAL_YEAR,status),
856 cal1->get(UCAL_MONTH,status),
857 cal1->get(UCAL_DATE,status),
858 cal1->get(UCAL_HOUR_OF_DAY,status),
859 cal1->get(UCAL_MINUTE,status),
860 cal1->get(UCAL_SECOND,status));
861 // Issue 2: Calendar continues to use the timezone in its
862 // constructor for set() conversions, regardless
863 // of calls to setTimeZone()
864 logln(UnicodeString("RGMT 3 is: ") + (t4=cal3->getTime(status)));
865 if (t1 == t2 ||
866 t1 != t4 ||
867 t2 != t3)
868 errln("Fail: Calendar zone behavior faulty");
869
870 delete cal1;
871 delete cal2;
872 delete cal3;
873 delete GMT;
874 delete PST;
875 }
876
877 /**
878 * @bug 4096539
879 */
test4096539()880 void CalendarRegressionTest::test4096539()
881 {
882 UErrorCode status = U_ZERO_ERROR;
883 int32_t y [] = {31,28,31,30,31,30,31,31,30,31,30,31};
884
885 for (int32_t x=0;x<12;x++) {
886 GregorianCalendar *gc = new
887 GregorianCalendar(1997,x,y[x], status);
888 if (U_FAILURE(status)) {
889 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
890 delete gc;
891 return;
892 }
893 int32_t m1,m2;
894 log(UnicodeString("") + (m1=gc->get(UCAL_MONTH,status)+1)+UnicodeString("/")+
895 gc->get(UCAL_DATE,status)+"/"+gc->get(UCAL_YEAR,status)+
896 " + 1mo = ");
897
898 gc->add(UCAL_MONTH, 1,status);
899 logln(UnicodeString("") + (m2=gc->get(UCAL_MONTH,status)+1)+UnicodeString("/")+
900 gc->get(UCAL_DATE,status)+"/"+gc->get(UCAL_YEAR,status)
901 );
902 int32_t m = (m1 % 12) + 1;
903 if (m2 != m)
904 errln(UnicodeString("Fail: Want ") + m + " Got " + m2);
905 delete gc;
906 }
907
908 }
909
910 /**
911 * @bug 4100311
912 */
test41003112()913 void CalendarRegressionTest::test41003112()
914 {
915 UErrorCode status = U_ZERO_ERROR;
916 GregorianCalendar *cal = (GregorianCalendar*)Calendar::createInstance(status);
917 if(U_FAILURE(status)) {
918 dataerrln("Error creating calendar: %s", u_errorName(status));
919 delete cal;
920 return;
921 }
922 cal->set(UCAL_YEAR, 1997);
923 cal->set(UCAL_DAY_OF_YEAR, 1);
924 //UDate d = cal->getTime(status); // Should be Jan 1
925 //logln(d.toString());
926 if (cal->get(UCAL_DAY_OF_YEAR, status) != 1)
927 errln("Fail: DAY_OF_YEAR not set");
928 delete cal;
929 }
930
931 /**
932 * @bug 4103271
933 */
test4103271()934 void CalendarRegressionTest::test4103271()
935 {
936 UErrorCode status = U_ZERO_ERROR;
937 SimpleDateFormat sdf(status);
938 int32_t numYears=40, startYear=1997, numDays=15;
939 UnicodeString output, testDesc, str, str2;
940 GregorianCalendar *testCal = (GregorianCalendar*)Calendar::createInstance(status);
941 if(U_FAILURE(status)) {
942 dataerrln("Error creating calendar: %s", u_errorName(status));
943 delete testCal;
944 return;
945 }
946 testCal->clear();
947 sdf.adoptCalendar(testCal);
948 sdf.applyPattern("EEE dd MMM yyyy 'WOY'ww'-'YYYY 'DOY'DDD");
949 UBool fail = FALSE;
950 for (int32_t firstDay=1; firstDay<=2; firstDay++) {
951 for (int32_t minDays=1; minDays<=7; minDays++) {
952 testCal->setMinimalDaysInFirstWeek((uint8_t)minDays);
953 testCal->setFirstDayOfWeek((UCalendarDaysOfWeek)firstDay);
954 testDesc = (UnicodeString("Test") + firstDay + minDays);
955 logln(testDesc + " => 1st day of week=" +
956 firstDay +
957 ", minimum days in first week=" +
958 minDays);
959 for (int32_t j=startYear; j<=startYear+numYears; j++) {
960 testCal->set(j,11,25);
961 for(int32_t i=0; i<numDays; i++) {
962 testCal->add(UCAL_DATE,1,status);
963 UnicodeString calWOY;
964 int32_t actWOY = testCal->get(UCAL_WEEK_OF_YEAR,status);
965 if (actWOY < 1 || actWOY > 53) {
966 UDate d = testCal->getTime(status);
967 //calWOY = String.valueOf(actWOY);
968 UnicodeString temp;
969 FieldPosition pos(FieldPosition::DONT_CARE);
970 output = testDesc + " - " + sdf.format(d,temp,pos) + "\t";
971 output = output + "\t" + actWOY;
972 logln(output);
973 fail = TRUE;
974 }
975 }
976 }
977 }
978 }
979
980 int32_t DATA [] = {
981 3, 52, 52, 52, 52, 52, 52, 52,
982 1, 1, 1, 1, 1, 1, 1,
983 2, 2, 2, 2, 2, 2, 2,
984 4, 52, 52, 52, 52, 52, 52, 52,
985 53, 53, 53, 53, 53, 53, 53,
986 1, 1, 1, 1, 1, 1, 1,
987 };
988 testCal->setFirstDayOfWeek(UCAL_SUNDAY);
989 for (int32_t j=0; j<44; j+=22) {
990 logln(UnicodeString("Minimal days in first week = ") + DATA[j] +
991 " Week starts on Sunday");
992 testCal->setMinimalDaysInFirstWeek((uint8_t)DATA[j]);
993 testCal->set(1997, UCAL_DECEMBER, 21);
994 for (int32_t i=0; i<21; ++i) {
995 int32_t woy = testCal->get(UCAL_WEEK_OF_YEAR,status);
996 str.remove();
997 log(UnicodeString("") + sdf.format(testCal->getTime(status), str) +
998 UnicodeString(" ") + woy);
999 if (woy != DATA[j + 1 + i]) {
1000 log(" ERROR");
1001 fail = TRUE;
1002 }
1003 logln("");
1004
1005 // Now compute the time from the fields, and make sure we
1006 // get the same answer back. This is a round-trip test.
1007 UDate save = testCal->getTime(status);
1008 testCal->clear();
1009 testCal->set(UCAL_YEAR_WOY, DATA[j+1+i] < 25 ? 1998 : 1997);
1010 testCal->set(UCAL_WEEK_OF_YEAR, DATA[j+1+i]);
1011 testCal->set(UCAL_DAY_OF_WEEK, (i%7) + UCAL_SUNDAY);
1012 if (testCal->getTime(status) != save) {
1013 str.remove();
1014 logln(UnicodeString(" Parse failed: ") +
1015 sdf.format(testCal->getTime(status), str));
1016 fail= TRUE;
1017 }
1018
1019 testCal->setTime(save,status);
1020 testCal->add(UCAL_DATE, 1,status);
1021 }
1022 }
1023 // Test field disambiguation with a few special hard-coded cases.
1024 // This shouldn't fail if the above cases aren't failing.
1025 int32_t DISAM_int [] = {
1026 // y y_woy woy dow
1027 1997, 1998, 1, UCAL_SUNDAY,
1028 (1998), (1998), (2), (UCAL_SATURDAY),
1029 (1998), (1998), (53), (UCAL_THURSDAY),
1030 (1999), (1998), (53), (UCAL_FRIDAY)
1031 };
1032
1033 UDate DISAM_date [] = {
1034 makeDate(1997, UCAL_DECEMBER, 28),
1035 makeDate(1998, UCAL_JANUARY, 10),
1036 makeDate(1998, UCAL_DECEMBER, 31),
1037 makeDate(1999, UCAL_JANUARY, 1)
1038 };
1039
1040 testCal->setMinimalDaysInFirstWeek(3);
1041 testCal->setFirstDayOfWeek(UCAL_SUNDAY);
1042 int32_t i = 0;
1043
1044 /* Enable this code to display various WOY values
1045 testCal->clear();
1046 for (i=25; i<38; ++i) {
1047 testCal->set(1996, Calendar::DECEMBER, i);
1048 UDate got = testCal->getTime(status);
1049 str.remove();
1050 logln(UnicodeString("") + sdf.format(got, str));
1051 }
1052 for (i=25; i<38; ++i) {
1053 testCal->set(1997, Calendar::DECEMBER, i);
1054 UDate got = testCal->getTime(status);
1055 str.remove();
1056 logln(UnicodeString("") + sdf.format(got, str));
1057 }
1058 for (i=25; i<38; ++i) {
1059 testCal->set(1998, UCAL_DECEMBER, i);
1060 UDate got = testCal->getTime(status);
1061 str.remove();
1062 logln(UnicodeString("") + sdf.format(got, str));
1063 }
1064 */
1065
1066 for (i=0; i < 16; i += 4) {
1067 int32_t y = DISAM_int[i];
1068 int32_t ywoy = DISAM_int[i+1];
1069 int32_t woy = DISAM_int[i+2];
1070 int32_t dow = DISAM_int[i+3];
1071 UDate exp = DISAM_date[i/4];
1072 testCal->clear();
1073 testCal->set(UCAL_YEAR, y);
1074 testCal->set(UCAL_WEEK_OF_YEAR, woy);
1075 testCal->set(UCAL_DAY_OF_WEEK, dow);
1076 UDate got = testCal->getTime(status);
1077 str.remove();
1078 str2.remove();
1079 log(UnicodeString("Y") + y + "-W" + woy +
1080 "-DOW" + dow + " expect:" + sdf.format(exp, str) +
1081 " got:" + sdf.format(got, str2));
1082 if (got != exp) {
1083 log(" FAIL (%s:%d, i=%d)", __FILE__, __LINE__, i);
1084 logln(CalendarTest::calToStr(*testCal));
1085 testCal->setTime(exp, status);
1086 logln(CalendarTest::calToStr(*testCal) + UnicodeString( " <<< expected "));
1087 fail = TRUE;
1088 }
1089 logln("");
1090
1091 testCal->clear();
1092 testCal->set(UCAL_YEAR_WOY, ywoy);
1093 testCal->set(UCAL_WEEK_OF_YEAR, woy);
1094 testCal->set(UCAL_DAY_OF_WEEK, dow);
1095 got = testCal->getTime(status);
1096 str.remove();
1097 str2.remove();
1098 log(UnicodeString("YWOY") + ywoy + "-W" + woy +
1099 "-DOW" + dow + " expect:" + sdf.format(exp, str) +
1100 " got:" + sdf.format(got, str2));
1101 if (got != exp) {
1102 log(" FAIL");
1103 fail = TRUE;
1104 }
1105 logln("");
1106 }
1107 // Now try adding and rolling
1108 UDate ADDROLL_date [] = {
1109 makeDate(1998, UCAL_DECEMBER, 25), makeDate(1999, UCAL_JANUARY, 1),
1110 makeDate(1997, UCAL_DECEMBER, 28), makeDate(1998, UCAL_JANUARY, 4),
1111 makeDate(1998, UCAL_DECEMBER, 27), makeDate(1997, UCAL_DECEMBER, 28),
1112 makeDate(1999, UCAL_JANUARY, 2), makeDate(1998, UCAL_JANUARY, 3),
1113 };
1114
1115 int32_t ADDROLL_int []= {
1116 (1),
1117 (1),
1118 (1),
1119 (1)
1120 };
1121
1122
1123 UBool ADDROLL_bool [] = {
1124 TRUE,//ADD,
1125 TRUE,
1126 FALSE,
1127 FALSE
1128 };
1129
1130 testCal->setMinimalDaysInFirstWeek(3);
1131 testCal->setFirstDayOfWeek(UCAL_SUNDAY);
1132 for (i=0; i<8; i += 2) {
1133 int32_t amount = ADDROLL_int[i/2];
1134 UDate before = ADDROLL_date[i];
1135 UDate after = ADDROLL_date[i+1];
1136
1137 testCal->setTime(before,status);
1138 if (ADDROLL_bool[i/2])
1139 testCal->add(UCAL_WEEK_OF_YEAR, amount,status);
1140 else
1141 testCal->roll(UCAL_WEEK_OF_YEAR, amount,status);
1142 UDate got = testCal->getTime(status);
1143 str.remove();
1144 str2.remove();
1145 UnicodeString opTypeStr;
1146 if (ADDROLL_bool[i/2]) {
1147 opTypeStr = UnicodeString("add(WOY,", "");
1148 } else {
1149 opTypeStr = UnicodeString("roll(WOY,", "");
1150 }
1151 log(opTypeStr + amount + ") " + sdf.format(before, str) + " => " +
1152 sdf.format(got, str2));
1153 if (after != got) {
1154 str.remove();
1155 logln(UnicodeString(" exp:") + sdf.format(after, str) + " FAIL");
1156 fail = TRUE;
1157 }
1158 else logln(" ok");
1159
1160 testCal->setTime(after,status);
1161 if (ADDROLL_bool[i/2])
1162 testCal->add(UCAL_WEEK_OF_YEAR, -amount,status);
1163 else
1164 testCal->roll(UCAL_WEEK_OF_YEAR, -amount,status);
1165 got = testCal->getTime(status);
1166 str.remove();
1167 str2.remove();
1168 log(opTypeStr + (-amount) + ") " + sdf.format(after, str) + " => " +
1169 sdf.format(got, str2));
1170 if (before != got) {
1171 str.remove();
1172 logln(UnicodeString(" exp:") + sdf.format(before, str) + " FAIL");
1173 fail = TRUE;
1174 }
1175 else logln(" ok");
1176 }
1177 if (fail)
1178 errln("Fail: Week of year misbehaving");
1179 }
1180
1181 /**
1182 * @bug 4106136
1183 */
test4106136()1184 void CalendarRegressionTest::test4106136()
1185 {
1186 UErrorCode status = U_ZERO_ERROR;
1187 Locale saveLocale = Locale::getDefault();
1188 //try {
1189 Locale locales [] = { Locale::getChinese(), Locale::getChina() };
1190 for (int32_t i=0; i<2; ++i) {
1191 Locale::setDefault(locales[i], status);
1192 failure(status, "Locale::setDefault");
1193 int32_t count1, count2, count3;
1194 Calendar::getAvailableLocales(count1);
1195 DateFormat::getAvailableLocales(count2);
1196 NumberFormat::getAvailableLocales(count3);
1197 int32_t n [] = {
1198 count1, count2, count3
1199 };
1200 for (int32_t j=0; j<3; ++j) {
1201 UnicodeString temp;
1202 if (n[j] == 0)
1203 dataerrln(UnicodeString("Fail: No locales for ") + locales[i].getName());
1204 }
1205 }
1206 //}
1207 //finally {
1208 Locale::setDefault(saveLocale,status);
1209 //}
1210 }
1211
1212 /**
1213 * @bug 4108764
1214 */
test4108764()1215 void CalendarRegressionTest::test4108764()
1216 {
1217 UErrorCode status = U_ZERO_ERROR;
1218 Calendar *cal = Calendar::createInstance(status);
1219 if(U_FAILURE(status)) {
1220 dataerrln("Error creating calendar %s", u_errorName(status));
1221 delete cal;
1222 return;
1223 }
1224 UDate d00 = makeDate(1997, UCAL_MARCH, 15, 12, 00, 00);
1225 UDate d01 = makeDate(1997, UCAL_MARCH, 15, 12, 00, 56);
1226 UDate d10 = makeDate(1997, UCAL_MARCH, 15, 12, 34, 00);
1227 UDate d11 = makeDate(1997, UCAL_MARCH, 15, 12, 34, 56);
1228 UDate epoch = makeDate(1970, UCAL_JANUARY, 1);
1229
1230 cal->setTime(d11,status);
1231
1232 cal->clear( UCAL_MINUTE );
1233 logln(UnicodeString("") + cal->getTime(status));
1234 if (cal->getTime(status) != d01)
1235 errln("Fail: clear(MINUTE) broken");
1236
1237 cal->set( UCAL_SECOND, 0 );
1238 logln(UnicodeString("") + cal->getTime(status));
1239 if (cal->getTime(status) != d00)
1240 errln("Fail: set(SECOND, 0) broken");
1241
1242 cal->setTime(d11,status);
1243 cal->set( UCAL_SECOND, 0 );
1244 logln(UnicodeString("") + cal->getTime(status));
1245 if (cal->getTime(status) != d10)
1246 errln("Fail: set(SECOND, 0) broken #2");
1247
1248 cal->clear( UCAL_MINUTE );
1249 logln(UnicodeString("") + cal->getTime(status));
1250 if (cal->getTime(status) != d00)
1251 errln("Fail: clear(MINUTE) broken #2");
1252
1253 cal->clear();
1254 logln(UnicodeString("") + cal->getTime(status));
1255 if (cal->getTime(status) != epoch)
1256 errln(UnicodeString("Fail: clear() broken Want ") + epoch);
1257
1258 delete cal;
1259 }
1260
1261 /**
1262 * @bug 4114578
1263 */
test4114578()1264 void CalendarRegressionTest::test4114578()
1265 {
1266 UErrorCode status = U_ZERO_ERROR;
1267 double ONE_HOUR = 60*60*1000;
1268 Calendar *cal = Calendar::createInstance(status);
1269 if(U_FAILURE(status)) {
1270 dataerrln("Error creating calendar %s", u_errorName(status));
1271 delete cal;
1272 return;
1273 }
1274 cal->adoptTimeZone(TimeZone::createTimeZone("PST"));
1275 UDate onset = makeDate(1998, UCAL_APRIL, 5, 1, 0) + ONE_HOUR;
1276 UDate cease = makeDate(1998, UCAL_OCTOBER, 25, 0, 0) + 2*ONE_HOUR;
1277
1278 UBool fail = FALSE;
1279
1280 const int32_t ADD = 1;
1281 const int32_t ROLL = 2;
1282
1283 double DATA []= {
1284 // Start Action Amt Expected_change
1285 onset - ONE_HOUR, ADD, 1, ONE_HOUR,
1286 onset, ADD, -1, -ONE_HOUR,
1287 onset - ONE_HOUR, ROLL, 1, ONE_HOUR,
1288 onset, ROLL, -1, -ONE_HOUR,
1289 cease - ONE_HOUR, ADD, 1, ONE_HOUR,
1290 cease, ADD, -1, -ONE_HOUR,
1291 cease - ONE_HOUR, ROLL, 1, ONE_HOUR,
1292 cease, ROLL, -1, -ONE_HOUR,
1293 };
1294
1295 for (int32_t i=0; i<32; i+=4) {
1296 UDate date = DATA[i];
1297 int32_t amt = (int32_t) DATA[i+2];
1298 double expectedChange = DATA[i+3];
1299
1300 log(UnicodeString("") + date);
1301 cal->setTime(date,status);
1302
1303 switch ((int32_t) DATA[i+1]) {
1304 case ADD:
1305 log(UnicodeString(" add (HOUR,") + (amt<0?"":"+")+amt + ")= ");
1306 cal->add(UCAL_HOUR, amt,status);
1307 break;
1308 case ROLL:
1309 log(UnicodeString(" roll(HOUR,") + (amt<0?"":"+")+amt + ")= ");
1310 cal->roll(UCAL_HOUR, amt,status);
1311 break;
1312 }
1313
1314 log(UnicodeString("") + cal->getTime(status));
1315
1316 double change = cal->getTime(status) - date;
1317 if (change != expectedChange) {
1318 fail = TRUE;
1319 logln(" FAIL");
1320 }
1321 else logln(" OK");
1322 }
1323
1324 if (fail) errln("Fail: roll/add misbehaves around DST onset/cease");
1325
1326 delete cal;
1327 }
1328
1329 /**
1330 * @bug 4118384
1331 * Make sure maximum for HOUR field is 11, not 12.
1332 */
test4118384()1333 void CalendarRegressionTest::test4118384()
1334 {
1335 UErrorCode status = U_ZERO_ERROR;
1336 Calendar *cal = Calendar::createInstance(status);
1337 if(U_FAILURE(status)) {
1338 dataerrln("Error creating calendar %s", u_errorName(status));
1339 delete cal;
1340 return;
1341 }
1342 if (cal->getMaximum(UCAL_HOUR) != 11 ||
1343 cal->getLeastMaximum(UCAL_HOUR) != 11 ||
1344 cal->getActualMaximum(UCAL_HOUR,status) != 11)
1345 errln("Fail: maximum of HOUR field should be 11");
1346
1347 // test deprecated functions
1348 if (cal->getLeastMaximum(Calendar::HOUR) != 11 ||
1349 cal->getMaximum(Calendar::HOUR) != 11) {
1350 errln("Fail: [deprecated functions] maximum of HOUR field should be 11\n");
1351 }
1352
1353 if (cal->getGreatestMinimum(Calendar::HOUR) != 0 ||
1354 cal->getMinimum(Calendar::HOUR) != 0) {
1355 errln("Fail: [deprecated functions] minimum of HOUR field should be 1\n");
1356 }
1357
1358 delete cal;
1359 cal = Calendar::createInstance(Locale("th_TH@calendar=buddhist"),status);
1360 // test deprecated functions
1361 if (cal->getLeastMaximum(Calendar::HOUR) != 11 ||
1362 cal->getMaximum(Calendar::HOUR) != 11) {
1363 errln("Fail: Buddhist:[deprecated functions] maximum of HOUR field should be 11\n");
1364 }
1365
1366 if (cal->getGreatestMinimum(Calendar::HOUR) != 0 ||
1367 cal->getMinimum(Calendar::HOUR) != 0) {
1368 errln("Fail: Buddhist:[deprecated functions] minimum of HOUR field should be 1\n");
1369 }
1370
1371 delete cal;
1372 // test deprecated functions
1373 cal = Calendar::createInstance(Locale("ja_JP@calendar=japanese"),status);
1374 if (cal->getLeastMaximum(Calendar::HOUR) != 11 ||
1375 cal->getMaximum(Calendar::HOUR) != 11) {
1376 errln("Fail: Japanese:[deprecated functions] maximum of HOUR field should be 11\n");
1377 }
1378
1379 if (cal->getGreatestMinimum(Calendar::HOUR) != 0 ||
1380 cal->getMinimum(Calendar::HOUR) != 0) {
1381 errln("Fail: Japanese:[deprecated functions] minimum of HOUR field should be 1\n");
1382 }
1383
1384 delete cal;
1385 }
1386
1387 /**
1388 * @bug 4125881
1389 * Check isLeapYear for BC years.
1390 */
test4125881()1391 void CalendarRegressionTest::test4125881()
1392 {
1393 UErrorCode status = U_ZERO_ERROR;
1394 GregorianCalendar *cal = (GregorianCalendar*) Calendar::createInstance(status);
1395 if(U_FAILURE(status)) {
1396 dataerrln("Error creating calendar %s", u_errorName(status));
1397 delete cal;
1398 return;
1399 }
1400 DateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"),status);
1401 if(!assertSuccess("trying to construct", status))return;
1402 cal->clear();
1403 for (int32_t y=-20; y<=10; ++y) {
1404 cal->set(UCAL_ERA, y < 1 ? GregorianCalendar::BC : GregorianCalendar::AD);
1405 cal->set(UCAL_YEAR, y < 1 ? 1 - y : y);
1406 UnicodeString temp;
1407 logln(UnicodeString("") + y + UnicodeString(" = ") + fmt->format(cal->getTime(status), temp) + " " +
1408 cal->isLeapYear(y));
1409 if (cal->isLeapYear(y) != ((y+40)%4 == 0))
1410 errln("Leap years broken");
1411 }
1412
1413 delete cal;
1414 delete fmt;
1415 }
1416
1417 /**
1418 * @bug 4125892
1419 * Prove that GregorianCalendar is proleptic (it used to cut off
1420 * at 45 BC, and not have leap years before then).
1421 */
test4125892()1422 void CalendarRegressionTest::test4125892() {
1423 UErrorCode status = U_ZERO_ERROR;
1424 GregorianCalendar *cal = (GregorianCalendar*) Calendar::createInstance(status);
1425 if(U_FAILURE(status)) {
1426 dataerrln("Error creating calendar %s", u_errorName(status));
1427 delete cal;
1428 return;
1429 }
1430 DateFormat *fmt = new SimpleDateFormat(UnicodeString("MMMM d, yyyy G"),status);
1431 if(!assertSuccess("trying to construct", status))return;
1432 cal->clear();
1433 cal->set(UCAL_ERA, GregorianCalendar::BC);
1434 cal->set(UCAL_YEAR, 81); // 81 BC is a leap year (proleptically)
1435 cal->set(UCAL_MONTH, UCAL_FEBRUARY);
1436 cal->set(UCAL_DATE, 28);
1437 cal->add(UCAL_DATE, 1,status);
1438 if(U_FAILURE(status))
1439 errln("add(DATE,1) failed");
1440 if (cal->get(UCAL_DATE,status) != 29 ||
1441 !cal->isLeapYear(-80)) // -80 == 81 BC
1442 errln("Calendar not proleptic");
1443
1444 delete cal;
1445 delete fmt;
1446 }
1447
1448 /**
1449 * @bug 4141665
1450 * GregorianCalendar::equals() ignores cutover date
1451 */
test4141665()1452 void CalendarRegressionTest::test4141665()
1453 {
1454 UErrorCode status = U_ZERO_ERROR;
1455 GregorianCalendar *cal = new GregorianCalendar(status);
1456 if(U_FAILURE(status)) {
1457 dataerrln("Error creating calendar %s", u_errorName(status));
1458 delete cal;
1459 return;
1460 }
1461 GregorianCalendar *cal2 = (GregorianCalendar*)cal->clone();
1462 UDate cut = cal->getGregorianChange();
1463 UDate cut2 = cut + 100*24*60*60*1000.0; // 100 days later
1464 if (*cal != *cal2) {
1465 errln("Cloned GregorianCalendars not equal");
1466 }
1467 cal2->setGregorianChange(cut2,status);
1468 if ( *cal == *cal2) {
1469 errln("GregorianCalendar::equals() ignores cutover");
1470 }
1471
1472 delete cal;
1473 delete cal2;
1474 }
1475
1476 /**
1477 * @bug 4142933
1478 * Bug states that ArrayIndexOutOfBoundsException is thrown by GregorianCalendar::roll()
1479 * when IllegalArgumentException should be.
1480 */
test4142933()1481 void CalendarRegressionTest::test4142933()
1482 {
1483 UErrorCode status = U_ZERO_ERROR;
1484 GregorianCalendar *calendar = new GregorianCalendar(status);
1485 if(U_FAILURE(status)) {
1486 dataerrln("Error creating calendar %s", u_errorName(status));
1487 delete calendar;
1488 return;
1489 }
1490 //try {
1491 calendar->roll((UCalendarDateFields)-1, TRUE, status);
1492 if(U_SUCCESS(status))
1493 errln("Test failed, no exception thrown");
1494 //}
1495 //catch (IllegalArgumentException e) {
1496 // OK: Do nothing
1497 // logln("Test passed");
1498 //}
1499 //catch (Exception e) {
1500 //errln("Test failed. Unexpected exception is thrown: " + e);
1501 //e.printStackTrace();
1502 //}
1503
1504 delete calendar;
1505 }
1506
1507 /**
1508 * @bug 4145158
1509 * GregorianCalendar handling of Dates Long.MIN_VALUE and Long.MAX_VALUE is
1510 * confusing; unless the time zone has a raw offset of zero, one or the
1511 * other of these will wrap. We've modified the test given in the bug
1512 * report to therefore only check the behavior of a calendar with a zero raw
1513 * offset zone.
1514 */
test4145158()1515 void CalendarRegressionTest::test4145158()
1516 {
1517 UErrorCode status = U_ZERO_ERROR;
1518 GregorianCalendar *calendar = new GregorianCalendar(status);
1519 if(status == U_USING_FALLBACK_WARNING || U_FAILURE(status)) {
1520 dataerrln("Error creating calendar %s", u_errorName(status));
1521 delete calendar;
1522 return;
1523 }
1524
1525 calendar->adoptTimeZone(TimeZone::createTimeZone("GMT"));
1526
1527 calendar->setTime(makeDate(INT32_MIN),status);
1528 int32_t year1 = calendar->get(UCAL_YEAR,status);
1529 int32_t era1 = calendar->get(UCAL_ERA,status);
1530
1531 calendar->setTime(makeDate(INT32_MAX),status);
1532 int32_t year2 = calendar->get(UCAL_YEAR,status);
1533 int32_t era2 = calendar->get(UCAL_ERA,status);
1534
1535 if (year1 == year2 && era1 == era2) {
1536 errln("Fail: Long.MIN_VALUE or Long.MAX_VALUE wrapping around");
1537 }
1538
1539 delete calendar;
1540 }
1541
1542 /**
1543 * @bug 4145983
1544 * Maximum value for YEAR field wrong.
1545 */
1546 // {sfb} this is not directly applicable in C++, since all
1547 // possible doubles are not representable by our Calendar.
1548 // In Java, all longs are representable.
1549 // We can determine limits programmatically
1550 // Using DBL_MAX is a bit of a hack, since for large doubles
1551 // Calendar gets squirrely and doesn't behave in any sort
1552 // of linear fashion (ie years jump around, up/down, etc) for a
1553 // small change in millis.
test4145983()1554 void CalendarRegressionTest::test4145983()
1555 {
1556 UErrorCode status = U_ZERO_ERROR;
1557 GregorianCalendar *calendar = new GregorianCalendar(status);
1558 if(U_FAILURE(status)) {
1559 dataerrln("Error creating calendar %s", u_errorName(status));
1560 delete calendar;
1561 return;
1562 }
1563 calendar->adoptTimeZone(TimeZone::createTimeZone("GMT"));
1564 UDate DATES [] = { LATEST_SUPPORTED_MILLIS, EARLIEST_SUPPORTED_MILLIS };
1565 for (int32_t i=0; i<2; ++i) {
1566 calendar->setTime(DATES[i], status);
1567 int32_t year = calendar->get(UCAL_YEAR,status);
1568 int32_t maxYear = calendar->getMaximum(UCAL_YEAR);
1569 if (year > maxYear) {
1570 errln(UnicodeString("Failed for ")+DATES[i]+" ms: year=" +
1571 year + ", maxYear=" + maxYear);
1572 }
1573 }
1574
1575 delete calendar;
1576 }
1577
1578 /**
1579 * @bug 4147269
1580 * This is a bug in the validation code of GregorianCalendar:: As reported,
1581 * the bug seems worse than it really is, due to a bug in the way the bug
1582 * report test was written. In reality the bug is restricted to the DAY_OF_YEAR
1583 * field. - liu 6/29/98
1584 */
test4147269()1585 void CalendarRegressionTest::test4147269()
1586 {
1587 UErrorCode status = U_ZERO_ERROR;
1588 GregorianCalendar *calendar = new GregorianCalendar(status);
1589 if(status == U_USING_FALLBACK_WARNING || U_FAILURE(status)) {
1590 dataerrln("Error creating calendar %s", u_errorName(status));
1591 delete calendar;
1592 return;
1593 }
1594 calendar->setLenient(FALSE);
1595 UDate date = makeDate(1996, UCAL_JANUARY, 3); // Arbitrary date
1596 for (int32_t field = 0; field < UCAL_FIELD_COUNT; field++) {
1597 calendar->setTime(date,status);
1598 // Note: In the bug report, getActualMaximum() was called instead
1599 // of getMaximum() -- this was an error. The validation code doesn't
1600 // use getActualMaximum(), since that's too costly.
1601 int32_t max = calendar->getMaximum((UCalendarDateFields)field);
1602 int32_t value = max+1;
1603 calendar->set((UCalendarDateFields)field, value);
1604 //try {
1605 calendar->getTime(status); // Force time computation
1606 // We expect an exception to be thrown. If we fall through
1607 // to the next line, then we have a bug.
1608 if(U_SUCCESS(status))
1609 errln(UnicodeString("Test failed with field ") + FIELD_NAME[field] +
1610 ", date before: " + date +
1611 ", date after: " + calendar->getTime(status) +
1612 ", value: " + value + " (max = " + max +")");
1613 //} catch (IllegalArgumentException e) {}
1614 }
1615
1616 delete calendar;
1617 }
1618
1619 /**
1620 * @bug 4149677
1621 * Reported bug is that a GregorianCalendar with a cutover of Date(Long.MAX_VALUE)
1622 * doesn't behave as a pure Julian calendar.
1623 * CANNOT REPRODUCE THIS BUG
1624 */
1625 void
Test4149677()1626 CalendarRegressionTest::Test4149677()
1627 {
1628 UErrorCode status = U_ZERO_ERROR;
1629
1630 TimeZone *zones [] = {
1631 TimeZone::createTimeZone("GMT"),
1632 TimeZone::createTimeZone("PST"),
1633 TimeZone::createTimeZone("EAT")
1634 };
1635 if(U_FAILURE(status)) {
1636 errln("Couldn't create zones");
1637 return;
1638 // could leak memory
1639 }
1640
1641 for (int32_t i=0; i < 3; ++i) {
1642 GregorianCalendar *calendar = new GregorianCalendar(zones[i], status);
1643 if(U_FAILURE(status)) {
1644 dataerrln("Couldnt' create calendar.: %s", u_errorName(status));
1645 return;
1646 }
1647
1648 // Make sure extreme values don't wrap around
1649 calendar->setTime(EARLIEST_SUPPORTED_MILLIS, status);
1650 if(U_FAILURE(status))
1651 errln("setTime failed");
1652 if (calendar->get(UCAL_ERA, status) != GregorianCalendar::BC || U_FAILURE(status)) {
1653 errln("Fail: Date(EARLIEST_SUPPORTED_MILLIS) has an AD year");
1654 }
1655 calendar->setTime(LATEST_SUPPORTED_MILLIS, status);
1656 if(U_FAILURE(status))
1657 errln("setTime failed");
1658 if (calendar->get(UCAL_ERA, status) != GregorianCalendar::AD || U_FAILURE(status)) {
1659 errln("Fail: Date(LATEST_SUPPORTED_MILLIS) has a BC year");
1660 }
1661
1662 calendar->setGregorianChange(LATEST_SUPPORTED_MILLIS, status);
1663 if(U_FAILURE(status))
1664 errln("setGregorianChange failed");
1665 // to obtain a pure Julian calendar
1666
1667 UBool is100Leap = calendar->isLeapYear(100);
1668 if (!is100Leap) {
1669 UnicodeString temp;
1670 errln("test failed with zone " + zones[i]->getID(temp));
1671 errln(" cutover date is Date(Long.MAX_VALUE)");
1672 errln(" isLeapYear(100) returns: " + is100Leap);
1673 }
1674 delete calendar;
1675 }
1676
1677 // no need for cleanup- zones were adopted
1678 }
1679
1680 /**
1681 * @bug 4162587
1682 * Calendar and Date HOUR broken. If HOUR is out-of-range, Calendar
1683 * and Date classes will misbehave.
1684 */
1685 void
Test4162587()1686 CalendarRegressionTest::Test4162587()
1687 {
1688 UErrorCode status = U_ZERO_ERROR;
1689 TimeZone *savedef = TimeZone::createDefault();
1690 TimeZone *tz = TimeZone::createTimeZone("PST");
1691 //TimeZone::adoptDefault(tz);
1692 TimeZone::setDefault(*tz);
1693
1694 GregorianCalendar *cal = new GregorianCalendar(tz, status);
1695 if(U_FAILURE(status)) {
1696 dataerrln("Couldn't create calendar.: %s", u_errorName(status));
1697 return;
1698 }
1699 UDate d0, dPlus, dMinus;
1700
1701 for(int32_t i=0; i<5; ++i) {
1702 if (i>0) logln("---");
1703
1704 cal->clear();
1705 cal->set(1998, UCAL_APRIL, 5, i, 0);
1706 d0 = cal->getTime(status);
1707 if(U_FAILURE(status))
1708 errln("Coudln't get time (1)");
1709 //String s0 = d.toString();
1710 logln(UnicodeString("0 ") + i + ": " + d0/*s0*/);
1711
1712 cal->clear();
1713 cal->set(1998, UCAL_APRIL, 4, i+24, 0);
1714 dPlus = cal->getTime(status);
1715 if(U_FAILURE(status))
1716 errln("Coudln't get time (2)");
1717 //String sPlus = d.toString();
1718 logln(UnicodeString("+ ") + i + ": " + dPlus/*sPlus*/);
1719
1720 cal->clear();
1721 cal->set(1998, UCAL_APRIL, 6, i-24, 0);
1722 dMinus = cal->getTime(status);
1723 if(U_FAILURE(status))
1724 errln("Coudln't get time (3)");
1725 //String sMinus = d.toString();
1726 logln(UnicodeString("- ") + i + ": " + dMinus/*sMinus*/);
1727
1728 if (d0 != dPlus || d0 != dMinus) {
1729 errln("Fail: All three lines must match");
1730 }
1731 }
1732 TimeZone::setDefault(*savedef);
1733 //delete tz;
1734 delete cal;
1735 delete savedef;
1736 }
1737
1738 /**
1739 * @bug 4165343
1740 * Adding 12 months behaves differently from adding 1 year
1741 */
1742 void
Test4165343()1743 CalendarRegressionTest::Test4165343()
1744 {
1745 UErrorCode status = U_ZERO_ERROR;
1746 GregorianCalendar *calendar = new GregorianCalendar(1996, UCAL_FEBRUARY, 29, status);
1747 if(U_FAILURE(status)) {
1748 dataerrln("Couldn't create calendar.: %s", u_errorName(status));
1749 return;
1750 }
1751 UDate start = calendar->getTime(status);
1752 if(U_FAILURE(status))
1753 errln("Couldn't getTime (1)");
1754 logln(UnicodeString("init date: ") + start);
1755 calendar->add(UCAL_MONTH, 12, status);
1756 if(U_FAILURE(status))
1757 errln("Couldn't add(MONTH, 12)");
1758 UDate date1 = calendar->getTime(status);
1759 if(U_FAILURE(status))
1760 errln("Couldn't getTime (2)");
1761 logln(UnicodeString("after adding 12 months: ") + date1);
1762 calendar->setTime(start, status);
1763 if(U_FAILURE(status))
1764 errln("Couldn't setTime");
1765 calendar->add(UCAL_YEAR, 1, status);
1766 if(U_FAILURE(status))
1767 errln("Couldn't add(YEAR, 1)");
1768 UDate date2 = calendar->getTime(status);
1769 if(U_FAILURE(status))
1770 errln("Couldn't getTime (3)");
1771 logln(UnicodeString("after adding one year : ") + date2);
1772 if (date1 == date2) {
1773 logln("Test passed");
1774 } else {
1775 errln("Test failed");
1776 }
1777 delete calendar;
1778 }
1779
1780 /**
1781 * @bug 4166109
1782 * GregorianCalendar.getActualMaximum() does not account for first day of week.
1783 */
1784 void
Test4166109()1785 CalendarRegressionTest::Test4166109()
1786 {
1787 /* Test month:
1788 *
1789 * March 1998
1790 * Su Mo Tu We Th Fr Sa
1791 * 1 2 3 4 5 6 7
1792 * 8 9 10 11 12 13 14
1793 * 15 16 17 18 19 20 21
1794 * 22 23 24 25 26 27 28
1795 * 29 30 31
1796 */
1797 UBool passed = TRUE;
1798 UErrorCode status = U_ZERO_ERROR;
1799 UCalendarDateFields field = UCAL_WEEK_OF_MONTH;
1800
1801 GregorianCalendar *calendar = new GregorianCalendar(Locale::getUS(), status);
1802 if(U_FAILURE(status)) {
1803 dataerrln("Couldn't create calendar.: %s", u_errorName(status));
1804 return;
1805 }
1806 calendar->set(1998, UCAL_MARCH, 1);
1807 calendar->setMinimalDaysInFirstWeek(1);
1808 logln(UnicodeString("Date: ") + calendar->getTime(status)); // 888817448000
1809
1810 int32_t firstInMonth = calendar->get(UCAL_DATE, status);
1811 if(U_FAILURE(status))
1812 errln("get(D_O_M) failed");
1813
1814 for(int32_t firstInWeek = UCAL_SUNDAY; firstInWeek <= UCAL_SATURDAY; firstInWeek++) {
1815 calendar->setFirstDayOfWeek((UCalendarDaysOfWeek)firstInWeek);
1816 int32_t returned = calendar->getActualMaximum(field, status);
1817 int32_t expected = (31 + ((firstInMonth - firstInWeek + 7)% 7) + 6) / 7;
1818
1819 logln(UnicodeString("First day of week = ") + firstInWeek +
1820 " getActualMaximum(WEEK_OF_MONTH, status) = " + returned +
1821 " expected = " + expected +
1822 ((returned == expected) ? " ok" : " FAIL"));
1823
1824 if (returned != expected) {
1825 passed = FALSE;
1826 }
1827 }
1828 if (!passed) {
1829 errln("Test failed");
1830 }
1831
1832 delete calendar;
1833 }
1834
1835 /**
1836 * @bug 4167060
1837 * Calendar.getActualMaximum(YEAR) works wrong.
1838 */
1839 void
Test4167060()1840 CalendarRegressionTest::Test4167060()
1841 {
1842 UErrorCode status = U_ZERO_ERROR;
1843 UCalendarDateFields field = UCAL_YEAR;
1844 DateFormat *format = new SimpleDateFormat(UnicodeString("EEE MMM dd HH:mm:ss zzz yyyy G"),
1845 Locale::getUS(), status);
1846 if(U_FAILURE(status)) {
1847 dataerrln("Couldn't create SimpleDateFormat - %s", u_errorName(status));
1848 return;
1849 }
1850
1851 GregorianCalendar *calendars [] = {
1852 new GregorianCalendar(100, UCAL_NOVEMBER, 1, status),
1853 new GregorianCalendar(-99 /*100BC*/, UCAL_JANUARY, 1, status),
1854 new GregorianCalendar(1996, UCAL_FEBRUARY, 29, status),
1855 };
1856 if(U_FAILURE(status)) {
1857 errln("Couldn't create GregorianCalendars");
1858 return;
1859 // could leak
1860 }
1861
1862 UnicodeString id [] = { "Hybrid", "Gregorian", "Julian" };
1863
1864 for (int32_t k=0; k<3; ++k) {
1865 logln("--- " + id[k] + " ---");
1866
1867 for (int32_t j=0; j < 3; ++j) {
1868 GregorianCalendar *calendar = calendars[j];
1869 if (k == 1) {
1870 calendar->setGregorianChange(EARLIEST_SUPPORTED_MILLIS, status);
1871 }
1872 else if (k == 2) {
1873 calendar->setGregorianChange(LATEST_SUPPORTED_MILLIS, status);
1874 }
1875
1876 if(U_FAILURE(status))
1877 errln("setGregorianChange() failed");
1878 format->adoptCalendar((Calendar*)calendar->clone());
1879
1880 UDate dateBefore = calendar->getTime(status);
1881 if(U_FAILURE(status))
1882 errln("getTime() failed");
1883
1884 int32_t maxYear = calendar->getActualMaximum(field, status);
1885 UnicodeString temp;
1886 logln(UnicodeString("maxYear: ") + maxYear + " for " + format->format(calendar->getTime(status), temp));
1887 temp.remove();
1888 logln("date before: " + format->format(dateBefore, temp));
1889
1890 int32_t years[] = {2000, maxYear-1, maxYear, maxYear+1};
1891
1892 for (int32_t i = 0; i < 4; i++) {
1893 UBool valid = years[i] <= maxYear;
1894 calendar->set(field, years[i]);
1895 UDate dateAfter = calendar->getTime(status);
1896 if(U_FAILURE(status))
1897 errln("getTime() failed");
1898 int32_t newYear = calendar->get(field, status);
1899 if(U_FAILURE(status))
1900 errln(UnicodeString("get(") + (int32_t)field + ") failed");
1901 calendar->setTime(dateBefore, status); // restore calendar for next use
1902 if(U_FAILURE(status))
1903 errln("setTime() failed");
1904
1905 temp.remove();
1906 logln(UnicodeString(" Year ") + years[i] + (valid? " ok " : " bad") +
1907 " => " + format->format(dateAfter, temp));
1908 if (valid && newYear != years[i]) {
1909 errln(UnicodeString(" FAIL: ") + newYear + " should be valid; date, month and time shouldn't change");
1910 }
1911 // {sfb} this next line is a hack, but it should work since if a
1912 // double has an exponent, adding 1 should not yield the same double
1913 else if (!valid && /*newYear == years[i]*/ dateAfter + 1.0 == dateAfter) {
1914 errln(UnicodeString(" FAIL: ") + newYear + " should be invalid");
1915 }
1916 }
1917 }
1918 }
1919
1920 delete format;
1921 delete calendars[0];
1922 delete calendars[1];
1923 delete calendars[2];
1924 }
1925
1926 /**
1927 * Week of year is wrong at the start and end of the year.
1928 */
Test4197699()1929 void CalendarRegressionTest::Test4197699() {
1930 UErrorCode status = U_ZERO_ERROR;
1931 GregorianCalendar cal(status);
1932 cal.setFirstDayOfWeek(UCAL_MONDAY);
1933 cal.setMinimalDaysInFirstWeek(4);
1934 SimpleDateFormat fmt("E dd MMM yyyy 'DOY='D 'WOY='w",
1935 Locale::getUS(), status);
1936 fmt.setCalendar(cal);
1937 if (U_FAILURE(status)) {
1938 dataerrln("Couldn't initialize test - %s", u_errorName(status));
1939 return;
1940 }
1941
1942 int32_t DATA[] = {
1943 2000, UCAL_JANUARY, 1, 52,
1944 2001, UCAL_DECEMBER, 31, 1,
1945 };
1946 int32_t DATA_length = (int32_t)(sizeof(DATA) / sizeof(DATA[0]));
1947
1948 UnicodeString str;
1949 DateFormat& dfmt = *(DateFormat*)&fmt;
1950 for (int32_t i=0; i<DATA_length; ) {
1951 cal.clear();
1952 cal.set(DATA[i], DATA[i+1], DATA[i+2]);
1953 i += 3;
1954 int32_t expWOY = DATA[i++];
1955 int32_t actWOY = cal.get(UCAL_WEEK_OF_YEAR, status);
1956 if (expWOY == actWOY) {
1957 logln(UnicodeString("Ok: ") + dfmt.format(cal.getTime(status), str.remove()));
1958 } else {
1959 errln(UnicodeString("FAIL: ") + dfmt.format(cal.getTime(status), str.remove())
1960 + ", expected WOY=" + expWOY);
1961 cal.add(UCAL_DATE, -8, status);
1962 for (int j=0; j<14; ++j) {
1963 cal.add(UCAL_DATE, 1, status);
1964 logln(dfmt.format(cal.getTime(status), str.remove()));
1965 }
1966 }
1967 if (U_FAILURE(status)) {
1968 errln("FAIL: Unexpected error from Calendar");
1969 return;
1970 }
1971 }
1972 }
1973
1974 enum Action { ADD=1, ROLL=2 };
1975 enum Sign { PLUS=1, MINUS=2 };
1976
1977 #define ONE_HOUR (60*60*1000)
1978 #define ONE_DAY (24*ONE_HOUR)
1979
1980 typedef struct {
1981 UCalendarDateFields field;
1982 int8_t actionMask; // ADD or ROLL or both
1983 int8_t signMask; // PLUS or MINUS or both
1984 int32_t amount;
1985 int32_t before; // ms before cutover
1986 int32_t after; // ms after cutover
1987 } J81_DATA;
1988
1989 /**
1990 * Rolling and adding across the Gregorian cutover should work as expected.
1991 * Jitterbug 81.
1992 */
TestJ81()1993 void CalendarRegressionTest::TestJ81() {
1994 UErrorCode status = U_ZERO_ERROR;
1995 UnicodeString temp, temp2, temp3;
1996 int32_t i;
1997 GregorianCalendar cal(TimeZone::createTimeZone("GMT"), Locale::getUS(), status);
1998 SimpleDateFormat fmt("HH:mm 'w'w 'd'D E d MMM yyyy", Locale::getUS(), status);
1999 if (U_FAILURE(status)) {
2000 dataerrln("Error: Cannot create calendar or format - %s", u_errorName(status));
2001 return;
2002 }
2003 fmt.setCalendar(cal);
2004 // Get the Gregorian cutover
2005 UDate cutover = cal.getGregorianChange();
2006 UDate days = ONE_DAY;
2007 days = cutover/days;
2008 logln(UnicodeString("Cutover: {") +
2009 fmt.format(cutover, temp) + "}(epoch days-" + (int)days + ", jd" + (2440588 + days) +")");
2010
2011 // Check woy and doy handling. Reference data:
2012 /* w40 d274 Mon 1 Oct 1582
2013 w40 d275 Tue 2 Oct 1582
2014 w40 d276 Wed 3 Oct 1582
2015 w40 d277 Thu 4 Oct 1582
2016 w40 d278 Fri 15 Oct 1582
2017 w40 d279 Sat 16 Oct 1582
2018 w41 d280 Sun 17 Oct 1582
2019 w41 d281 Mon 18 Oct 1582
2020 w41 d282 Tue 19 Oct 1582
2021 w41 d283 Wed 20 Oct 1582
2022 w41 d284 Thu 21 Oct 1582
2023 w41 d285 Fri 22 Oct 1582
2024 w41 d286 Sat 23 Oct 1582
2025 w42 d287 Sun 24 Oct 1582
2026 w42 d288 Mon 25 Oct 1582
2027 w42 d289 Tue 26 Oct 1582
2028 w42 d290 Wed 27 Oct 1582
2029 w42 d291 Thu 28 Oct 1582
2030 w42 d292 Fri 29 Oct 1582
2031 w42 d293 Sat 30 Oct 1582
2032 w43 d294 Sun 31 Oct 1582
2033 w43 d295 Mon 1 Nov 1582 */
2034 int32_t DOY_DATA[] = {
2035 // dom, woy, doy
2036 1, 40, 274, UCAL_MONDAY,
2037 4, 40, 277, UCAL_THURSDAY,
2038 15, 40, 278, UCAL_FRIDAY,
2039 17, 41, 280, UCAL_SUNDAY,
2040 24, 42, 287, UCAL_SUNDAY,
2041 25, 42, 288, UCAL_MONDAY,
2042 26, 42, 289, UCAL_TUESDAY,
2043 27, 42, 290, UCAL_WEDNESDAY,
2044 28, 42, 291, UCAL_THURSDAY,
2045 29, 42, 292, UCAL_FRIDAY,
2046 30, 42, 293, UCAL_SATURDAY,
2047 31, 43, 294, UCAL_SUNDAY
2048 };
2049 int32_t DOY_DATA_length = (int32_t)(sizeof(DOY_DATA) / sizeof(DOY_DATA[0]));
2050
2051 for (i=0; i<DOY_DATA_length; i+=4) {
2052 // Test time->fields
2053 cal.set(1582, UCAL_OCTOBER, DOY_DATA[i]);
2054 int32_t woy = cal.get(UCAL_WEEK_OF_YEAR, status);
2055 int32_t doy = cal.get(UCAL_DAY_OF_YEAR, status);
2056 int32_t dow = cal.get(UCAL_DAY_OF_WEEK, status);
2057 if (U_FAILURE(status)) {
2058 errln("Error: get() failed");
2059 break;
2060 }
2061 if (woy != DOY_DATA[i+1] || doy != DOY_DATA[i+2] || dow != DOY_DATA[i+3]) {
2062 errln((UnicodeString)"Fail: expect woy=" + DOY_DATA[i+1] +
2063 ", doy=" + DOY_DATA[i+2] + ", dow=" + DOY_DATA[i+3] + " on " +
2064 fmt.format(cal.getTime(status), temp.remove()) +
2065 " set(1582,OCTOBER, " + DOY_DATA[i] + ")");
2066 logln(CalendarTest::calToStr(cal));
2067 status = U_ZERO_ERROR;
2068 } else {
2069 logln((UnicodeString)"PASS: expect woy=" + DOY_DATA[i+1] +
2070 ", doy=" + DOY_DATA[i+2] + ", dow=" + DOY_DATA[i+3] + " on " +
2071 fmt.format(cal.getTime(status), temp.remove()));
2072 logln(CalendarTest::calToStr(cal));
2073 status = U_ZERO_ERROR;
2074 }
2075 // Test fields->time for WOY
2076 cal.clear();
2077 cal.set(UCAL_YEAR, 1582);
2078 cal.set(UCAL_WEEK_OF_YEAR, DOY_DATA[i+1]);
2079 cal.set(UCAL_DAY_OF_WEEK, DOY_DATA[i+3]);
2080 int32_t dom = cal.get(UCAL_DATE, status);
2081 if (U_FAILURE(status)) {
2082 errln("Error: get() failed");
2083 break;
2084 }
2085 if (dom != DOY_DATA[i]) {
2086 errln((UnicodeString)"Fail: set woy=" + DOY_DATA[i+1] +
2087 " dow=" + DOY_DATA[i+3] + " => " +
2088 fmt.format(cal.getTime(status), temp.remove()) +
2089 ", expected 1582 Oct " + DOY_DATA[i]);
2090 logln(CalendarTest::calToStr(cal));
2091 status = U_ZERO_ERROR;
2092 }
2093
2094 // Test fields->time for DOY
2095 cal.clear();
2096 cal.set(UCAL_YEAR, 1582);
2097 cal.set(UCAL_DAY_OF_YEAR, DOY_DATA[i+2]);
2098 dom = cal.get(UCAL_DATE, status);
2099 if (U_FAILURE(status)) {
2100 errln("Error: get() failed");
2101 break;
2102 }
2103 if (dom != DOY_DATA[i]) {
2104 errln((UnicodeString)"Fail: set doy=" + DOY_DATA[i+2] +
2105 " => " +
2106 fmt.format(cal.getTime(status), temp.remove()) +
2107 ", expected 1582 Oct " + DOY_DATA[i]);
2108 status = U_ZERO_ERROR;
2109 }
2110 }
2111 status = U_ZERO_ERROR;
2112
2113 #define ADD_ROLL ADD|ROLL
2114 #define PLUS_MINUS PLUS|MINUS
2115 // Test cases
2116 J81_DATA DATA[] = {
2117 { UCAL_WEEK_OF_YEAR, ADD_ROLL, PLUS_MINUS, 1, -ONE_DAY, +6*ONE_DAY },
2118 { UCAL_WEEK_OF_YEAR, ADD_ROLL, PLUS_MINUS, 1, -ONE_DAY, +6*ONE_DAY },
2119 { UCAL_WEEK_OF_MONTH, ADD|ROLL, PLUS|MINUS, 1, -ONE_DAY, +6*ONE_DAY },
2120 { UCAL_DATE, ADD|ROLL, PLUS|MINUS, 2, -ONE_DAY, +1*ONE_DAY },
2121 { UCAL_DATE, ROLL, PLUS, -6, -ONE_DAY, +14*ONE_DAY },
2122 { UCAL_DATE, ROLL, PLUS, -7, 0, +14*ONE_DAY },
2123 { UCAL_DATE, ROLL, PLUS, -7, +ONE_DAY, +15*ONE_DAY },
2124 { UCAL_DATE, ROLL, PLUS, +18, -ONE_DAY, -4*ONE_DAY },
2125 { UCAL_DAY_OF_YEAR, ADD|ROLL, PLUS|MINUS, 2, -ONE_DAY, +1*ONE_DAY },
2126 { UCAL_DAY_OF_WEEK, ADD|ROLL, PLUS|MINUS, 2, -ONE_DAY, +1*ONE_DAY },
2127 { UCAL_DAY_OF_WEEK_IN_MONTH, ADD|ROLL, PLUS|MINUS, 1, -ONE_DAY, +6*ONE_DAY },
2128 { UCAL_AM_PM, ADD, PLUS|MINUS, 4, -12*ONE_HOUR, +36*ONE_HOUR },
2129 { UCAL_HOUR, ADD, PLUS|MINUS, 48, -12*ONE_HOUR, +36*ONE_HOUR },
2130 { UCAL_HOUR_OF_DAY, ADD, PLUS|MINUS, 48, -12*ONE_HOUR, +36*ONE_HOUR },
2131 { UCAL_MINUTE, ADD, PLUS|MINUS, 48*60, -12*ONE_HOUR, +36*ONE_HOUR },
2132 { UCAL_SECOND, ADD, PLUS|MINUS, 48*60*60, -12*ONE_HOUR, +36*ONE_HOUR },
2133 { UCAL_MILLISECOND, ADD, PLUS|MINUS, 48*ONE_HOUR, -12*ONE_HOUR, +36*ONE_HOUR },
2134 // NOTE: These are not supported yet. See jitterbug 180.
2135 // Uncomment these lines when add/roll supported on these fields.
2136 // { Calendar::YEAR_WOY, ADD|ROLL, 1, -ONE_DAY, +6*ONE_DAY },
2137 // { Calendar::DOW_LOCAL, ADD|ROLL, 2, -ONE_DAY, +1*ONE_DAY }
2138 };
2139 int32_t DATA_length = (int32_t)(sizeof(DATA) / sizeof(DATA[0]));
2140
2141 // Now run the tests
2142 for (i=0; i<DATA_length; ++i) {
2143 for (Action action=ADD; action<=ROLL; action=(Action)(action+1)) {
2144 if (!(DATA[i].actionMask & action)) {
2145 continue;
2146 }
2147 for (Sign sign=PLUS; sign<=MINUS; sign=(Sign)(sign+1)) {
2148 if (!(DATA[i].signMask & sign)) {
2149 continue;
2150 }
2151 status = U_ZERO_ERROR;
2152 int32_t amount = DATA[i].amount * (sign==MINUS?-1:1);
2153 UDate date = cutover +
2154 (sign==PLUS ? DATA[i].before : DATA[i].after);
2155 UDate expected = cutover +
2156 (sign==PLUS ? DATA[i].after : DATA[i].before);
2157 cal.setTime(date, status);
2158 if (U_FAILURE(status)) {
2159 errln((UnicodeString)"FAIL: setTime returned error code " + u_errorName(status));
2160 continue;
2161 }
2162 if (action == ADD) {
2163 cal.add(DATA[i].field, amount, status);
2164 } else {
2165 cal.roll(DATA[i].field, amount, status);
2166 }
2167 if (U_FAILURE(status)) {
2168 errln((UnicodeString)"FAIL: " +
2169 (action==ADD?"add ":"roll ") + FIELD_NAME[DATA[i].field] +
2170 " returned error code " + u_errorName(status));
2171 continue;
2172 }
2173 UDate result = cal.getTime(status);
2174 if (U_FAILURE(status)) {
2175 errln((UnicodeString)"FAIL: getTime returned error code " + u_errorName(status));
2176 continue;
2177 }
2178 if (result == expected) {
2179 logln((UnicodeString)"Ok: {" +
2180 fmt.format(date, temp.remove()) +
2181 "}(" + date/ONE_DAY +
2182 (action==ADD?") add ":") roll ") +
2183 amount + " " + FIELD_NAME[DATA[i].field] + " -> {" +
2184 fmt.format(result, temp2.remove()) +
2185 "}(" + result/ONE_DAY + ")");
2186 } else {
2187 errln((UnicodeString)"FAIL: {" +
2188 fmt.format(date, temp.remove()) +
2189 "}(" + date/ONE_DAY +
2190 (action==ADD?") add ":") roll ") +
2191 amount + " " + FIELD_NAME[DATA[i].field] + " -> {" +
2192 fmt.format(result, temp2.remove()) +
2193 "}(" + result/ONE_DAY + "), expect {" +
2194 fmt.format(expected, temp3.remove()) +
2195 "}(" + expected/ONE_DAY + ")");
2196 }
2197 }
2198 }
2199 }
2200 }
2201
2202 /**
2203 * Test fieldDifference().
2204 */
TestJ438(void)2205 void CalendarRegressionTest::TestJ438(void) {
2206 UErrorCode ec = U_ZERO_ERROR;
2207 int32_t DATA[] = {
2208 2000, UCAL_JANUARY, 20, 2010, UCAL_JUNE, 15,
2209 2010, UCAL_JUNE, 15, 2000, UCAL_JANUARY, 20,
2210 1964, UCAL_SEPTEMBER, 7, 1999, UCAL_JUNE, 4,
2211 1999, UCAL_JUNE, 4, 1964, UCAL_SEPTEMBER, 7,
2212 };
2213 int32_t DATA_length = (int32_t)(sizeof(DATA)/sizeof(DATA[0]));
2214 Calendar* pcal = Calendar::createInstance(Locale::getUS(), ec);
2215 if(U_FAILURE(ec)) {
2216 dataerrln("Error creating calendar %s", u_errorName(ec));
2217 delete pcal;
2218 return;
2219 }
2220 Calendar& cal = *pcal;
2221 int32_t i;
2222 SimpleDateFormat fmt(UnicodeString("MMM dd yyyy",""), ec);
2223 fmt.setCalendar(cal);
2224 UnicodeString s, t, u;
2225 if (!failure(ec, "setup")) {
2226 for (i=0; i<DATA_length; i+=6) {
2227 int32_t y1 = DATA[i];
2228 int32_t m1 = DATA[i+1];
2229 int32_t d1 = DATA[i+2];
2230 int32_t y2 = DATA[i+3];
2231 int32_t m2 = DATA[i+4];
2232 int32_t d2 = DATA[i+5];
2233
2234 cal.clear();
2235 cal.set(y1, m1, d1);
2236 UDate date1 = cal.getTime(ec);
2237 if (failure(ec, "getTime"))
2238 break;
2239 cal.set(y2, m2, d2);
2240 UDate date2 = cal.getTime(ec);
2241 if (failure(ec, "getTime"))
2242 break;
2243
2244 cal.setTime(date1, ec);
2245 if (failure(ec, "setTime"))
2246 break;
2247 int32_t dy = cal.fieldDifference(date2, UCAL_YEAR, ec);
2248 int32_t dm = cal.fieldDifference(date2, UCAL_MONTH, ec);
2249 int32_t dd = cal.fieldDifference(date2, UCAL_DATE, ec);
2250 if (failure(ec, "fieldDifference"))
2251 break;
2252
2253 {
2254 Calendar *cal2 = cal.clone();
2255 UErrorCode ec2 = U_ZERO_ERROR;
2256
2257 cal2->setTime(date1, ec2);
2258
2259 int32_t dy2 = cal2->fieldDifference(date2, Calendar::YEAR, ec2);
2260 int32_t dm2 = cal2->fieldDifference(date2, Calendar::MONTH, ec2);
2261 int32_t dd2 = cal2->fieldDifference(date2, Calendar::DATE, ec2);
2262 if (failure(ec2, "fieldDifference(date, Calendar::DATE, ec)"))
2263 break;
2264 if( (dd2 != dd) ||
2265 (dm2 != dm) ||
2266 (dy2 != dy)){
2267 errln("fieldDifference(UCAL_...) and fieldDifference(Calendar::...) give different results!\n");
2268 }
2269 delete cal2;
2270 }
2271
2272
2273 logln(UnicodeString("") +
2274 fmt.format(date2, s.remove()) + " - " +
2275 fmt.format(date1, t.remove()) + " = " +
2276 dy + "y " + dm + "m " + dd + "d");
2277
2278 cal.setTime(date1, ec);
2279 if (failure(ec, "setTime"))
2280 break;
2281 cal.add(UCAL_YEAR, dy, ec);
2282 cal.add(UCAL_MONTH, dm, ec);
2283 cal.add(UCAL_DATE, dd, ec);
2284 if (failure(ec, "add"))
2285 break;
2286 UDate date22 = cal.getTime(ec);
2287 if (failure(ec, "getTime"))
2288 break;
2289 if (date2 != date22) {
2290 errln(UnicodeString("FAIL: ") +
2291 fmt.format(date1, s.remove()) + " + " +
2292 dy + "y " + dm + "m " + dd + "d = " +
2293 fmt.format(date22, t.remove()) + ", exp " +
2294 fmt.format(date2, u.remove()));
2295 } else {
2296 logln(UnicodeString("Ok: ") +
2297 fmt.format(date1, s.remove()) + " + " +
2298 dy + "y " + dm + "m " + dd + "d = " +
2299 fmt.format(date22, t.remove()));
2300 }
2301 }
2302 }
2303 delete pcal;
2304 }
2305
TestT5555()2306 void CalendarRegressionTest::TestT5555()
2307 {
2308 UErrorCode ec = U_ZERO_ERROR;
2309 Calendar *cal = Calendar::createInstance(ec);
2310
2311 if (cal == NULL || U_FAILURE(ec)) {
2312 dataerrln("FAIL: Calendar::createInstance(): %s", u_errorName(ec));
2313 delete cal;
2314 return;
2315 }
2316
2317 // Set to Wednesday, February 21, 2007
2318 cal->set(2007, UCAL_FEBRUARY, 21);
2319
2320 // Advance three years
2321 cal->add(UCAL_MONTH, 36, ec);
2322
2323 // Set to last Wednesday of the month
2324 cal->set(UCAL_DAY_OF_WEEK_IN_MONTH, -1);
2325
2326 cal->getTime(ec);
2327
2328 int32_t yy, mm, dd, ee;
2329
2330 yy = cal->get(UCAL_YEAR, ec);
2331 mm = cal->get(UCAL_MONTH, ec);
2332 dd = cal->get(UCAL_DATE, ec);
2333 ee = cal->get(UCAL_DAY_OF_WEEK, ec);
2334
2335 // Should be set to Wednesday, February 24, 2010
2336 if (U_FAILURE(ec) || yy != 2010 || mm != UCAL_FEBRUARY || dd != 24 || ee != UCAL_WEDNESDAY) {
2337 errln("FAIL: got date %4d/%02d/%02d, expected 210/02/24: ", yy, mm + 1, dd);
2338 }
2339 delete cal;
2340 }
2341
2342 typedef struct {
2343 int32_t startYear;
2344 int32_t startMonth; // 0-based
2345 int32_t startDay; // 1-based
2346 UCalendarDateFields fieldToChange;
2347 int32_t fieldDelta;
2348 int32_t endYear;
2349 int32_t endMonth; // 0-based
2350 int32_t endDay; // 1-based
2351 } CoptEthCalTestItem;
2352
2353 // year 1724 in coptic calendar =
2354 // year 2000 in ethiopic calendar (276 more than coptic) =
2355 // year 7500 in ethiopic-amete-alem calendar (5776 more than coptic)
2356 // (2007-2008 in gregorian calendar depending on month)
2357 static const CoptEthCalTestItem coptEthCalTestItems[] = {
2358 { 1724, 12, 1, UCAL_MONTH, +1, 1725, 0, 1 },
2359 { 1724, 12, 1, UCAL_MONTH, +9, 1725, 8, 1 },
2360 { 1723, 12, 2, UCAL_MONTH, +1, 1724, 0, 2 }, // 1723 is a leap year
2361 { 1723, 12, 2, UCAL_MONTH, +9, 1724, 8, 2 },
2362 { 1725, 0, 1, UCAL_MONTH, -1, 1724, 12, 1 },
2363 { 1725, 0, 1, UCAL_MONTH, -6, 1724, 7, 1 },
2364 { 1724, 12, 1, UCAL_DATE, +8, 1725, 0, 4 },
2365 { 1723, 12, 1, UCAL_DATE, +8, 1724, 0, 3 }, // 1723 is a leap year
2366 { 1724, 0, 1, UCAL_DATE, -1, 1723, 12, 6 }, // 1723 is a leap year
2367 { 0, 0, 0, (UCalendarDateFields)0, 0, 0, 0, 0 } // terminator
2368 };
2369
2370 typedef struct {
2371 const char * locale;
2372 int32_t yearOffset;
2373 } CoptEthCalLocale;
2374
2375 static const CoptEthCalLocale copEthCalLocales[] = {
2376 { "en@calendar=coptic", 0 },
2377 { "en@calendar=ethiopic", 276 },
2378 { NULL, 0 } // terminator
2379 };
2380
TestT6745()2381 void CalendarRegressionTest::TestT6745()
2382 {
2383 const CoptEthCalLocale * testLocalePtr;
2384 for ( testLocalePtr = copEthCalLocales; testLocalePtr->locale != NULL; ++testLocalePtr) {
2385 UErrorCode status = U_ZERO_ERROR;
2386 Calendar *cal = Calendar::createInstance(Locale(testLocalePtr->locale), status);
2387 if ( U_FAILURE(status) ) {
2388 dataerrln((UnicodeString)"FAIL: Calendar::createInstance, locale " + testLocalePtr->locale + ", status " + u_errorName(status));
2389 continue;
2390 }
2391 const CoptEthCalTestItem * testItemPtr;
2392 for (testItemPtr = coptEthCalTestItems; testItemPtr->fieldDelta != 0; ++testItemPtr) {
2393 status = U_ZERO_ERROR;
2394 cal->set( testItemPtr->startYear + testLocalePtr->yearOffset, testItemPtr->startMonth, testItemPtr->startDay, 9, 0 );
2395 cal->add( testItemPtr->fieldToChange, testItemPtr->fieldDelta, status );
2396 if ( U_FAILURE(status) ) {
2397 errln((UnicodeString)"FAIL: Calendar::add, locale " + testLocalePtr->locale + ", field/delta " +
2398 testItemPtr->fieldToChange + "/" + testItemPtr->fieldDelta + ", status " + u_errorName(status));
2399 continue;
2400 }
2401 int32_t endYear = testItemPtr->endYear + testLocalePtr->yearOffset;
2402 int32_t year = cal->get(UCAL_YEAR, status);
2403 int32_t month = cal->get(UCAL_MONTH, status);
2404 int32_t day = cal->get(UCAL_DATE, status);
2405 if ( U_FAILURE(status) || year != endYear || month != testItemPtr->endMonth || day != testItemPtr->endDay ) {
2406 errln((UnicodeString)"ERROR: Calendar::add, locale " + testLocalePtr->locale + ", field/delta " +
2407 testItemPtr->fieldToChange + "/" + testItemPtr->fieldDelta + ", status " + u_errorName(status) +
2408 ", expected " + endYear + "/" + testItemPtr->endMonth + "/" + testItemPtr->endDay +
2409 ", got " + year + "/" + month + "/" + day );
2410 }
2411 }
2412 delete cal;
2413 }
2414 }
2415
2416 /**
2417 * Test behavior of fieldDifference around leap years. Also test a large
2418 * field difference to check binary search.
2419 */
TestLeapFieldDifference()2420 void CalendarRegressionTest::TestLeapFieldDifference() {
2421 UErrorCode ec = U_ZERO_ERROR;
2422 Calendar* cal = Calendar::createInstance(ec);
2423 if (cal == NULL || U_FAILURE(ec)) {
2424 dataerrln("FAIL: Calendar::createInstance(): %s", u_errorName(ec));
2425 delete cal;
2426 return;
2427 }
2428 cal->set(2004, UCAL_FEBRUARY, 29);
2429 UDate date2004 = cal->getTime(ec);
2430 cal->set(2000, UCAL_FEBRUARY, 29);
2431 UDate date2000 = cal->getTime(ec);
2432 if (U_FAILURE(ec)) {
2433 errln("FAIL: getTime()");
2434 delete cal;
2435 return;
2436 }
2437 int32_t y = cal->fieldDifference(date2004, UCAL_YEAR, ec);
2438 int32_t d = cal->fieldDifference(date2004, UCAL_DAY_OF_YEAR, ec);
2439 if (U_FAILURE(ec)) {
2440 errln("FAIL: fieldDifference()");
2441 delete cal;
2442 return;
2443 }
2444 if (d == 0) {
2445 logln((UnicodeString)"Ok: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, " + d + " days");
2446 } else {
2447 errln((UnicodeString)"FAIL: 2004/Feb/29 - 2000/Feb/29 = " + y + " years, " + d + " days");
2448 }
2449 cal->setTime(date2004, ec);
2450 y = cal->fieldDifference(date2000, UCAL_YEAR, ec);
2451 d = cal->fieldDifference(date2000, UCAL_DAY_OF_YEAR, ec);
2452 if (U_FAILURE(ec)) {
2453 errln("FAIL: setTime() / fieldDifference()");
2454 delete cal;
2455 return;
2456 }
2457 if (d == 0) {
2458 logln((UnicodeString)"Ok: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, " + d + " days");
2459 } else {
2460 errln((UnicodeString)"FAIL: 2000/Feb/29 - 2004/Feb/29 = " + y + " years, " + d + " days");
2461 }
2462 // Test large difference
2463 cal->set(2001, UCAL_APRIL, 5); // 2452005
2464 UDate ayl = cal->getTime(ec);
2465 cal->set(1964, UCAL_SEPTEMBER, 7); // 2438646
2466 UDate asl = cal->getTime(ec);
2467 if (U_FAILURE(ec)) {
2468 errln("FAIL: getTime()");
2469 delete cal;
2470 return;
2471 }
2472 d = cal->fieldDifference(ayl, UCAL_DATE, ec);
2473 cal->setTime(ayl, ec);
2474 int32_t d2 = cal->fieldDifference(asl, UCAL_DATE, ec);
2475 if (U_FAILURE(ec)) {
2476 errln("FAIL: setTime() / fieldDifference()");
2477 delete cal;
2478 return;
2479 }
2480 if (d == -d2 && d == 13359) {
2481 logln((UnicodeString)"Ok: large field difference symmetrical " + d);
2482 } else {
2483 logln((UnicodeString)"FAIL: large field difference incorrect " + d + ", " + d2 +
2484 ", expect +/- 13359");
2485 }
2486 delete cal;
2487 }
2488
2489 /**
2490 * Test ms_MY "Malay (Malaysia)" locale. Bug 1543.
2491 */
TestMalaysianInstance()2492 void CalendarRegressionTest::TestMalaysianInstance() {
2493 Locale loc("ms", "MY"); // Malay (Malaysia)
2494 UErrorCode ec = U_ZERO_ERROR;
2495 Calendar* cal = Calendar::createInstance(loc, ec);
2496 if (U_FAILURE(ec)) {
2497 dataerrln("FAIL: Can't construct calendar for ms_MY: %s", u_errorName(ec));
2498 }
2499 delete cal;
2500 }
2501
2502 /**
2503 * setFirstDayOfWeek and setMinimalDaysInFirstWeek may change the
2504 * field <=> time mapping, since they affect the interpretation of
2505 * the WEEK_OF_MONTH or WEEK_OF_YEAR fields.
2506 */
TestWeekShift()2507 void CalendarRegressionTest::TestWeekShift() {
2508 UErrorCode ec = U_ZERO_ERROR;
2509 GregorianCalendar cal(TimeZone::createTimeZone("America/Los_Angeles"),
2510 Locale("en", "US"), ec);
2511 if (U_FAILURE(ec)) {
2512 dataerrln("Fail GregorianCalendar: %s", u_errorName(ec));
2513 return;
2514 }
2515 cal.setTime(UDate(997257600000.0), ec); // Wed Aug 08 01:00:00 PDT 2001
2516 // In pass one, change the first day of week so that the weeks
2517 // shift in August 2001. In pass two, change the minimal days
2518 // in the first week so that the weeks shift in August 2001.
2519 // August 2001
2520 // Su Mo Tu We Th Fr Sa
2521 // 1 2 3 4
2522 // 5 6 7 8 9 10 11
2523 // 12 13 14 15 16 17 18
2524 // 19 20 21 22 23 24 25
2525 // 26 27 28 29 30 31
2526 for (int32_t pass=0; pass<2; ++pass) {
2527 if (pass==0) {
2528 cal.setFirstDayOfWeek(UCAL_WEDNESDAY);
2529 cal.setMinimalDaysInFirstWeek(4);
2530 } else {
2531 cal.setFirstDayOfWeek(UCAL_SUNDAY);
2532 cal.setMinimalDaysInFirstWeek(4);
2533 }
2534 cal.add(UCAL_DATE, 1, ec); // Force recalc
2535 cal.add(UCAL_DATE, -1, ec);
2536
2537 UDate time1 = cal.getTime(ec); // Get time -- should not change
2538
2539 // Now change a week parameter and then force a recalc.
2540 // The bug is that the recalc should not be necessary --
2541 // calendar should do so automatically.
2542 if (pass==0) {
2543 cal.setFirstDayOfWeek(UCAL_THURSDAY);
2544 } else {
2545 cal.setMinimalDaysInFirstWeek(5);
2546 }
2547
2548 int32_t woy1 = cal.get(UCAL_WEEK_OF_YEAR, ec);
2549 int32_t wom1 = cal.get(UCAL_WEEK_OF_MONTH, ec);
2550
2551 cal.add(UCAL_DATE, 1, ec); // Force recalc
2552 cal.add(UCAL_DATE, -1, ec);
2553
2554 int32_t woy2 = cal.get(UCAL_WEEK_OF_YEAR, ec);
2555 int32_t wom2 = cal.get(UCAL_WEEK_OF_MONTH, ec);
2556
2557 UDate time2 = cal.getTime(ec);
2558
2559 if (U_FAILURE(ec)) {
2560 errln("FAIL: internal test error");
2561 return;
2562 }
2563
2564 if (time1 != time2) {
2565 errln("FAIL: shifting week should not alter time");
2566 } else {
2567 // logln(time1);
2568 }
2569 if (woy1 == woy2 && wom1 == wom2) {
2570 logln((UnicodeString)"Ok: WEEK_OF_YEAR: " + woy1 +
2571 ", WEEK_OF_MONTH: " + wom1);
2572 } else {
2573 errln((UnicodeString)"FAIL: WEEK_OF_YEAR: " + woy1 + " => " + woy2 +
2574 ", WEEK_OF_MONTH: " + wom1 + " => " + wom2 +
2575 " after week shift");
2576 }
2577 }
2578 }
2579
2580 /**
2581 * Make sure that when adding a day, we actually wind up in a
2582 * different day. The DST adjustments we use to keep the hour
2583 * constant across DST changes can backfire and change the day.
2584 */
TestTimeZoneTransitionAdd()2585 void CalendarRegressionTest::TestTimeZoneTransitionAdd() {
2586 UErrorCode ec = U_ZERO_ERROR;
2587 Locale locale(Locale::getUS()); // could also be CHINA
2588 SimpleDateFormat dateFormat("MM/dd/yyyy HH:mm z", locale, ec);
2589
2590 StringEnumeration *tz = TimeZone::createEnumeration();
2591 if (tz == NULL) {
2592 errln("FAIL: TimeZone::createEnumeration");
2593 return;
2594 }
2595
2596 UnicodeString buf1, buf2;
2597
2598 const UChar* id;
2599 while ((id = tz->unext(NULL, ec)) != NULL && U_SUCCESS(ec)) {
2600 if (U_FAILURE(ec)) {
2601 errln("FAIL: StringEnumeration::unext");
2602 break;
2603 }
2604
2605 TimeZone *t = TimeZone::createTimeZone(id);
2606 if (t == NULL) {
2607 errln("FAIL: TimeZone::createTimeZone");
2608 break;
2609 }
2610 dateFormat.setTimeZone(*t);
2611
2612 Calendar *cal = Calendar::createInstance(t, locale, ec);
2613 if (cal == NULL || U_FAILURE(ec)) {
2614 errln("FAIL: Calendar::createTimeZone");
2615 delete cal;
2616 break;
2617 }
2618
2619 cal->clear();
2620 // Scan the year 2003, overlapping the edges of the year
2621 cal->set(UCAL_YEAR, 2002);
2622 cal->set(UCAL_MONTH, UCAL_DECEMBER);
2623 cal->set(UCAL_DATE, 25);
2624
2625 for (int32_t i=0; i<365+10 && U_SUCCESS(ec); ++i) {
2626 UDate yesterday = cal->getTime(ec);
2627 int32_t yesterday_day = cal->get(UCAL_DATE, ec);
2628 cal->add(UCAL_DATE, 1, ec);
2629 if (yesterday_day == cal->get(UCAL_DATE, ec)) {
2630 errln(UnicodeString(id) + " " +
2631 dateFormat.format(yesterday, buf1) + " +1d= " +
2632 dateFormat.format(cal->getTime(ec), buf2));
2633 buf1.truncate(0);
2634 buf2.truncate(0);
2635 }
2636 }
2637 delete cal;
2638 }
2639
2640 if (U_FAILURE(ec)) {
2641 dataerrln("FAIL: %s", u_errorName(ec));
2642 }
2643
2644 delete tz;
2645 }
2646
2647 UDate
makeDate(int32_t y,int32_t m,int32_t d,int32_t hr,int32_t min,int32_t sec)2648 CalendarRegressionTest::makeDate(int32_t y, int32_t m, int32_t d,
2649 int32_t hr, int32_t min, int32_t sec)
2650 {
2651 UDate result;
2652
2653 UErrorCode status = U_ZERO_ERROR;
2654 Calendar *cal = Calendar::createInstance(status);
2655 cal->clear();
2656
2657 cal->set(UCAL_YEAR, y);
2658
2659 if(m != 0) cal->set(UCAL_MONTH, m);
2660 if(d != 0) cal->set(UCAL_DATE, d);
2661 if(hr != 0) cal->set(UCAL_HOUR, hr);
2662 if(min != 0) cal->set(UCAL_MINUTE, min);
2663 if(sec != 0) cal->set(UCAL_SECOND, sec);
2664
2665 result = cal->getTime(status);
2666
2667 delete cal;
2668
2669 return result;
2670 }
2671
TestDeprecates(void)2672 void CalendarRegressionTest::TestDeprecates(void)
2673 {
2674 UErrorCode status = U_ZERO_ERROR;
2675 Calendar *c1 = Calendar::createInstance("ja_JP@calendar=japanese",status);
2676 Calendar *c2 = Calendar::createInstance("ja_JP_TRADITIONAL",status);
2677
2678 if(!c1 || !c2 || U_FAILURE(status)) {
2679 dataerrln("Couldn't create calendars for roll of HOUR: %s", u_errorName(status));
2680 return;
2681 }
2682
2683 c2->set(UCAL_HOUR,2);
2684 c1->setTime(c2->getTime(status),status);
2685 // *c1 = *c2;
2686
2687 c1->roll(Calendar::HOUR,(int32_t)3,status);
2688 c2->roll(UCAL_HOUR,(int32_t)3,status);
2689
2690 if(U_FAILURE(status)) {
2691 errln("Error code when trying to roll");
2692 } else if(*c1 != *c2) {
2693 errln("roll(EDateField, int32_t) had different effect than roll(UCalendarField, int32_t)");
2694 }
2695
2696 c1->setTime(c2->getTime(status),status);
2697 c1->roll(Calendar::HOUR,(UBool)FALSE,status);
2698 c2->roll(UCAL_HOUR,(UBool)FALSE,status);
2699
2700 if(U_FAILURE(status)) {
2701 errln("Error code when trying to roll(UBool)");
2702 } else if(*c1 != *c2) {
2703 errln("roll(EDateField, UBool) had different effect than roll(UCalendarField, UBool)");
2704 }
2705
2706 delete c1;
2707 delete c2;
2708
2709 status = U_ZERO_ERROR;
2710
2711 c1 = Calendar::createInstance("th_TH_TRADITIONAL",status);
2712 c2 = Calendar::createInstance("th_TH@calendar=buddhist",status);
2713
2714 if(!c1 || !c2 || U_FAILURE(status)) {
2715 errln("Couldn't create calendars for add of HOUR");
2716 return;
2717 }
2718
2719 c2->set(UCAL_HOUR,2);
2720 c1->setTime(c2->getTime(status),status);
2721 //*c1 = *c2;
2722
2723 c1->add(Calendar::HOUR,(int32_t)1,status);
2724
2725 if(U_FAILURE(status)) {
2726 errln("Error code when trying to add Calendar::HOUR - %s", u_errorName(status));
2727 }
2728
2729 c2->add(UCAL_HOUR,(int32_t)1,status);
2730
2731 if(U_FAILURE(status)) {
2732 errln("Error code when trying to add - UCAL_HOUR %s", u_errorName(status));
2733 } else if(*c1 != *c2) {
2734 errln("add(EDateField) had different effect than add(UCalendarField)");
2735 }
2736
2737 delete c1;
2738 delete c2;
2739
2740 status = U_ZERO_ERROR;
2741
2742 c1 = Calendar::createInstance("es_ES",status);
2743 c2 = Calendar::createInstance("es_ES",status);
2744
2745 if(!c1 || !c2 || U_FAILURE(status)) {
2746 errln("Couldn't create calendars for add of YEAR");
2747 return;
2748 }
2749
2750 c2->set(UCAL_YEAR,1900);
2751 c1->setTime(c2->getTime(status),status);
2752 //*c1 = *c2;
2753
2754 c1->add(Calendar::YEAR,(int32_t)9,status);
2755 c2->add(UCAL_YEAR,(int32_t)9,status);
2756
2757 if(U_FAILURE(status)) {
2758 errln("Error code when trying to add YEARs");
2759 } else if(*c1 != *c2) {
2760 errln("add(EDateField YEAR) had different effect than add(UCalendarField YEAR)");
2761 }
2762
2763 delete c1;
2764 delete c2;
2765 }
2766
2767
2768 #endif /* #if !UCONFIG_NO_FORMATTING */
2769