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