1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2013, 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
29const UDate CalendarRegressionTest::EARLIEST_SUPPORTED_MILLIS = - 4503599627370495.0;
30const 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
34void
35CalendarRegressionTest::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
95const 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
117UBool
118CalendarRegressionTest::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 */
131void
132CalendarRegressionTest::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 */
154void
155CalendarRegressionTest::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
177void
178CalendarRegressionTest::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
201void
202CalendarRegressionTest::Test9019()
203{
204    UErrorCode status = U_ZERO_ERROR;
205    LocalPointer<GregorianCalendar> cal1(new GregorianCalendar(status));
206    LocalPointer<GregorianCalendar> cal2(new GregorianCalendar(status));
207    cal1->set(UCAL_HOUR, 1);
208    cal2->set(UCAL_HOUR,2);
209    cal1->clear();
210    cal2->clear();
211    if(U_FAILURE(status)) {
212      dataerrln("Error creating Calendar: %s", u_errorName(status));
213      return;
214    }
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
231void
232CalendarRegressionTest::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 */
248void
249CalendarRegressionTest::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 */
300void 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 */
319void 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 */
370void 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
394void 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 */
454void 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 */
483void 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 */
516void 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 */
541UDate
542CalendarRegressionTest::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 */
566void CalendarRegressionTest::test4071197()
567{
568    dowTest(FALSE);
569    dowTest(TRUE);
570}
571
572void 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 */
629void 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 */
650void 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 */
701void 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 */
748void 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
788delete newZone;
789delete cal;
790delete date;
791delete saveZone;
792}
793
794/**
795 * @bug 4092362
796 */
797void 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 */
837void 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 */
856void 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 */
926void 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 */
959void 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 */
980void 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 */
1230void 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 */
1261void 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 */
1310void 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 */
1379void 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 */
1437void 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 */
1472void 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 */
1506void 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 */
1535void 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 */
1569void 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.
1608void 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 */
1639void 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 */
1679void
1680CalendarRegressionTest::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 */
1739void
1740CalendarRegressionTest::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 */
1796void
1797CalendarRegressionTest::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 */
1838void
1839CalendarRegressionTest::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 */
1893void
1894CalendarRegressionTest::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 */
1983void 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 */
2047void 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 */
2259void 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
2362void 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
2398typedef 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)
2413static 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
2426typedef struct {
2427    const char * locale;
2428    int32_t      yearOffset;
2429} CoptEthCalLocale;
2430
2431static const CoptEthCalLocale copEthCalLocales[] = {
2432    { "en@calendar=coptic",   0    },
2433    { "en@calendar=ethiopic", 276  },
2434    { NULL,                   0    } // terminator
2435};
2436
2437void 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 */
2476void 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 */
2548void 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 */
2563void 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 */
2641void 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
2703UDate
2704CalendarRegressionTest::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
2728void 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
2824void 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.
2863void 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
2905void 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