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