1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/***********************************************************************
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * COPYRIGHT:
38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius * Copyright (c) 1997-2013, International Business Machines Corporation
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * and others. All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru ***********************************************************************/
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "callimts.h"
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "caltest.h"
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/calendar.h"
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/gregocal.h"
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/datefmt.h"
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/smpdtfmt.h"
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "putilimp.h"
18c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "cstring.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_USE
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid CalendarLimitTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (exec) logln("TestSuite TestCalendarLimit");
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (index) {
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Re-enable this later
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        case 0:
27c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            name = "TestCalendarExtremeLimit";
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (exec) {
29c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                logln("TestCalendarExtremeLimit---"); logln("");
30c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                TestCalendarExtremeLimit();
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
33c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        case 1:
34c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            name = "TestLimits";
35c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (exec) {
36c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                logln("TestLimits---"); logln("");
37c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                TestLimits();
38c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
39c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            break;
40c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default: name = ""; break;
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// class CalendarLimitTest
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
52103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusCalendarLimitTest::test(UDate millis, icu::Calendar* cal, icu::DateFormat* fmt)
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  static const UDate kDrift = 1e-10;
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode exception = U_ZERO_ERROR;
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString theDate;
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cal->setTime(millis, exception);
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(exception)) {
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fmt->format(millis, theDate);
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UDate dt = fmt->parse(theDate, status);
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // allow a small amount of error (drift)
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(! withinErr(dt, millis, kDrift)) {
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          errln("FAIL:round trip for large milli, got: %.1lf wanted: %.1lf. (delta %.2lf greater than %.2lf)",
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                dt, millis, uprv_fabs(millis-dt), uprv_fabs(dt*kDrift));
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          logln(UnicodeString("   ") + theDate + " " + CalendarTest::calToStr(*cal));
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          } else {
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logln(UnicodeString("OK: got ") + dt + ", wanted " + millis);
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            logln(UnicodeString("    ") + theDate);
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// bug 986c: deprecate nextDouble/previousDouble
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|double
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|CalendarLimitTest::nextDouble(double a)
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|{
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|    return uprv_nextDouble(a, TRUE);
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|}
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|double
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|CalendarLimitTest::previousDouble(double a)
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|{
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|    return uprv_nextDouble(a, FALSE);
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//|}
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruCalendarLimitTest::withinErr(double a, double b, double err)
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return ( uprv_fabs(a - b) < uprv_fabs(a * err) );
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
96c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruCalendarLimitTest::TestCalendarExtremeLimit()
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Calendar *cal = Calendar::createInstance(status);
10050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if (failure(status, "Calendar::createInstance", TRUE)) return;
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cal->adoptTimeZone(TimeZone::createTimeZone("GMT"));
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DateFormat *fmt = DateFormat::createDateTimeInstance();
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(!fmt || !cal) {
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       dataerrln("can't open cal and/or fmt");
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru       return;
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    fmt->adoptCalendar(cal);
108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ((SimpleDateFormat*) fmt)->applyPattern("HH:mm:ss.SSS Z, EEEE, MMMM d, yyyy G");
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // This test used to test the algorithmic limits of the dates that
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // GregorianCalendar could handle.  However, the algorithm has
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // been rewritten completely since then and the prior limits no
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // longer apply.  Instead, we now do basic round-trip testing of
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // some extreme (but still manageable) dates.
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate m;
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln("checking 1e16..1e17");
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for ( m = 1e16; m < 1e17; m *= 1.1) {
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        test(m, cal, fmt);
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln("checking -1e14..-1e15");
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for ( m = -1e14; m > -1e15; m *= 1.1) {
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        test(m, cal, fmt);
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // This is 2^52 - 1, the largest allowable mantissa with a 0
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // exponent in a 64-bit double
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate VERY_EARLY_MILLIS = - 4503599627370495.0;
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate VERY_LATE_MILLIS  =   4503599627370495.0;
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // I am removing the previousDouble and nextDouble calls below for
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // two reasons: 1. As part of jitterbug 986, I am deprecating
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // these methods and removing calls to them.  2. This test is a
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // non-critical boundary behavior test.
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    test(VERY_EARLY_MILLIS, cal, fmt);
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //test(previousDouble(VERY_EARLY_MILLIS), cal, fmt);
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    test(VERY_LATE_MILLIS, cal, fmt);
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    //test(nextDouble(VERY_LATE_MILLIS), cal, fmt);
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete fmt;
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
142c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
143c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruCalendarLimitTest::TestLimits(void) {
144c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    static const UDate DEFAULT_START = 944006400000.0; // 1999-12-01T00:00Z
14550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    static const int32_t DEFAULT_END = -120; // Default for non-quick is run 2 minutes
146c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
147c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    static const struct {
148c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        const char *type;
149c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UBool hasLeapMonth;
150c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UDate actualTestStart;
15150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t actualTestEnd;
152c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } TestCases[] = {
15350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"gregorian",       FALSE,      DEFAULT_START, DEFAULT_END},
15450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"japanese",        FALSE,      596937600000.0, DEFAULT_END}, // 1988-12-01T00:00Z, Showa 63
15550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"buddhist",        FALSE,      DEFAULT_START, DEFAULT_END},
15650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"roc",             FALSE,      DEFAULT_START, DEFAULT_END},
15750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"persian",         FALSE,      DEFAULT_START, DEFAULT_END},
15850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"islamic-civil",   FALSE,      DEFAULT_START, DEFAULT_END},
15950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"islamic",         FALSE,      DEFAULT_START, 800000}, // Approx. 2250 years from now, after which some rounding errors occur in Islamic calendar
16050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"hebrew",          TRUE,       DEFAULT_START, DEFAULT_END},
16150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"chinese",         TRUE,       DEFAULT_START, DEFAULT_END},
1628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {"dangi",           TRUE,       DEFAULT_START, DEFAULT_END},
16350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"indian",          FALSE,      DEFAULT_START, DEFAULT_END},
16450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"coptic",          FALSE,      DEFAULT_START, DEFAULT_END},
16550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"ethiopic",        FALSE,      DEFAULT_START, DEFAULT_END},
16650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        {"ethiopic-amete-alem", FALSE,  DEFAULT_START, DEFAULT_END},
16727f654740f2a26ad62a5c155af9199af9e69b889claireho        {NULL,              FALSE,      0, 0}
168c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    };
169c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
170c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int16_t i = 0;
171c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    char buf[64];
172c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
173c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (i = 0; TestCases[i].type; i++) {
174c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
175c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        uprv_strcpy(buf, "root@calendar=");
176c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        strcat(buf, TestCases[i].type);
177c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        Calendar *cal = Calendar::createInstance(buf, status);
17850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (failure(status, "Calendar::createInstance", TRUE)) {
179c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            continue;
180c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
181c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (uprv_strcmp(cal->getType(), TestCases[i].type) != 0) {
182c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            errln((UnicodeString)"FAIL: Wrong calendar type: " + cal->getType()
183c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                + " Requested: " + TestCases[i].type);
184c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            delete cal;
185c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            continue;
186c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
187c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // Do the test
188c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        doTheoreticalLimitsTest(*cal, TestCases[i].hasLeapMonth);
18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        doLimitsTest(*cal, TestCases[i].actualTestStart,TestCases[i].actualTestEnd);
190c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        delete cal;
191c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
192c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
193c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
194c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
195c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruCalendarLimitTest::doTheoreticalLimitsTest(Calendar& cal, UBool leapMonth) {
196c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    const char* calType = cal.getType();
197c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
198c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t nDOW = cal.getMaximum(UCAL_DAY_OF_WEEK);
199c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t maxDOY = cal.getMaximum(UCAL_DAY_OF_YEAR);
200c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t lmaxDOW = cal.getLeastMaximum(UCAL_DAY_OF_YEAR);
201c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t maxWOY = cal.getMaximum(UCAL_WEEK_OF_YEAR);
202c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t lmaxWOY = cal.getLeastMaximum(UCAL_WEEK_OF_YEAR);
203c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t maxM = cal.getMaximum(UCAL_MONTH) + 1;
204c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t lmaxM = cal.getLeastMaximum(UCAL_MONTH) + 1;
205c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t maxDOM = cal.getMaximum(UCAL_DAY_OF_MONTH);
206c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t lmaxDOM = cal.getLeastMaximum(UCAL_DAY_OF_MONTH);
207c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t maxDOWIM = cal.getMaximum(UCAL_DAY_OF_WEEK_IN_MONTH);
208c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t lmaxDOWIM = cal.getLeastMaximum(UCAL_DAY_OF_WEEK_IN_MONTH);
209c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t maxWOM = cal.getMaximum(UCAL_WEEK_OF_MONTH);
210c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t lmaxWOM = cal.getLeastMaximum(UCAL_WEEK_OF_MONTH);
211c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t minDaysInFirstWeek = cal.getMinimalDaysInFirstWeek();
212c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
213c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Day of year
214c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t expected;
215c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (!leapMonth) {
216c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        expected = maxM*maxDOM;
217c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (maxDOY > expected) {
218c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            errln((UnicodeString)"FAIL: [" + calType + "] Maximum value of DAY_OF_YEAR is too big: "
219c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                + maxDOY + "/expected: <=" + expected);
220c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
221c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        expected = lmaxM*lmaxDOM;
222c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (lmaxDOW < expected) {
223c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            errln((UnicodeString)"FAIL: [" + calType + "] Least maximum value of DAY_OF_YEAR is too small: "
224c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                + lmaxDOW + "/expected: >=" + expected);
225c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
226c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
227c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
228c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Week of year
229c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    expected = maxDOY/nDOW + 1;
230c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (maxWOY > expected) {
231c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        errln((UnicodeString)"FAIL: [" + calType + "] Maximum value of WEEK_OF_YEAR is too big: "
232c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            + maxWOY + "/expected: <=" + expected);
233c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
234c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    expected = lmaxDOW/nDOW;
235c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (lmaxWOY < expected) {
236c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        errln((UnicodeString)"FAIL: [" + calType + "] Least maximum value of WEEK_OF_YEAR is too small: "
237c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            + lmaxWOY + "/expected >=" + expected);
238c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
239c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
240c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Day of week in month
241c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    expected = (maxDOM + nDOW - 1)/nDOW;
242c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (maxDOWIM != expected) {
243c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        errln((UnicodeString)"FAIL: [" + calType + "] Maximum value of DAY_OF_WEEK_IN_MONTH is incorrect: "
244c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            + maxDOWIM + "/expected: " + expected);
245c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
246c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    expected = (lmaxDOM + nDOW - 1)/nDOW;
247c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (lmaxDOWIM != expected) {
248c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        errln((UnicodeString)"FAIL: [" + calType + "] Least maximum value of DAY_OF_WEEK_IN_MONTH is incorrect: "
249c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            + lmaxDOWIM + "/expected: " + expected);
250c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
251c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
252c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Week of month
253c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    expected = (maxDOM + (nDOW - 1) + (nDOW - minDaysInFirstWeek)) / nDOW;
254c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (maxWOM != expected) {
255c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        errln((UnicodeString)"FAIL: [" + calType + "] Maximum value of WEEK_OF_MONTH is incorrect: "
256c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            + maxWOM + "/expected: " + expected);
257c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
258c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    expected = (lmaxDOM + (nDOW - minDaysInFirstWeek)) / nDOW;
259c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (lmaxWOM != expected) {
260c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        errln((UnicodeString)"FAIL: [" + calType + "] Least maximum value of WEEK_OF_MONTH is incorrect: "
261c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            + lmaxWOM + "/expected: " + expected);
262c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
263c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
265c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
26650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoCalendarLimitTest::doLimitsTest(Calendar& cal, UDate startDate, int32_t endTime) {
26750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t testTime = quick ? ( endTime / 40 ) : endTime;
268c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    doLimitsTest(cal, NULL /*default fields*/, startDate, testTime);
269c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
270c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
271c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queruvoid
272c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruCalendarLimitTest::doLimitsTest(Calendar& cal,
273c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                const int32_t* fieldsToTest,
274c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                UDate startDate,
275c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                                int32_t testDuration) {
276c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    static const int32_t FIELDS[] = {
277c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCAL_ERA,
278c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCAL_YEAR,
279c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCAL_MONTH,
280c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCAL_WEEK_OF_YEAR,
281c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCAL_WEEK_OF_MONTH,
282c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCAL_DAY_OF_MONTH,
283c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCAL_DAY_OF_YEAR,
284c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCAL_DAY_OF_WEEK_IN_MONTH,
285c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCAL_YEAR_WOY,
286c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCAL_EXTENDED_YEAR,
287c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        -1,
288c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    };
289c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
290c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    static const char* FIELD_NAME[] = {
291c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH",
292c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK",
293c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", "HOUR_OF_DAY",
294c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
295c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        "DST_OFFSET", "YEAR_WOY", "DOW_LOCAL", "EXTENDED_YEAR",
296c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        "JULIAN_DAY", "MILLISECONDS_IN_DAY",
297c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        "IS_LEAP_MONTH"
298c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    };
299c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
300c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
301c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t i, j;
302c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString ymd;
303c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
304c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    GregorianCalendar greg(status);
305c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (failure(status, "new GregorianCalendar")) {
306c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
307c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
308c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    greg.setTime(startDate, status);
309c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (failure(status, "GregorianCalendar::setTime")) {
310c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return;
311c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
312c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    logln((UnicodeString)"Start: " + startDate);
313c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
314c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (fieldsToTest == NULL) {
315c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        fieldsToTest = FIELDS;
316c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
317c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
318c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
319c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Keep a record of minima and maxima that we actually see.
320c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // These are kept in an array of arrays of hashes.
321c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t limits[UCAL_FIELD_COUNT][4];
322c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (j = 0; j < UCAL_FIELD_COUNT; j++) {
323c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        limits[j][0] = INT32_MAX;
324c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        limits[j][1] = INT32_MIN;
325c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        limits[j][2] = INT32_MAX;
326c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        limits[j][3] = INT32_MIN;
327c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
328c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
329c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // This test can run for a long time; show progress.
330c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UDate millis = ucal_getNow();
331c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UDate mark = millis + 5000; // 5 sec
332c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    millis -= testDuration * 1000; // stop time if testDuration<0
333c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
334c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (i = 0;
335c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         testDuration > 0 ? i < testDuration
336c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        : ucal_getNow() < millis;
337c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru         ++i) {
338c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (ucal_getNow() >= mark) {
339c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            logln((UnicodeString)"(" + i + " days)");
340c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            mark += 5000; // 5 sec
341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
3428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        UDate testMillis = greg.getTime(status);
3438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        cal.setTime(testMillis, status);
344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        cal.setMinimalDaysInFirstWeek(1);
345c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (failure(status, "Calendar set/getTime")) {
346c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
347c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
348c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        for (j = 0; fieldsToTest[j] >= 0; ++j) {
349c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            UCalendarDateFields f = (UCalendarDateFields)fieldsToTest[j];
350c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t v = cal.get(f, status);
351c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t minActual = cal.getActualMinimum(f, status);
352c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t maxActual = cal.getActualMaximum(f, status);
353c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t minLow = cal.getMinimum(f);
354c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t minHigh = cal.getGreatestMinimum(f);
355c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t maxLow = cal.getLeastMaximum(f);
356c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            int32_t maxHigh = cal.getMaximum(f);
357c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
358c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (limits[j][0] > minActual) {
359c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // the minimum
360c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                limits[j][0] = minActual;
361c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
362c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (limits[j][1] < minActual) {
363c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // the greatest minimum
364c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                limits[j][1] = minActual;
365c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
366c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (limits[j][2] > maxActual) {
367c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // the least maximum
368c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                limits[j][2] = maxActual;
369c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
370c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (limits[j][3] < maxActual) {
371c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                // the maximum
372c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                limits[j][3] = maxActual;
373c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
374c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
375c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (minActual < minLow || minActual > minHigh) {
376c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                errln((UnicodeString)"Fail: [" + cal.getType() + "] " +
377c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      ymdToString(cal, ymd) +
378c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      " Range for min of " + FIELD_NAME[f] + "(" + f +
379c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      ")=" + minLow + ".." + minHigh +
380c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      ", actual_min=" + minActual);
381c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
382c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (maxActual < maxLow || maxActual > maxHigh) {
383c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                errln((UnicodeString)"Fail: [" + cal.getType() + "] " +
384c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      ymdToString(cal, ymd) +
385c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      " Range for max of " + FIELD_NAME[f] + "(" + f +
386c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      ")=" + maxLow + ".." + maxHigh +
387c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                      ", actual_max=" + maxActual);
388c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
389c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (v < minActual || v > maxActual) {
3908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                // timebomb per #9967, fix with #9972
39159d709d503bab6e2b61931737e662dd293b40578ccornelius                if ( uprv_strcmp(cal.getType(), "dangi") == 0 &&
39259d709d503bab6e2b61931737e662dd293b40578ccornelius                        testMillis >= 1865635198000.0  &&
39359d709d503bab6e2b61931737e662dd293b40578ccornelius                     logKnownIssue("9972", "as per #9967")) { // Feb 2029 gregorian, end of dangi 4361
3948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    logln((UnicodeString)"Fail: [" + cal.getType() + "] " +
3958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                          ymdToString(cal, ymd) +
3968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                          " " + FIELD_NAME[f] + "(" + f + ")=" + v +
3978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                          ", actual=" + minActual + ".." + maxActual +
3988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                          ", allowed=(" + minLow + ".." + minHigh + ")..(" +
3998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                          maxLow + ".." + maxHigh + ")");
4008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                } else {
4018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    errln((UnicodeString)"Fail: [" + cal.getType() + "] " +
4028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                          ymdToString(cal, ymd) +
4038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                          " " + FIELD_NAME[f] + "(" + f + ")=" + v +
4048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                          ", actual=" + minActual + ".." + maxActual +
4058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                          ", allowed=(" + minLow + ".." + minHigh + ")..(" +
4068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                          maxLow + ".." + maxHigh + ")");
4078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                }
408c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
409c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
410c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        greg.add(UCAL_DAY_OF_YEAR, 1, status);
411c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (failure(status, "Calendar::add")) {
412c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
413c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
414c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
415c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
416c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Check actual maxima and minima seen against ranges returned
417c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // by API.
418c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UnicodeString buf;
419c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    for (j = 0; fieldsToTest[j] >= 0; ++j) {
420c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t rangeLow, rangeHigh;
421c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UBool fullRangeSeen = TRUE;
422c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UCalendarDateFields f = (UCalendarDateFields)fieldsToTest[j];
423c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
424c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        buf.remove();
425c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        buf.append((UnicodeString)"[" + cal.getType() + "] " + FIELD_NAME[f]);
426c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
427c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // Minumum
428c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        rangeLow = cal.getMinimum(f);
429c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        rangeHigh = cal.getGreatestMinimum(f);
430c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (limits[j][0] != rangeLow || limits[j][1] != rangeHigh) {
431c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fullRangeSeen = FALSE;
432c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
433c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        buf.append((UnicodeString)" minima range=" + rangeLow + ".." + rangeHigh);
434c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        buf.append((UnicodeString)" minima actual=" + limits[j][0] + ".." + limits[j][1]);
435c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
436c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // Maximum
437c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        rangeLow = cal.getLeastMaximum(f);
438c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        rangeHigh = cal.getMaximum(f);
439c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (limits[j][2] != rangeLow || limits[j][3] != rangeHigh) {
440c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            fullRangeSeen = FALSE;
441c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
442c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        buf.append((UnicodeString)" maxima range=" + rangeLow + ".." + rangeHigh);
443c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        buf.append((UnicodeString)" maxima actual=" + limits[j][2] + ".." + limits[j][3]);
444c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
445c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (fullRangeSeen) {
446c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            logln((UnicodeString)"OK: " + buf);
447c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // This may or may not be an error -- if the range of dates
449c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // we scan over doesn't happen to contain a minimum or
450c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            // maximum, it doesn't mean some other range won't.
451c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            logln((UnicodeString)"Warning: " + buf);
452c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
453c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
454c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    logln((UnicodeString)"End: " + greg.getTime(status));
456c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
457c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
458c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
459c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruCalendarLimitTest::ymdToString(const Calendar& cal, UnicodeString& str) {
460c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
461c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    str.remove();
462c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    str.append((UnicodeString)"" + cal.get(UCAL_EXTENDED_YEAR, status)
463c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        + "/" + (cal.get(UCAL_MONTH, status) + 1)
464c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        + (cal.get(UCAL_IS_LEAP_MONTH, status) == 1 ? "(leap)" : "")
465c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        + "/" + cal.get(UCAL_DATE, status)
4668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        + " " + cal.get(UCAL_HOUR_OF_DAY, status)
4678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        + ":" + cal.get(UCAL_MINUTE, status)
4688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        + " zone(hrs) " + cal.get(UCAL_ZONE_OFFSET, status)/(60.0*60.0*1000.0)
4698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        + " dst(hrs) " + cal.get(UCAL_DST_OFFSET, status)/(60.0*60.0*1000.0)
4708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        + ", time(millis)=" + cal.getTime(status));
471c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return str;
472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
473c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// eof
477