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