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