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