12e5b6d6dSopenharmony_ci// © 2016 and later: Unicode, Inc. and others.
22e5b6d6dSopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
32e5b6d6dSopenharmony_ci/*
42e5b6d6dSopenharmony_ci*******************************************************************************
52e5b6d6dSopenharmony_ci* Copyright (C) 2007-2016, International Business Machines Corporation and
62e5b6d6dSopenharmony_ci* others. All Rights Reserved.
72e5b6d6dSopenharmony_ci*******************************************************************************
82e5b6d6dSopenharmony_ci*/
92e5b6d6dSopenharmony_ci
102e5b6d6dSopenharmony_ci#include "unicode/utypes.h"
112e5b6d6dSopenharmony_ci
122e5b6d6dSopenharmony_ci#if !UCONFIG_NO_FORMATTING
132e5b6d6dSopenharmony_ci
142e5b6d6dSopenharmony_ci#include "unicode/dtrule.h"
152e5b6d6dSopenharmony_ci#include "unicode/tzrule.h"
162e5b6d6dSopenharmony_ci#include "unicode/rbtz.h"
172e5b6d6dSopenharmony_ci#include "unicode/simpletz.h"
182e5b6d6dSopenharmony_ci#include "unicode/tzrule.h"
192e5b6d6dSopenharmony_ci#include "unicode/calendar.h"
202e5b6d6dSopenharmony_ci#include "unicode/gregocal.h"
212e5b6d6dSopenharmony_ci#include "unicode/strenum.h"
222e5b6d6dSopenharmony_ci#include "unicode/ucal.h"
232e5b6d6dSopenharmony_ci#include "unicode/unistr.h"
242e5b6d6dSopenharmony_ci#include "unicode/ustring.h"
252e5b6d6dSopenharmony_ci#include "unicode/tztrans.h"
262e5b6d6dSopenharmony_ci#include "unicode/vtzone.h"
272e5b6d6dSopenharmony_ci#include "tzrulets.h"
282e5b6d6dSopenharmony_ci#include "zrule.h"
292e5b6d6dSopenharmony_ci#include "ztrans.h"
302e5b6d6dSopenharmony_ci#include "vzone.h"
312e5b6d6dSopenharmony_ci#include "cmemory.h"
322e5b6d6dSopenharmony_ci
332e5b6d6dSopenharmony_ci#define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); logln((UnicodeString)""); test(); } break
342e5b6d6dSopenharmony_ci#define HOUR (60*60*1000)
352e5b6d6dSopenharmony_ci
362e5b6d6dSopenharmony_cistatic const char *const TESTZIDS[] = {
372e5b6d6dSopenharmony_ci        "AGT",
382e5b6d6dSopenharmony_ci        "America/New_York",
392e5b6d6dSopenharmony_ci        "America/Los_Angeles",
402e5b6d6dSopenharmony_ci        "America/Indiana/Indianapolis",
412e5b6d6dSopenharmony_ci        "America/Havana",
422e5b6d6dSopenharmony_ci        "Europe/Lisbon",
432e5b6d6dSopenharmony_ci        "Europe/Paris",
442e5b6d6dSopenharmony_ci        "Asia/Tokyo",
452e5b6d6dSopenharmony_ci        "Asia/Sakhalin",
462e5b6d6dSopenharmony_ci        "Africa/Cairo",
472e5b6d6dSopenharmony_ci        "Africa/Windhoek",
482e5b6d6dSopenharmony_ci        "Australia/Sydney",
492e5b6d6dSopenharmony_ci        "Etc/GMT+8"
502e5b6d6dSopenharmony_ci};
512e5b6d6dSopenharmony_ci
522e5b6d6dSopenharmony_cistatic UBool hasEquivalentTransitions(/*const*/ BasicTimeZone& tz1, /*const*/BasicTimeZone& tz2,
532e5b6d6dSopenharmony_ci                                        UDate start, UDate end,
542e5b6d6dSopenharmony_ci                                        UBool ignoreDstAmount, int32_t maxTransitionTimeDelta,
552e5b6d6dSopenharmony_ci                                        UErrorCode& status);
562e5b6d6dSopenharmony_ci
572e5b6d6dSopenharmony_ciclass TestZIDEnumeration : public StringEnumeration {
582e5b6d6dSopenharmony_cipublic:
592e5b6d6dSopenharmony_ci    TestZIDEnumeration(UBool all = false);
602e5b6d6dSopenharmony_ci    ~TestZIDEnumeration();
612e5b6d6dSopenharmony_ci
622e5b6d6dSopenharmony_ci    virtual int32_t count(UErrorCode& /*status*/) const override {
632e5b6d6dSopenharmony_ci        return len;
642e5b6d6dSopenharmony_ci    }
652e5b6d6dSopenharmony_ci    virtual const UnicodeString *snext(UErrorCode& status) override;
662e5b6d6dSopenharmony_ci    virtual void reset(UErrorCode& status) override;
672e5b6d6dSopenharmony_ci    static inline UClassID getStaticClassID() {
682e5b6d6dSopenharmony_ci        return (UClassID)&fgClassID;
692e5b6d6dSopenharmony_ci    }
702e5b6d6dSopenharmony_ci    virtual UClassID getDynamicClassID() const override {
712e5b6d6dSopenharmony_ci        return getStaticClassID();
722e5b6d6dSopenharmony_ci    }
732e5b6d6dSopenharmony_ciprivate:
742e5b6d6dSopenharmony_ci    static const char fgClassID;
752e5b6d6dSopenharmony_ci    int32_t idx;
762e5b6d6dSopenharmony_ci    int32_t len;
772e5b6d6dSopenharmony_ci    StringEnumeration   *tzenum;
782e5b6d6dSopenharmony_ci};
792e5b6d6dSopenharmony_ci
802e5b6d6dSopenharmony_ciconst char TestZIDEnumeration::fgClassID = 0;
812e5b6d6dSopenharmony_ci
822e5b6d6dSopenharmony_ciTestZIDEnumeration::TestZIDEnumeration(UBool all)
832e5b6d6dSopenharmony_ci: idx(0) {
842e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
852e5b6d6dSopenharmony_ci    if (all) {
862e5b6d6dSopenharmony_ci        tzenum = TimeZone::createEnumeration(status);
872e5b6d6dSopenharmony_ci        len = tzenum->count(status);
882e5b6d6dSopenharmony_ci    } else {
892e5b6d6dSopenharmony_ci        tzenum = NULL;
902e5b6d6dSopenharmony_ci        len = UPRV_LENGTHOF(TESTZIDS);
912e5b6d6dSopenharmony_ci    }
922e5b6d6dSopenharmony_ci}
932e5b6d6dSopenharmony_ci
942e5b6d6dSopenharmony_ciTestZIDEnumeration::~TestZIDEnumeration() {
952e5b6d6dSopenharmony_ci    if (tzenum != NULL) {
962e5b6d6dSopenharmony_ci        delete tzenum;
972e5b6d6dSopenharmony_ci    }
982e5b6d6dSopenharmony_ci}
992e5b6d6dSopenharmony_ci
1002e5b6d6dSopenharmony_ciconst UnicodeString*
1012e5b6d6dSopenharmony_ciTestZIDEnumeration::snext(UErrorCode& status) {
1022e5b6d6dSopenharmony_ci    if (tzenum != NULL) {
1032e5b6d6dSopenharmony_ci        return tzenum->snext(status);
1042e5b6d6dSopenharmony_ci    } else if (U_SUCCESS(status) && idx < len) {
1052e5b6d6dSopenharmony_ci        unistr = UnicodeString(TESTZIDS[idx++], "");
1062e5b6d6dSopenharmony_ci        return &unistr;
1072e5b6d6dSopenharmony_ci    }
1082e5b6d6dSopenharmony_ci    return NULL;
1092e5b6d6dSopenharmony_ci}
1102e5b6d6dSopenharmony_ci
1112e5b6d6dSopenharmony_civoid
1122e5b6d6dSopenharmony_ciTestZIDEnumeration::reset(UErrorCode& status) {
1132e5b6d6dSopenharmony_ci    if (tzenum != NULL) {
1142e5b6d6dSopenharmony_ci        tzenum->reset(status);
1152e5b6d6dSopenharmony_ci    } else {
1162e5b6d6dSopenharmony_ci        idx = 0;
1172e5b6d6dSopenharmony_ci    }
1182e5b6d6dSopenharmony_ci}
1192e5b6d6dSopenharmony_ci
1202e5b6d6dSopenharmony_ci
1212e5b6d6dSopenharmony_civoid TimeZoneRuleTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
1222e5b6d6dSopenharmony_ci{
1232e5b6d6dSopenharmony_ci    if (exec) {
1242e5b6d6dSopenharmony_ci        logln("TestSuite TestTimeZoneRule");
1252e5b6d6dSopenharmony_ci    }
1262e5b6d6dSopenharmony_ci    switch (index) {
1272e5b6d6dSopenharmony_ci        CASE(0, TestSimpleRuleBasedTimeZone);
1282e5b6d6dSopenharmony_ci        CASE(1, TestHistoricalRuleBasedTimeZone);
1292e5b6d6dSopenharmony_ci        CASE(2, TestOlsonTransition);
1302e5b6d6dSopenharmony_ci        CASE(3, TestRBTZTransition);
1312e5b6d6dSopenharmony_ci        CASE(4, TestHasEquivalentTransitions);
1322e5b6d6dSopenharmony_ci        CASE(5, TestVTimeZoneRoundTrip);
1332e5b6d6dSopenharmony_ci        CASE(6, TestVTimeZoneRoundTripPartial);
1342e5b6d6dSopenharmony_ci        CASE(7, TestVTimeZoneSimpleWrite);
1352e5b6d6dSopenharmony_ci        CASE(8, TestVTimeZoneHeaderProps);
1362e5b6d6dSopenharmony_ci        CASE(9, TestGetSimpleRules);
1372e5b6d6dSopenharmony_ci        CASE(10, TestTimeZoneRuleCoverage);
1382e5b6d6dSopenharmony_ci        CASE(11, TestSimpleTimeZoneCoverage);
1392e5b6d6dSopenharmony_ci        CASE(12, TestVTimeZoneCoverage);
1402e5b6d6dSopenharmony_ci        CASE(13, TestVTimeZoneParse);
1412e5b6d6dSopenharmony_ci        CASE(14, TestT6216);
1422e5b6d6dSopenharmony_ci        CASE(15, TestT6669);
1432e5b6d6dSopenharmony_ci        CASE(16, TestVTimeZoneWrapper);
1442e5b6d6dSopenharmony_ci        CASE(17, TestT8943);
1452e5b6d6dSopenharmony_ci        default: name = ""; break;
1462e5b6d6dSopenharmony_ci    }
1472e5b6d6dSopenharmony_ci}
1482e5b6d6dSopenharmony_ci
1492e5b6d6dSopenharmony_ci/*
1502e5b6d6dSopenharmony_ci * Compare SimpleTimeZone with equivalent RBTZ
1512e5b6d6dSopenharmony_ci */
1522e5b6d6dSopenharmony_civoid
1532e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestSimpleRuleBasedTimeZone(void) {
1542e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
1552e5b6d6dSopenharmony_ci    SimpleTimeZone stz(-1*HOUR, "TestSTZ",
1562e5b6d6dSopenharmony_ci        UCAL_SEPTEMBER, -30, -UCAL_SATURDAY, 1*HOUR, SimpleTimeZone::WALL_TIME,
1572e5b6d6dSopenharmony_ci        UCAL_FEBRUARY, 2, UCAL_SUNDAY, 1*HOUR, SimpleTimeZone::WALL_TIME,
1582e5b6d6dSopenharmony_ci        1*HOUR, status);
1592e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
1602e5b6d6dSopenharmony_ci        errln("FAIL: Couldn't create SimpleTimezone.");
1612e5b6d6dSopenharmony_ci    }
1622e5b6d6dSopenharmony_ci
1632e5b6d6dSopenharmony_ci    DateTimeRule *dtr;
1642e5b6d6dSopenharmony_ci    AnnualTimeZoneRule *atzr;
1652e5b6d6dSopenharmony_ci    int32_t STARTYEAR = 2000;
1662e5b6d6dSopenharmony_ci
1672e5b6d6dSopenharmony_ci    InitialTimeZoneRule *ir = new InitialTimeZoneRule(
1682e5b6d6dSopenharmony_ci        "RBTZ_Initial", // Initial time Name
1692e5b6d6dSopenharmony_ci        -1*HOUR,        // Raw offset
1702e5b6d6dSopenharmony_ci        1*HOUR);        // DST saving amount
1712e5b6d6dSopenharmony_ci
1722e5b6d6dSopenharmony_ci    // Original rules
1732e5b6d6dSopenharmony_ci    RuleBasedTimeZone *rbtz1 = new RuleBasedTimeZone("RBTZ1", ir->clone());
1742e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_SEPTEMBER, 30, UCAL_SATURDAY, false,
1752e5b6d6dSopenharmony_ci        1*HOUR, DateTimeRule::WALL_TIME); // SUN<=30 in September, at 1AM wall time
1762e5b6d6dSopenharmony_ci    atzr = new AnnualTimeZoneRule("RBTZ_DST1",
1772e5b6d6dSopenharmony_ci        -1*HOUR /*rawOffset*/, 1*HOUR /*dstSavings*/, dtr,
1782e5b6d6dSopenharmony_ci        STARTYEAR, AnnualTimeZoneRule::MAX_YEAR);
1792e5b6d6dSopenharmony_ci    rbtz1->addTransitionRule(atzr, status);
1802e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
1812e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 1-1.");
1822e5b6d6dSopenharmony_ci    }
1832e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_FEBRUARY, 2, UCAL_SUNDAY,
1842e5b6d6dSopenharmony_ci        1*HOUR, DateTimeRule::WALL_TIME);  // 2nd Sunday in February, at 1AM wall time
1852e5b6d6dSopenharmony_ci    atzr = new AnnualTimeZoneRule("RBTZ_STD1",
1862e5b6d6dSopenharmony_ci        -1*HOUR /*rawOffset*/, 0 /*dstSavings*/, dtr,
1872e5b6d6dSopenharmony_ci        STARTYEAR, AnnualTimeZoneRule::MAX_YEAR);
1882e5b6d6dSopenharmony_ci    rbtz1->addTransitionRule(atzr, status);
1892e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
1902e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 1-2.");
1912e5b6d6dSopenharmony_ci    }
1922e5b6d6dSopenharmony_ci    rbtz1->complete(status);
1932e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
1942e5b6d6dSopenharmony_ci        errln("FAIL: couldn't complete RBTZ 1.");
1952e5b6d6dSopenharmony_ci    }
1962e5b6d6dSopenharmony_ci
1972e5b6d6dSopenharmony_ci    // Equivalent, but different date rule type
1982e5b6d6dSopenharmony_ci    RuleBasedTimeZone *rbtz2 = new RuleBasedTimeZone("RBTZ2", ir->clone());
1992e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_SEPTEMBER, -1, UCAL_SATURDAY,
2002e5b6d6dSopenharmony_ci        1*HOUR, DateTimeRule::WALL_TIME); // Last Sunday in September at 1AM wall time
2012e5b6d6dSopenharmony_ci    atzr = new AnnualTimeZoneRule("RBTZ_DST2", -1*HOUR, 1*HOUR, dtr, STARTYEAR, AnnualTimeZoneRule::MAX_YEAR);
2022e5b6d6dSopenharmony_ci    rbtz2->addTransitionRule(atzr, status);
2032e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
2042e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 2-1.");
2052e5b6d6dSopenharmony_ci    }
2062e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_FEBRUARY, 8, UCAL_SUNDAY, true,
2072e5b6d6dSopenharmony_ci        1*HOUR, DateTimeRule::WALL_TIME); // SUN>=8 in February, at 1AM wall time
2082e5b6d6dSopenharmony_ci    atzr = new AnnualTimeZoneRule("RBTZ_STD2", -1*HOUR, 0, dtr, STARTYEAR, AnnualTimeZoneRule::MAX_YEAR);
2092e5b6d6dSopenharmony_ci    rbtz2->addTransitionRule(atzr, status);
2102e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
2112e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 2-2.");
2122e5b6d6dSopenharmony_ci    }
2132e5b6d6dSopenharmony_ci    rbtz2->complete(status);
2142e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
2152e5b6d6dSopenharmony_ci        errln("FAIL: couldn't complete RBTZ 2");
2162e5b6d6dSopenharmony_ci    }
2172e5b6d6dSopenharmony_ci
2182e5b6d6dSopenharmony_ci    // Equivalent, but different time rule type
2192e5b6d6dSopenharmony_ci    RuleBasedTimeZone *rbtz3 = new RuleBasedTimeZone("RBTZ3", ir->clone());
2202e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_SEPTEMBER, 30, UCAL_SATURDAY, false,
2212e5b6d6dSopenharmony_ci        2*HOUR, DateTimeRule::UTC_TIME);
2222e5b6d6dSopenharmony_ci    atzr = new AnnualTimeZoneRule("RBTZ_DST3", -1*HOUR, 1*HOUR, dtr, STARTYEAR, AnnualTimeZoneRule::MAX_YEAR);
2232e5b6d6dSopenharmony_ci    rbtz3->addTransitionRule(atzr, status);
2242e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
2252e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 3-1.");
2262e5b6d6dSopenharmony_ci    }
2272e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_FEBRUARY, 2, UCAL_SUNDAY,
2282e5b6d6dSopenharmony_ci        0*HOUR, DateTimeRule::STANDARD_TIME);
2292e5b6d6dSopenharmony_ci    atzr = new AnnualTimeZoneRule("RBTZ_STD3", -1*HOUR, 0, dtr, STARTYEAR, AnnualTimeZoneRule::MAX_YEAR);
2302e5b6d6dSopenharmony_ci    rbtz3->addTransitionRule(atzr, status);
2312e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
2322e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 3-2.");
2332e5b6d6dSopenharmony_ci    }
2342e5b6d6dSopenharmony_ci    rbtz3->complete(status);
2352e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
2362e5b6d6dSopenharmony_ci        errln("FAIL: couldn't complete RBTZ 3");
2372e5b6d6dSopenharmony_ci    }
2382e5b6d6dSopenharmony_ci
2392e5b6d6dSopenharmony_ci    // Check equivalency for 10 years
2402e5b6d6dSopenharmony_ci    UDate start = getUTCMillis(STARTYEAR, UCAL_JANUARY, 1);
2412e5b6d6dSopenharmony_ci    UDate until = getUTCMillis(STARTYEAR + 10, UCAL_JANUARY, 1);
2422e5b6d6dSopenharmony_ci
2432e5b6d6dSopenharmony_ci    if (!(stz.hasEquivalentTransitions(*rbtz1, start, until, true, status))) {
2442e5b6d6dSopenharmony_ci        errln("FAIL: rbtz1 must be equivalent to the SimpleTimeZone in the time range.");
2452e5b6d6dSopenharmony_ci    }
2462e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
2472e5b6d6dSopenharmony_ci        errln("FAIL: error returned from hasEquivalentTransitions");
2482e5b6d6dSopenharmony_ci    }
2492e5b6d6dSopenharmony_ci    if (!(stz.hasEquivalentTransitions(*rbtz2, start, until, true, status))) {
2502e5b6d6dSopenharmony_ci        errln("FAIL: rbtz2 must be equivalent to the SimpleTimeZone in the time range.");
2512e5b6d6dSopenharmony_ci    }
2522e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
2532e5b6d6dSopenharmony_ci        errln("FAIL: error returned from hasEquivalentTransitions");
2542e5b6d6dSopenharmony_ci    }
2552e5b6d6dSopenharmony_ci    if (!(stz.hasEquivalentTransitions(*rbtz3, start, until, true, status))) {
2562e5b6d6dSopenharmony_ci        errln("FAIL: rbtz3 must be equivalent to the SimpleTimeZone in the time range.");
2572e5b6d6dSopenharmony_ci    }
2582e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
2592e5b6d6dSopenharmony_ci        errln("FAIL: error returned from hasEquivalentTransitions");
2602e5b6d6dSopenharmony_ci    }
2612e5b6d6dSopenharmony_ci
2622e5b6d6dSopenharmony_ci    // hasSameRules
2632e5b6d6dSopenharmony_ci    if (rbtz1->hasSameRules(*rbtz2)) {
2642e5b6d6dSopenharmony_ci        errln("FAIL: rbtz1 and rbtz2 have different rules, but returned true.");
2652e5b6d6dSopenharmony_ci    }
2662e5b6d6dSopenharmony_ci    if (rbtz1->hasSameRules(*rbtz3)) {
2672e5b6d6dSopenharmony_ci        errln("FAIL: rbtz1 and rbtz3 have different rules, but returned true.");
2682e5b6d6dSopenharmony_ci    }
2692e5b6d6dSopenharmony_ci    RuleBasedTimeZone *rbtz1c = rbtz1->clone();
2702e5b6d6dSopenharmony_ci    if (!rbtz1->hasSameRules(*rbtz1c)) {
2712e5b6d6dSopenharmony_ci        errln("FAIL: Cloned RuleBasedTimeZone must have the same rules with the original.");
2722e5b6d6dSopenharmony_ci    }
2732e5b6d6dSopenharmony_ci
2742e5b6d6dSopenharmony_ci    // getOffset
2752e5b6d6dSopenharmony_ci    int32_t era, year, month, dayOfMonth, dayOfWeek, millisInDay;
2762e5b6d6dSopenharmony_ci    UDate time;
2772e5b6d6dSopenharmony_ci    int32_t offset, dstSavings;
2782e5b6d6dSopenharmony_ci    UBool dst;
2792e5b6d6dSopenharmony_ci
2802e5b6d6dSopenharmony_ci    GregorianCalendar *cal = new GregorianCalendar(status);
2812e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
2822e5b6d6dSopenharmony_ci        dataerrln("FAIL: Could not create a Gregorian calendar instance.: %s", u_errorName(status));
2832e5b6d6dSopenharmony_ci        delete rbtz1;
2842e5b6d6dSopenharmony_ci        delete rbtz2;
2852e5b6d6dSopenharmony_ci        delete rbtz3;
2862e5b6d6dSopenharmony_ci        delete rbtz1c;
2872e5b6d6dSopenharmony_ci        return;
2882e5b6d6dSopenharmony_ci    }
2892e5b6d6dSopenharmony_ci    cal->setTimeZone(*rbtz1);
2902e5b6d6dSopenharmony_ci    cal->clear();
2912e5b6d6dSopenharmony_ci
2922e5b6d6dSopenharmony_ci    // Jan 1, 1000 BC
2932e5b6d6dSopenharmony_ci    cal->set(UCAL_ERA, GregorianCalendar::BC);
2942e5b6d6dSopenharmony_ci    cal->set(1000, UCAL_JANUARY, 1);
2952e5b6d6dSopenharmony_ci
2962e5b6d6dSopenharmony_ci    era = cal->get(UCAL_ERA, status);
2972e5b6d6dSopenharmony_ci    year = cal->get(UCAL_YEAR, status);
2982e5b6d6dSopenharmony_ci    month = cal->get(UCAL_MONTH, status);
2992e5b6d6dSopenharmony_ci    dayOfMonth = cal->get(UCAL_DAY_OF_MONTH, status);
3002e5b6d6dSopenharmony_ci    dayOfWeek = cal->get(UCAL_DAY_OF_WEEK, status);
3012e5b6d6dSopenharmony_ci    millisInDay = cal->get(UCAL_MILLISECONDS_IN_DAY, status);
3022e5b6d6dSopenharmony_ci    time = cal->getTime(status);
3032e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
3042e5b6d6dSopenharmony_ci        errln("FAIL: Could not get calendar field values.");
3052e5b6d6dSopenharmony_ci    }
3062e5b6d6dSopenharmony_ci    offset = rbtz1->getOffset(era, year, month, dayOfMonth, dayOfWeek, millisInDay, status);
3072e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
3082e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(7 args) failed.");
3092e5b6d6dSopenharmony_ci    }
3102e5b6d6dSopenharmony_ci    if (offset != 0) {
3112e5b6d6dSopenharmony_ci        errln(UnicodeString("FAIL: Invalid time zone offset: ") + offset + " /expected: 0");
3122e5b6d6dSopenharmony_ci    }
3132e5b6d6dSopenharmony_ci    dst = rbtz1->inDaylightTime(time, status);
3142e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
3152e5b6d6dSopenharmony_ci        errln("FAIL: inDaylightTime failed.");
3162e5b6d6dSopenharmony_ci    }
3172e5b6d6dSopenharmony_ci    if (!dst) {
3182e5b6d6dSopenharmony_ci        errln("FAIL: Invalid daylight saving time");
3192e5b6d6dSopenharmony_ci    }
3202e5b6d6dSopenharmony_ci    rbtz1->getOffset(time, true, offset, dstSavings, status);
3212e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
3222e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(5 args) failed.");
3232e5b6d6dSopenharmony_ci    }
3242e5b6d6dSopenharmony_ci    if (offset != -3600000) {
3252e5b6d6dSopenharmony_ci        errln(UnicodeString("FAIL: Invalid time zone raw offset: ") + offset + " /expected: -3600000");
3262e5b6d6dSopenharmony_ci    }
3272e5b6d6dSopenharmony_ci    if (dstSavings != 3600000) {
3282e5b6d6dSopenharmony_ci        errln(UnicodeString("FAIL: Invalid DST amount: ") + dstSavings + " /expected: 3600000");
3292e5b6d6dSopenharmony_ci    }
3302e5b6d6dSopenharmony_ci
3312e5b6d6dSopenharmony_ci    // July 1, 2000, AD
3322e5b6d6dSopenharmony_ci    cal->set(UCAL_ERA, GregorianCalendar::AD);
3332e5b6d6dSopenharmony_ci    cal->set(2000, UCAL_JULY, 1);
3342e5b6d6dSopenharmony_ci
3352e5b6d6dSopenharmony_ci    era = cal->get(UCAL_ERA, status);
3362e5b6d6dSopenharmony_ci    year = cal->get(UCAL_YEAR, status);
3372e5b6d6dSopenharmony_ci    month = cal->get(UCAL_MONTH, status);
3382e5b6d6dSopenharmony_ci    dayOfMonth = cal->get(UCAL_DAY_OF_MONTH, status);
3392e5b6d6dSopenharmony_ci    dayOfWeek = cal->get(UCAL_DAY_OF_WEEK, status);
3402e5b6d6dSopenharmony_ci    millisInDay = cal->get(UCAL_MILLISECONDS_IN_DAY, status);
3412e5b6d6dSopenharmony_ci    time = cal->getTime(status);
3422e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
3432e5b6d6dSopenharmony_ci        errln("FAIL: Could not get calendar field values.");
3442e5b6d6dSopenharmony_ci    }
3452e5b6d6dSopenharmony_ci    offset = rbtz1->getOffset(era, year, month, dayOfMonth, dayOfWeek, millisInDay, status);
3462e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
3472e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(7 args) failed.");
3482e5b6d6dSopenharmony_ci    }
3492e5b6d6dSopenharmony_ci    if (offset != -3600000) {
3502e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: Invalid time zone offset: " + offset + " /expected: -3600000");
3512e5b6d6dSopenharmony_ci    }
3522e5b6d6dSopenharmony_ci    dst = rbtz1->inDaylightTime(time, status);
3532e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
3542e5b6d6dSopenharmony_ci        errln("FAIL: inDaylightTime failed.");
3552e5b6d6dSopenharmony_ci    }
3562e5b6d6dSopenharmony_ci    if (dst) {
3572e5b6d6dSopenharmony_ci        errln("FAIL: Invalid daylight saving time");
3582e5b6d6dSopenharmony_ci    }
3592e5b6d6dSopenharmony_ci    rbtz1->getOffset(time, true, offset, dstSavings, status);
3602e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
3612e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(5 args) failed.");
3622e5b6d6dSopenharmony_ci    }
3632e5b6d6dSopenharmony_ci    if (offset != -3600000) {
3642e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: Invalid time zone raw offset: " + offset + " /expected: -3600000");
3652e5b6d6dSopenharmony_ci    }
3662e5b6d6dSopenharmony_ci    if (dstSavings != 0) {
3672e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: Invalid DST amount: " + dstSavings + " /expected: 0");
3682e5b6d6dSopenharmony_ci    }
3692e5b6d6dSopenharmony_ci
3702e5b6d6dSopenharmony_ci    // getRawOffset
3712e5b6d6dSopenharmony_ci    offset = rbtz1->getRawOffset();
3722e5b6d6dSopenharmony_ci    if (offset != -1*HOUR) {
3732e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: Invalid time zone raw offset returned by getRawOffset: "
3742e5b6d6dSopenharmony_ci            + offset + " /expected: -3600000");
3752e5b6d6dSopenharmony_ci    }
3762e5b6d6dSopenharmony_ci
3772e5b6d6dSopenharmony_ci    // operator=/==/!=
3782e5b6d6dSopenharmony_ci    RuleBasedTimeZone rbtz0("RBTZ1", ir->clone());
3792e5b6d6dSopenharmony_ci    if (rbtz0 == *rbtz1 || !(rbtz0 != *rbtz1)) {
3802e5b6d6dSopenharmony_ci        errln("FAIL: RuleBasedTimeZone rbtz0 is not equal to rbtz1, but got wrong result");
3812e5b6d6dSopenharmony_ci    }
3822e5b6d6dSopenharmony_ci    rbtz0 = *rbtz1;
3832e5b6d6dSopenharmony_ci    if (rbtz0 != *rbtz1 || !(rbtz0 == *rbtz1)) {
3842e5b6d6dSopenharmony_ci        errln("FAIL: RuleBasedTimeZone rbtz0 is equal to rbtz1, but got wrong result");
3852e5b6d6dSopenharmony_ci    }
3862e5b6d6dSopenharmony_ci
3872e5b6d6dSopenharmony_ci    // setRawOffset
3882e5b6d6dSopenharmony_ci    const int32_t RAW = -10*HOUR;
3892e5b6d6dSopenharmony_ci    rbtz0.setRawOffset(RAW);
3902e5b6d6dSopenharmony_ci    if (rbtz0.getRawOffset() != RAW) {
3912e5b6d6dSopenharmony_ci        logln("setRawOffset is implemented in RuleBasedTimeZone");
3922e5b6d6dSopenharmony_ci    }
3932e5b6d6dSopenharmony_ci
3942e5b6d6dSopenharmony_ci    // useDaylightTime
3952e5b6d6dSopenharmony_ci    if (!rbtz1->useDaylightTime()) {
3962e5b6d6dSopenharmony_ci        errln("FAIL: useDaylightTime returned false");
3972e5b6d6dSopenharmony_ci    }
3982e5b6d6dSopenharmony_ci
3992e5b6d6dSopenharmony_ci    // Try to add 3rd final rule
4002e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_OCTOBER, 15, 1*HOUR, DateTimeRule::WALL_TIME);
4012e5b6d6dSopenharmony_ci    atzr = new AnnualTimeZoneRule("3RD_ATZ", -1*HOUR, 2*HOUR, dtr, STARTYEAR, AnnualTimeZoneRule::MAX_YEAR);
4022e5b6d6dSopenharmony_ci    rbtz1->addTransitionRule(atzr, status);
4032e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
4042e5b6d6dSopenharmony_ci        errln("FAIL: 3rd final rule must be rejected");
4052e5b6d6dSopenharmony_ci    }
4062e5b6d6dSopenharmony_ci
4072e5b6d6dSopenharmony_ci    // Try to add an initial rule
4082e5b6d6dSopenharmony_ci    InitialTimeZoneRule *ir1 = new InitialTimeZoneRule("Test Initial", 2*HOUR, 0);
4092e5b6d6dSopenharmony_ci    rbtz1->addTransitionRule(ir1, status);
4102e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
4112e5b6d6dSopenharmony_ci        errln("FAIL: InitialTimeZoneRule must be rejected");
4122e5b6d6dSopenharmony_ci    }
4132e5b6d6dSopenharmony_ci
4142e5b6d6dSopenharmony_ci    delete ir;
4152e5b6d6dSopenharmony_ci    delete rbtz1;
4162e5b6d6dSopenharmony_ci    delete rbtz2;
4172e5b6d6dSopenharmony_ci    delete rbtz3;
4182e5b6d6dSopenharmony_ci    delete rbtz1c;
4192e5b6d6dSopenharmony_ci    delete cal;
4202e5b6d6dSopenharmony_ci}
4212e5b6d6dSopenharmony_ci
4222e5b6d6dSopenharmony_ci/*
4232e5b6d6dSopenharmony_ci * Test equivalency between OlsonTimeZone and custom RBTZ representing the
4242e5b6d6dSopenharmony_ci * equivalent rules in a certain time range
4252e5b6d6dSopenharmony_ci */
4262e5b6d6dSopenharmony_civoid
4272e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestHistoricalRuleBasedTimeZone(void) {
4282e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
4292e5b6d6dSopenharmony_ci
4302e5b6d6dSopenharmony_ci    // Compare to America/New_York with equivalent RBTZ
4312e5b6d6dSopenharmony_ci    BasicTimeZone *ny = (BasicTimeZone*)TimeZone::createTimeZone("America/New_York");
4322e5b6d6dSopenharmony_ci
4332e5b6d6dSopenharmony_ci    //RBTZ
4342e5b6d6dSopenharmony_ci    InitialTimeZoneRule *ir = new InitialTimeZoneRule("EST", -5*HOUR, 0);
4352e5b6d6dSopenharmony_ci    RuleBasedTimeZone *rbtz = new RuleBasedTimeZone("EST5EDT", ir);
4362e5b6d6dSopenharmony_ci
4372e5b6d6dSopenharmony_ci    DateTimeRule *dtr;
4382e5b6d6dSopenharmony_ci    AnnualTimeZoneRule *tzr;
4392e5b6d6dSopenharmony_ci
4402e5b6d6dSopenharmony_ci    // Standard time
4412e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_OCTOBER, -1, UCAL_SUNDAY,
4422e5b6d6dSopenharmony_ci        2*HOUR, DateTimeRule::WALL_TIME); // Last Sunday in October, at 2AM wall time
4432e5b6d6dSopenharmony_ci    tzr = new AnnualTimeZoneRule("EST", -5*HOUR /*rawOffset*/, 0 /*dstSavings*/, dtr, 1967, 2006);
4442e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(tzr, status);
4452e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
4462e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 1.");
4472e5b6d6dSopenharmony_ci    }
4482e5b6d6dSopenharmony_ci
4492e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_NOVEMBER, 1, UCAL_SUNDAY,
4502e5b6d6dSopenharmony_ci        true, 2*HOUR, DateTimeRule::WALL_TIME); // SUN>=1 in November, at 2AM wall time
4512e5b6d6dSopenharmony_ci    tzr = new AnnualTimeZoneRule("EST", -5*HOUR, 0, dtr, 2007, AnnualTimeZoneRule::MAX_YEAR);
4522e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(tzr, status);
4532e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
4542e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 2.");
4552e5b6d6dSopenharmony_ci    }
4562e5b6d6dSopenharmony_ci
4572e5b6d6dSopenharmony_ci    // Daylight saving time
4582e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_APRIL, -1, UCAL_SUNDAY,
4592e5b6d6dSopenharmony_ci        2*HOUR, DateTimeRule::WALL_TIME); // Last Sunday in April, at 2AM wall time
4602e5b6d6dSopenharmony_ci    tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1967, 1973);
4612e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(tzr, status);
4622e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
4632e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 3.");
4642e5b6d6dSopenharmony_ci    }
4652e5b6d6dSopenharmony_ci
4662e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_JANUARY, 6,
4672e5b6d6dSopenharmony_ci        2*HOUR, DateTimeRule::WALL_TIME); // January 6, at 2AM wall time
4682e5b6d6dSopenharmony_ci    tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1974, 1974);
4692e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(tzr, status);
4702e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
4712e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 4.");
4722e5b6d6dSopenharmony_ci    }
4732e5b6d6dSopenharmony_ci
4742e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_FEBRUARY, 23,
4752e5b6d6dSopenharmony_ci        2*HOUR, DateTimeRule::WALL_TIME); // February 23, at 2AM wall time
4762e5b6d6dSopenharmony_ci    tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1975, 1975);
4772e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(tzr, status);
4782e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
4792e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 5.");
4802e5b6d6dSopenharmony_ci    }
4812e5b6d6dSopenharmony_ci
4822e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_APRIL, -1, UCAL_SUNDAY,
4832e5b6d6dSopenharmony_ci        2*HOUR, DateTimeRule::WALL_TIME); // Last Sunday in April, at 2AM wall time
4842e5b6d6dSopenharmony_ci    tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1976, 1986);
4852e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(tzr, status);
4862e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
4872e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 6.");
4882e5b6d6dSopenharmony_ci    }
4892e5b6d6dSopenharmony_ci
4902e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_APRIL, 1, UCAL_SUNDAY,
4912e5b6d6dSopenharmony_ci        true, 2*HOUR, DateTimeRule::WALL_TIME); // SUN>=1 in April, at 2AM wall time
4922e5b6d6dSopenharmony_ci    tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 1987, 2006);
4932e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(tzr, status);
4942e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
4952e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 7.");
4962e5b6d6dSopenharmony_ci    }
4972e5b6d6dSopenharmony_ci
4982e5b6d6dSopenharmony_ci    dtr = new DateTimeRule(UCAL_MARCH, 8, UCAL_SUNDAY,
4992e5b6d6dSopenharmony_ci        true, 2*HOUR, DateTimeRule::WALL_TIME); // SUN>=8 in March, at 2AM wall time
5002e5b6d6dSopenharmony_ci    tzr = new AnnualTimeZoneRule("EDT", -5*HOUR, 1*HOUR, dtr, 2007, AnnualTimeZoneRule::MAX_YEAR);
5012e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(tzr, status);
5022e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
5032e5b6d6dSopenharmony_ci        errln("FAIL: couldn't add AnnualTimeZoneRule 7.");
5042e5b6d6dSopenharmony_ci    }
5052e5b6d6dSopenharmony_ci
5062e5b6d6dSopenharmony_ci    rbtz->complete(status);
5072e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
5082e5b6d6dSopenharmony_ci        errln("FAIL: couldn't complete RBTZ.");
5092e5b6d6dSopenharmony_ci    }
5102e5b6d6dSopenharmony_ci
5112e5b6d6dSopenharmony_ci    // hasEquivalentTransitions
5122e5b6d6dSopenharmony_ci    UDate jan1_1950 = getUTCMillis(1950, UCAL_JANUARY, 1);
5132e5b6d6dSopenharmony_ci    UDate jan1_1967 = getUTCMillis(1971, UCAL_JANUARY, 1);
5142e5b6d6dSopenharmony_ci    UDate jan1_2010 = getUTCMillis(2010, UCAL_JANUARY, 1);
5152e5b6d6dSopenharmony_ci
5162e5b6d6dSopenharmony_ci    if (!ny->hasEquivalentTransitions(*rbtz, jan1_1967, jan1_2010, true, status)) {
5172e5b6d6dSopenharmony_ci        dataerrln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010");
5182e5b6d6dSopenharmony_ci    }
5192e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
5202e5b6d6dSopenharmony_ci        errln("FAIL: error returned from hasEquivalentTransitions for ny/rbtz 1967-2010");
5212e5b6d6dSopenharmony_ci    }
5222e5b6d6dSopenharmony_ci    if (ny->hasEquivalentTransitions(*rbtz, jan1_1950, jan1_2010, true, status)) {
5232e5b6d6dSopenharmony_ci        errln("FAIL: The RBTZ must not be equivalent to America/New_York between 1950 and 2010");
5242e5b6d6dSopenharmony_ci    }
5252e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
5262e5b6d6dSopenharmony_ci        errln("FAIL: error returned from hasEquivalentTransitions for ny/rbtz 1950-2010");
5272e5b6d6dSopenharmony_ci    }
5282e5b6d6dSopenharmony_ci
5292e5b6d6dSopenharmony_ci    // Same with above, but calling RBTZ#hasEquivalentTransitions against OlsonTimeZone
5302e5b6d6dSopenharmony_ci    if (!rbtz->hasEquivalentTransitions(*ny, jan1_1967, jan1_2010, true, status)) {
5312e5b6d6dSopenharmony_ci        dataerrln("FAIL: The RBTZ must be equivalent to America/New_York between 1967 and 2010 ");
5322e5b6d6dSopenharmony_ci    }
5332e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
5342e5b6d6dSopenharmony_ci        errln("FAIL: error returned from hasEquivalentTransitions for rbtz/ny 1967-2010");
5352e5b6d6dSopenharmony_ci    }
5362e5b6d6dSopenharmony_ci    if (rbtz->hasEquivalentTransitions(*ny, jan1_1950, jan1_2010, true, status)) {
5372e5b6d6dSopenharmony_ci        errln("FAIL: The RBTZ must not be equivalent to America/New_York between 1950 and 2010");
5382e5b6d6dSopenharmony_ci    }
5392e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
5402e5b6d6dSopenharmony_ci        errln("FAIL: error returned from hasEquivalentTransitions for rbtz/ny 1950-2010");
5412e5b6d6dSopenharmony_ci    }
5422e5b6d6dSopenharmony_ci
5432e5b6d6dSopenharmony_ci    // TimeZone APIs
5442e5b6d6dSopenharmony_ci    if (ny->hasSameRules(*rbtz) || rbtz->hasSameRules(*ny)) {
5452e5b6d6dSopenharmony_ci        errln("FAIL: hasSameRules must return false");
5462e5b6d6dSopenharmony_ci    }
5472e5b6d6dSopenharmony_ci    RuleBasedTimeZone *rbtzc = rbtz->clone();
5482e5b6d6dSopenharmony_ci    if (!rbtz->hasSameRules(*rbtzc) || !rbtz->hasEquivalentTransitions(*rbtzc, jan1_1950, jan1_2010, true, status)) {
5492e5b6d6dSopenharmony_ci        errln("FAIL: hasSameRules/hasEquivalentTransitions must return true for cloned RBTZs");
5502e5b6d6dSopenharmony_ci    }
5512e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
5522e5b6d6dSopenharmony_ci        errln("FAIL: error returned from hasEquivalentTransitions for rbtz/rbtzc 1950-2010");
5532e5b6d6dSopenharmony_ci    }
5542e5b6d6dSopenharmony_ci
5552e5b6d6dSopenharmony_ci    UDate times[] = {
5562e5b6d6dSopenharmony_ci        getUTCMillis(2006, UCAL_MARCH, 15),
5572e5b6d6dSopenharmony_ci        getUTCMillis(2006, UCAL_NOVEMBER, 1),
5582e5b6d6dSopenharmony_ci        getUTCMillis(2007, UCAL_MARCH, 15),
5592e5b6d6dSopenharmony_ci        getUTCMillis(2007, UCAL_NOVEMBER, 1),
5602e5b6d6dSopenharmony_ci        getUTCMillis(2008, UCAL_MARCH, 15),
5612e5b6d6dSopenharmony_ci        getUTCMillis(2008, UCAL_NOVEMBER, 1),
5622e5b6d6dSopenharmony_ci        0
5632e5b6d6dSopenharmony_ci    };
5642e5b6d6dSopenharmony_ci    int32_t offset1, dst1;
5652e5b6d6dSopenharmony_ci    int32_t offset2, dst2;
5662e5b6d6dSopenharmony_ci
5672e5b6d6dSopenharmony_ci    for (int i = 0; times[i] != 0; i++) {
5682e5b6d6dSopenharmony_ci        // Check getOffset - must return the same results for these time data
5692e5b6d6dSopenharmony_ci        rbtz->getOffset(times[i], false, offset1, dst1, status);
5702e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
5712e5b6d6dSopenharmony_ci            errln("FAIL: rbtz->getOffset failed");
5722e5b6d6dSopenharmony_ci        }
5732e5b6d6dSopenharmony_ci        ny->getOffset(times[i], false, offset2, dst2, status);
5742e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
5752e5b6d6dSopenharmony_ci            errln("FAIL: ny->getOffset failed");
5762e5b6d6dSopenharmony_ci        }
5772e5b6d6dSopenharmony_ci        if (offset1 != offset2 || dst1 != dst2) {
5782e5b6d6dSopenharmony_ci            dataerrln("FAIL: Incompatible time zone offset/dstSavings for ny and rbtz");
5792e5b6d6dSopenharmony_ci        }
5802e5b6d6dSopenharmony_ci
5812e5b6d6dSopenharmony_ci        // Check inDaylightTime
5822e5b6d6dSopenharmony_ci        if (rbtz->inDaylightTime(times[i], status) != ny->inDaylightTime(times[i], status)) {
5832e5b6d6dSopenharmony_ci            dataerrln("FAIL: Incompatible daylight saving time for ny and rbtz");
5842e5b6d6dSopenharmony_ci        }
5852e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
5862e5b6d6dSopenharmony_ci            errln("FAIL: inDaylightTime failed");
5872e5b6d6dSopenharmony_ci        }
5882e5b6d6dSopenharmony_ci    }
5892e5b6d6dSopenharmony_ci
5902e5b6d6dSopenharmony_ci    delete ny;
5912e5b6d6dSopenharmony_ci    delete rbtz;
5922e5b6d6dSopenharmony_ci    delete rbtzc;
5932e5b6d6dSopenharmony_ci}
5942e5b6d6dSopenharmony_ci
5952e5b6d6dSopenharmony_ci/*
5962e5b6d6dSopenharmony_ci * Check if transitions returned by getNextTransition/getPreviousTransition
5972e5b6d6dSopenharmony_ci * are actual time transitions.
5982e5b6d6dSopenharmony_ci */
5992e5b6d6dSopenharmony_civoid
6002e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestOlsonTransition(void) {
6012e5b6d6dSopenharmony_ci
6022e5b6d6dSopenharmony_ci    const int32_t TESTYEARS[][2] = {
6032e5b6d6dSopenharmony_ci        {1895, 1905}, // including int32 minimum second
6042e5b6d6dSopenharmony_ci        {1965, 1975}, // including the epoch
6052e5b6d6dSopenharmony_ci        {1995, 2015}, // practical year range
6062e5b6d6dSopenharmony_ci        {0,0}
6072e5b6d6dSopenharmony_ci    };
6082e5b6d6dSopenharmony_ci
6092e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
6102e5b6d6dSopenharmony_ci    TestZIDEnumeration tzenum(!quick);
6112e5b6d6dSopenharmony_ci    while (true) {
6122e5b6d6dSopenharmony_ci        const UnicodeString *tzid = tzenum.snext(status);
6132e5b6d6dSopenharmony_ci        if (tzid == NULL) {
6142e5b6d6dSopenharmony_ci            break;
6152e5b6d6dSopenharmony_ci        }
6162e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
6172e5b6d6dSopenharmony_ci            errln("FAIL: error returned while enumerating timezone IDs.");
6182e5b6d6dSopenharmony_ci            break;
6192e5b6d6dSopenharmony_ci        }
6202e5b6d6dSopenharmony_ci        BasicTimeZone *tz = (BasicTimeZone*)TimeZone::createTimeZone(*tzid);
6212e5b6d6dSopenharmony_ci        for (int32_t i = 0; TESTYEARS[i][0] != 0 || TESTYEARS[i][1] != 0; i++) {
6222e5b6d6dSopenharmony_ci            UDate lo = getUTCMillis(TESTYEARS[i][0], UCAL_JANUARY, 1);
6232e5b6d6dSopenharmony_ci            UDate hi = getUTCMillis(TESTYEARS[i][1], UCAL_JANUARY, 1);
6242e5b6d6dSopenharmony_ci            verifyTransitions(*tz, lo, hi);
6252e5b6d6dSopenharmony_ci        }
6262e5b6d6dSopenharmony_ci        delete tz;
6272e5b6d6dSopenharmony_ci    }
6282e5b6d6dSopenharmony_ci}
6292e5b6d6dSopenharmony_ci
6302e5b6d6dSopenharmony_ci/*
6312e5b6d6dSopenharmony_ci * Check if an OlsonTimeZone and its equivalent RBTZ have the exact same
6322e5b6d6dSopenharmony_ci * transitions.
6332e5b6d6dSopenharmony_ci */
6342e5b6d6dSopenharmony_civoid
6352e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestRBTZTransition(void) {
6362e5b6d6dSopenharmony_ci    const int32_t STARTYEARS[] = {
6372e5b6d6dSopenharmony_ci        1900,
6382e5b6d6dSopenharmony_ci        1960,
6392e5b6d6dSopenharmony_ci        1990,
6402e5b6d6dSopenharmony_ci        2010,
6412e5b6d6dSopenharmony_ci        0
6422e5b6d6dSopenharmony_ci    };
6432e5b6d6dSopenharmony_ci
6442e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
6452e5b6d6dSopenharmony_ci    TestZIDEnumeration tzenum(!quick);
6462e5b6d6dSopenharmony_ci    while (true) {
6472e5b6d6dSopenharmony_ci        const UnicodeString *tzid = tzenum.snext(status);
6482e5b6d6dSopenharmony_ci        if (tzid == NULL) {
6492e5b6d6dSopenharmony_ci            break;
6502e5b6d6dSopenharmony_ci        }
6512e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
6522e5b6d6dSopenharmony_ci            errln("FAIL: error returned while enumerating timezone IDs.");
6532e5b6d6dSopenharmony_ci            break;
6542e5b6d6dSopenharmony_ci        }
6552e5b6d6dSopenharmony_ci        BasicTimeZone *tz = (BasicTimeZone*)TimeZone::createTimeZone(*tzid);
6562e5b6d6dSopenharmony_ci        int32_t ruleCount = tz->countTransitionRules(status);
6572e5b6d6dSopenharmony_ci
6582e5b6d6dSopenharmony_ci        const InitialTimeZoneRule *initial;
6592e5b6d6dSopenharmony_ci        const TimeZoneRule **trsrules = new const TimeZoneRule*[ruleCount];
6602e5b6d6dSopenharmony_ci        tz->getTimeZoneRules(initial, trsrules, ruleCount, status);
6612e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
6622e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: failed to get the TimeZoneRules from time zone " + *tzid);
6632e5b6d6dSopenharmony_ci        }
6642e5b6d6dSopenharmony_ci        RuleBasedTimeZone *rbtz = new RuleBasedTimeZone(*tzid, initial->clone());
6652e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
6662e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: failed to get the transition rule count from time zone " + *tzid);
6672e5b6d6dSopenharmony_ci        }
6682e5b6d6dSopenharmony_ci        for (int32_t i = 0; i < ruleCount; i++) {
6692e5b6d6dSopenharmony_ci            rbtz->addTransitionRule(trsrules[i]->clone(), status);
6702e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
6712e5b6d6dSopenharmony_ci                errln((UnicodeString)"FAIL: failed to add a transition rule at index " + i + " to the RBTZ for " + *tzid);
6722e5b6d6dSopenharmony_ci            }
6732e5b6d6dSopenharmony_ci        }
6742e5b6d6dSopenharmony_ci        rbtz->complete(status);
6752e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
6762e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: complete() failed for the RBTZ for " + *tzid);
6772e5b6d6dSopenharmony_ci        }
6782e5b6d6dSopenharmony_ci
6792e5b6d6dSopenharmony_ci        for (int32_t idx = 0; STARTYEARS[idx] != 0; idx++) {
6802e5b6d6dSopenharmony_ci            UDate start = getUTCMillis(STARTYEARS[idx], UCAL_JANUARY, 1);
6812e5b6d6dSopenharmony_ci            UDate until = getUTCMillis(STARTYEARS[idx] + 20, UCAL_JANUARY, 1);
6822e5b6d6dSopenharmony_ci            // Compare the original OlsonTimeZone with the RBTZ starting the startTime for 20 years
6832e5b6d6dSopenharmony_ci
6842e5b6d6dSopenharmony_ci            // Ascending
6852e5b6d6dSopenharmony_ci            compareTransitionsAscending(*tz, *rbtz, start, until, false);
6862e5b6d6dSopenharmony_ci            // Ascending/inclusive
6872e5b6d6dSopenharmony_ci            compareTransitionsAscending(*tz, *rbtz, start + 1, until, true);
6882e5b6d6dSopenharmony_ci            // Descending
6892e5b6d6dSopenharmony_ci            compareTransitionsDescending(*tz, *rbtz, start, until, false);
6902e5b6d6dSopenharmony_ci            // Descending/inclusive
6912e5b6d6dSopenharmony_ci            compareTransitionsDescending(*tz, *rbtz, start + 1, until, true);
6922e5b6d6dSopenharmony_ci        }
6932e5b6d6dSopenharmony_ci        delete [] trsrules;
6942e5b6d6dSopenharmony_ci        delete rbtz;
6952e5b6d6dSopenharmony_ci        delete tz;
6962e5b6d6dSopenharmony_ci    }
6972e5b6d6dSopenharmony_ci}
6982e5b6d6dSopenharmony_ci
6992e5b6d6dSopenharmony_civoid
7002e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestHasEquivalentTransitions(void) {
7012e5b6d6dSopenharmony_ci    // America/New_York and America/Indiana/Indianapolis are equivalent
7022e5b6d6dSopenharmony_ci    // since 2006
7032e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
7042e5b6d6dSopenharmony_ci    BasicTimeZone *newyork = (BasicTimeZone*)TimeZone::createTimeZone("America/New_York");
7052e5b6d6dSopenharmony_ci    BasicTimeZone *indianapolis = (BasicTimeZone*)TimeZone::createTimeZone("America/Indiana/Indianapolis");
7062e5b6d6dSopenharmony_ci    BasicTimeZone *gmt_5 = (BasicTimeZone*)TimeZone::createTimeZone("Etc/GMT+5");
7072e5b6d6dSopenharmony_ci
7082e5b6d6dSopenharmony_ci    UDate jan1_1971 = getUTCMillis(1971, UCAL_JANUARY, 1);
7092e5b6d6dSopenharmony_ci    UDate jan1_2005 = getUTCMillis(2005, UCAL_JANUARY, 1);
7102e5b6d6dSopenharmony_ci    UDate jan1_2006 = getUTCMillis(2006, UCAL_JANUARY, 1);
7112e5b6d6dSopenharmony_ci    UDate jan1_2007 = getUTCMillis(2007, UCAL_JANUARY, 1);
7122e5b6d6dSopenharmony_ci    UDate jan1_2011 = getUTCMillis(2010, UCAL_JANUARY, 1);
7132e5b6d6dSopenharmony_ci
7142e5b6d6dSopenharmony_ci    if (newyork->hasEquivalentTransitions(*indianapolis, jan1_2005, jan1_2011, true, status)) {
7152e5b6d6dSopenharmony_ci        dataerrln("FAIL: New_York is not equivalent to Indianapolis between 2005 and 2010");
7162e5b6d6dSopenharmony_ci    }
7172e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
7182e5b6d6dSopenharmony_ci        errln("FAIL: error status is returned from hasEquivalentTransition");
7192e5b6d6dSopenharmony_ci    }
7202e5b6d6dSopenharmony_ci    if (!newyork->hasEquivalentTransitions(*indianapolis, jan1_2006, jan1_2011, true, status)) {
7212e5b6d6dSopenharmony_ci        errln("FAIL: New_York is equivalent to Indianapolis between 2006 and 2010");
7222e5b6d6dSopenharmony_ci    }
7232e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
7242e5b6d6dSopenharmony_ci        errln("FAIL: error status is returned from hasEquivalentTransition");
7252e5b6d6dSopenharmony_ci    }
7262e5b6d6dSopenharmony_ci
7272e5b6d6dSopenharmony_ci    if (!indianapolis->hasEquivalentTransitions(*gmt_5, jan1_1971, jan1_2006, true, status)) {
7282e5b6d6dSopenharmony_ci        errln("FAIL: Indianapolis is equivalent to GMT+5 between 1971 and 2005");
7292e5b6d6dSopenharmony_ci    }
7302e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
7312e5b6d6dSopenharmony_ci        errln("FAIL: error status is returned from hasEquivalentTransition");
7322e5b6d6dSopenharmony_ci    }
7332e5b6d6dSopenharmony_ci    if (indianapolis->hasEquivalentTransitions(*gmt_5, jan1_1971, jan1_2007, true, status)) {
7342e5b6d6dSopenharmony_ci        dataerrln("FAIL: Indianapolis is not equivalent to GMT+5 between 1971 and 2006");
7352e5b6d6dSopenharmony_ci    }
7362e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
7372e5b6d6dSopenharmony_ci        errln("FAIL: error status is returned from hasEquivalentTransition");
7382e5b6d6dSopenharmony_ci    }
7392e5b6d6dSopenharmony_ci
7402e5b6d6dSopenharmony_ci    // Cloned TimeZone
7412e5b6d6dSopenharmony_ci    BasicTimeZone *newyork2 = newyork->clone();
7422e5b6d6dSopenharmony_ci    if (!newyork->hasEquivalentTransitions(*newyork2, jan1_1971, jan1_2011, false, status)) {
7432e5b6d6dSopenharmony_ci        errln("FAIL: Cloned TimeZone must have the same transitions");
7442e5b6d6dSopenharmony_ci    }
7452e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
7462e5b6d6dSopenharmony_ci        errln("FAIL: error status is returned from hasEquivalentTransition for newyork/newyork2");
7472e5b6d6dSopenharmony_ci    }
7482e5b6d6dSopenharmony_ci    if (!newyork->hasEquivalentTransitions(*newyork2, jan1_1971, jan1_2011, true, status)) {
7492e5b6d6dSopenharmony_ci        errln("FAIL: Cloned TimeZone must have the same transitions");
7502e5b6d6dSopenharmony_ci    }
7512e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
7522e5b6d6dSopenharmony_ci        errln("FAIL: error status is returned from hasEquivalentTransition for newyork/newyork2");
7532e5b6d6dSopenharmony_ci    }
7542e5b6d6dSopenharmony_ci
7552e5b6d6dSopenharmony_ci    // America/New_York and America/Los_Angeles has same DST start rules, but
7562e5b6d6dSopenharmony_ci    // raw offsets are different
7572e5b6d6dSopenharmony_ci    BasicTimeZone *losangeles = (BasicTimeZone*)TimeZone::createTimeZone("America/Los_Angeles");
7582e5b6d6dSopenharmony_ci    if (newyork->hasEquivalentTransitions(*losangeles, jan1_2006, jan1_2011, true, status)) {
7592e5b6d6dSopenharmony_ci        dataerrln("FAIL: New_York is not equivalent to Los Angeles, but returned true");
7602e5b6d6dSopenharmony_ci    }
7612e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
7622e5b6d6dSopenharmony_ci        errln("FAIL: error status is returned from hasEquivalentTransition for newyork/losangeles");
7632e5b6d6dSopenharmony_ci    }
7642e5b6d6dSopenharmony_ci
7652e5b6d6dSopenharmony_ci    delete newyork;
7662e5b6d6dSopenharmony_ci    delete newyork2;
7672e5b6d6dSopenharmony_ci    delete indianapolis;
7682e5b6d6dSopenharmony_ci    delete gmt_5;
7692e5b6d6dSopenharmony_ci    delete losangeles;
7702e5b6d6dSopenharmony_ci}
7712e5b6d6dSopenharmony_ci
7722e5b6d6dSopenharmony_ci/*
7732e5b6d6dSopenharmony_ci * Write out time zone rules of OlsonTimeZone into VTIMEZONE format, create a new
7742e5b6d6dSopenharmony_ci * VTimeZone from the VTIMEZONE data, then compare transitions
7752e5b6d6dSopenharmony_ci */
7762e5b6d6dSopenharmony_civoid
7772e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestVTimeZoneRoundTrip(void) {
7782e5b6d6dSopenharmony_ci    UDate startTime = getUTCMillis(1850, UCAL_JANUARY, 1);
7792e5b6d6dSopenharmony_ci    UDate endTime = getUTCMillis(2050, UCAL_JANUARY, 1);
7802e5b6d6dSopenharmony_ci
7812e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
7822e5b6d6dSopenharmony_ci    TestZIDEnumeration tzenum(!quick);
7832e5b6d6dSopenharmony_ci    while (true) {
7842e5b6d6dSopenharmony_ci        const UnicodeString *tzid = tzenum.snext(status);
7852e5b6d6dSopenharmony_ci        if (tzid == NULL) {
7862e5b6d6dSopenharmony_ci            break;
7872e5b6d6dSopenharmony_ci        }
7882e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
7892e5b6d6dSopenharmony_ci            errln("FAIL: error returned while enumerating timezone IDs.");
7902e5b6d6dSopenharmony_ci            break;
7912e5b6d6dSopenharmony_ci        }
7922e5b6d6dSopenharmony_ci        BasicTimeZone *tz = (BasicTimeZone*)TimeZone::createTimeZone(*tzid);
7932e5b6d6dSopenharmony_ci        VTimeZone *vtz_org = VTimeZone::createVTimeZoneByID(*tzid);
7942e5b6d6dSopenharmony_ci        vtz_org->setTZURL("http://source.icu-project.org/timezone");
7952e5b6d6dSopenharmony_ci        vtz_org->setLastModified(Calendar::getNow());
7962e5b6d6dSopenharmony_ci        VTimeZone *vtz_new = NULL;
7972e5b6d6dSopenharmony_ci        UnicodeString vtzdata;
7982e5b6d6dSopenharmony_ci        // Write out VTIMEZONE data
7992e5b6d6dSopenharmony_ci        vtz_org->write(vtzdata, status);
8002e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
8012e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: error returned while writing time zone rules for " +
8022e5b6d6dSopenharmony_ci                *tzid + " into VTIMEZONE format.");
8032e5b6d6dSopenharmony_ci        } else {
8042e5b6d6dSopenharmony_ci            // Read VTIMEZONE data
8052e5b6d6dSopenharmony_ci            vtz_new = VTimeZone::createVTimeZone(vtzdata, status);
8062e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
8072e5b6d6dSopenharmony_ci                errln((UnicodeString)"FAIL: error returned while reading VTIMEZONE data for " + *tzid);
8082e5b6d6dSopenharmony_ci            } else {
8092e5b6d6dSopenharmony_ci                // Write out VTIMEZONE one more time
8102e5b6d6dSopenharmony_ci                UnicodeString vtzdata1;
8112e5b6d6dSopenharmony_ci                vtz_new->write(vtzdata1, status);
8122e5b6d6dSopenharmony_ci                if (U_FAILURE(status)) {
8132e5b6d6dSopenharmony_ci                    errln((UnicodeString)"FAIL: error returned while writing time zone rules for " +
8142e5b6d6dSopenharmony_ci                        *tzid + "(vtz_new) into VTIMEZONE format.");
8152e5b6d6dSopenharmony_ci                } else {
8162e5b6d6dSopenharmony_ci                    // Make sure VTIMEZONE data is exactly same with the first one
8172e5b6d6dSopenharmony_ci                    if (vtzdata != vtzdata1) {
8182e5b6d6dSopenharmony_ci                        errln((UnicodeString)"FAIL: different VTIMEZONE data after round trip for " + *tzid);
8192e5b6d6dSopenharmony_ci                    }
8202e5b6d6dSopenharmony_ci                }
8212e5b6d6dSopenharmony_ci                // Check equivalency after the first transition.
8222e5b6d6dSopenharmony_ci                // The DST information before the first transition might be lost
8232e5b6d6dSopenharmony_ci                // because there is no good way to represent the initial time with
8242e5b6d6dSopenharmony_ci                // VTIMEZONE.
8252e5b6d6dSopenharmony_ci                int32_t raw1, raw2, dst1, dst2;
8262e5b6d6dSopenharmony_ci                tz->getOffset(startTime, false, raw1, dst1, status);
8272e5b6d6dSopenharmony_ci                vtz_new->getOffset(startTime, false, raw2, dst2, status);
8282e5b6d6dSopenharmony_ci                if (U_FAILURE(status)) {
8292e5b6d6dSopenharmony_ci                    errln("FAIL: error status is returned from getOffset");
8302e5b6d6dSopenharmony_ci                } else {
8312e5b6d6dSopenharmony_ci                    if (raw1 + dst1 != raw2 + dst2) {
8322e5b6d6dSopenharmony_ci                        errln("FAIL: VTimeZone for " + *tzid +
8332e5b6d6dSopenharmony_ci                            " is not equivalent to its OlsonTimeZone corresponding at "
8342e5b6d6dSopenharmony_ci                            + dateToString(startTime));
8352e5b6d6dSopenharmony_ci                    }
8362e5b6d6dSopenharmony_ci                    TimeZoneTransition trans;
8372e5b6d6dSopenharmony_ci                    UBool avail = tz->getNextTransition(startTime, false, trans);
8382e5b6d6dSopenharmony_ci                    if (avail) {
8392e5b6d6dSopenharmony_ci                        if (!vtz_new->hasEquivalentTransitions(*tz, trans.getTime(),
8402e5b6d6dSopenharmony_ci                                endTime, true, status)) {
8412e5b6d6dSopenharmony_ci                            int32_t maxDelta = 1000;
8422e5b6d6dSopenharmony_ci                            if (!hasEquivalentTransitions(*vtz_new, *tz, trans.getTime() + maxDelta,
8432e5b6d6dSopenharmony_ci                                endTime, true, maxDelta, status)) {
8442e5b6d6dSopenharmony_ci                                errln("FAIL: VTimeZone for " + *tzid +
8452e5b6d6dSopenharmony_ci                                    " is not equivalent to its OlsonTimeZone corresponding.");
8462e5b6d6dSopenharmony_ci                            } else {
8472e5b6d6dSopenharmony_ci                                logln("VTimeZone for " + *tzid +
8482e5b6d6dSopenharmony_ci                                    "  differs from its OlsonTimeZone corresponding with maximum transition time delta - " + maxDelta);
8492e5b6d6dSopenharmony_ci                            }
8502e5b6d6dSopenharmony_ci                        }
8512e5b6d6dSopenharmony_ci                        if (U_FAILURE(status)) {
8522e5b6d6dSopenharmony_ci                            errln("FAIL: error status is returned from hasEquivalentTransition");
8532e5b6d6dSopenharmony_ci                        }
8542e5b6d6dSopenharmony_ci                    }
8552e5b6d6dSopenharmony_ci                }
8562e5b6d6dSopenharmony_ci            }
8572e5b6d6dSopenharmony_ci            if (vtz_new != NULL) {
8582e5b6d6dSopenharmony_ci                delete vtz_new;
8592e5b6d6dSopenharmony_ci                vtz_new = NULL;
8602e5b6d6dSopenharmony_ci            }
8612e5b6d6dSopenharmony_ci        }
8622e5b6d6dSopenharmony_ci        delete tz;
8632e5b6d6dSopenharmony_ci        delete vtz_org;
8642e5b6d6dSopenharmony_ci    }
8652e5b6d6dSopenharmony_ci}
8662e5b6d6dSopenharmony_ci
8672e5b6d6dSopenharmony_ci/*
8682e5b6d6dSopenharmony_ci * Write out time zone rules of OlsonTimeZone after a cutover date into VTIMEZONE format,
8692e5b6d6dSopenharmony_ci * create a new VTimeZone from the VTIMEZONE data, then compare transitions
8702e5b6d6dSopenharmony_ci */
8712e5b6d6dSopenharmony_civoid
8722e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestVTimeZoneRoundTripPartial(void) {
8732e5b6d6dSopenharmony_ci    const int32_t STARTYEARS[] = {
8742e5b6d6dSopenharmony_ci        1900,
8752e5b6d6dSopenharmony_ci        1950,
8762e5b6d6dSopenharmony_ci        2020,
8772e5b6d6dSopenharmony_ci        0
8782e5b6d6dSopenharmony_ci    };
8792e5b6d6dSopenharmony_ci    UDate endTime = getUTCMillis(2050, UCAL_JANUARY, 1);
8802e5b6d6dSopenharmony_ci
8812e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
8822e5b6d6dSopenharmony_ci    TestZIDEnumeration tzenum(!quick);
8832e5b6d6dSopenharmony_ci    while (true) {
8842e5b6d6dSopenharmony_ci        const UnicodeString *tzid = tzenum.snext(status);
8852e5b6d6dSopenharmony_ci        if (tzid == NULL) {
8862e5b6d6dSopenharmony_ci            break;
8872e5b6d6dSopenharmony_ci        }
8882e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
8892e5b6d6dSopenharmony_ci            errln("FAIL: error returned while enumerating timezone IDs.");
8902e5b6d6dSopenharmony_ci            break;
8912e5b6d6dSopenharmony_ci        }
8922e5b6d6dSopenharmony_ci        BasicTimeZone *tz = (BasicTimeZone*)TimeZone::createTimeZone(*tzid);
8932e5b6d6dSopenharmony_ci        VTimeZone *vtz_org = VTimeZone::createVTimeZoneByID(*tzid);
8942e5b6d6dSopenharmony_ci        VTimeZone *vtz_new = NULL;
8952e5b6d6dSopenharmony_ci        UnicodeString vtzdata;
8962e5b6d6dSopenharmony_ci
8972e5b6d6dSopenharmony_ci        for (int32_t i = 0; STARTYEARS[i] != 0; i++) {
8982e5b6d6dSopenharmony_ci            // Write out VTIMEZONE
8992e5b6d6dSopenharmony_ci            UDate startTime = getUTCMillis(STARTYEARS[i], UCAL_JANUARY, 1);
9002e5b6d6dSopenharmony_ci            vtz_org->write(startTime, vtzdata, status);
9012e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
9022e5b6d6dSopenharmony_ci                errln((UnicodeString)"FAIL: error returned while writing time zone rules for " +
9032e5b6d6dSopenharmony_ci                    *tzid + " into VTIMEZONE format since " + dateToString(startTime));
9042e5b6d6dSopenharmony_ci            } else {
9052e5b6d6dSopenharmony_ci                // Read VTIMEZONE data
9062e5b6d6dSopenharmony_ci                vtz_new = VTimeZone::createVTimeZone(vtzdata, status);
9072e5b6d6dSopenharmony_ci                if (U_FAILURE(status)) {
9082e5b6d6dSopenharmony_ci                    errln((UnicodeString)"FAIL: error returned while reading VTIMEZONE data for " + *tzid
9092e5b6d6dSopenharmony_ci                        + " since " + dateToString(startTime));
9102e5b6d6dSopenharmony_ci                } else {
9112e5b6d6dSopenharmony_ci                    // Check equivalency after the first transition.
9122e5b6d6dSopenharmony_ci                    // The DST information before the first transition might be lost
9132e5b6d6dSopenharmony_ci                    // because there is no good way to represent the initial time with
9142e5b6d6dSopenharmony_ci                    // VTIMEZONE.
9152e5b6d6dSopenharmony_ci                    int32_t raw1, raw2, dst1, dst2;
9162e5b6d6dSopenharmony_ci                    tz->getOffset(startTime, false, raw1, dst1, status);
9172e5b6d6dSopenharmony_ci                    vtz_new->getOffset(startTime, false, raw2, dst2, status);
9182e5b6d6dSopenharmony_ci                    if (U_FAILURE(status)) {
9192e5b6d6dSopenharmony_ci                        errln("FAIL: error status is returned from getOffset");
9202e5b6d6dSopenharmony_ci                    } else {
9212e5b6d6dSopenharmony_ci                        if (raw1 + dst1 != raw2 + dst2) {
9222e5b6d6dSopenharmony_ci                            errln("FAIL: VTimeZone for " + *tzid +
9232e5b6d6dSopenharmony_ci                                " is not equivalent to its OlsonTimeZone corresponding at "
9242e5b6d6dSopenharmony_ci                                + dateToString(startTime));
9252e5b6d6dSopenharmony_ci                        }
9262e5b6d6dSopenharmony_ci                        TimeZoneTransition trans;
9272e5b6d6dSopenharmony_ci                        UBool avail = tz->getNextTransition(startTime, false, trans);
9282e5b6d6dSopenharmony_ci                        if (avail) {
9292e5b6d6dSopenharmony_ci                            if (!vtz_new->hasEquivalentTransitions(*tz, trans.getTime(),
9302e5b6d6dSopenharmony_ci                                    endTime, true, status)) {
9312e5b6d6dSopenharmony_ci                                int32_t maxDelta = 1000;
9322e5b6d6dSopenharmony_ci                                if (!hasEquivalentTransitions(*vtz_new, *tz, trans.getTime() + maxDelta,
9332e5b6d6dSopenharmony_ci                                    endTime, true, maxDelta, status)) {
9342e5b6d6dSopenharmony_ci                                    errln("FAIL: VTimeZone for " + *tzid +
9352e5b6d6dSopenharmony_ci                                        " is not equivalent to its OlsonTimeZone corresponding.");
9362e5b6d6dSopenharmony_ci                                } else {
9372e5b6d6dSopenharmony_ci                                    logln("VTimeZone for " + *tzid +
9382e5b6d6dSopenharmony_ci                                        "  differs from its OlsonTimeZone corresponding with maximum transition time delta - " + maxDelta);
9392e5b6d6dSopenharmony_ci                                }
9402e5b6d6dSopenharmony_ci
9412e5b6d6dSopenharmony_ci                            }
9422e5b6d6dSopenharmony_ci                            if (U_FAILURE(status)) {
9432e5b6d6dSopenharmony_ci                                errln("FAIL: error status is returned from hasEquivalentTransition");
9442e5b6d6dSopenharmony_ci                            }
9452e5b6d6dSopenharmony_ci                        }
9462e5b6d6dSopenharmony_ci                    }
9472e5b6d6dSopenharmony_ci                }
9482e5b6d6dSopenharmony_ci            }
9492e5b6d6dSopenharmony_ci            if (vtz_new != NULL) {
9502e5b6d6dSopenharmony_ci                delete vtz_new;
9512e5b6d6dSopenharmony_ci                vtz_new = NULL;
9522e5b6d6dSopenharmony_ci            }
9532e5b6d6dSopenharmony_ci        }
9542e5b6d6dSopenharmony_ci        delete tz;
9552e5b6d6dSopenharmony_ci        delete vtz_org;
9562e5b6d6dSopenharmony_ci    }
9572e5b6d6dSopenharmony_ci}
9582e5b6d6dSopenharmony_ci
9592e5b6d6dSopenharmony_ci/*
9602e5b6d6dSopenharmony_ci * Write out simple time zone rules from an OlsonTimeZone at various time into VTIMEZONE
9612e5b6d6dSopenharmony_ci * format and create a new VTimeZone from the VTIMEZONE data, then make sure the raw offset
9622e5b6d6dSopenharmony_ci * and DST savings are same in these two time zones.
9632e5b6d6dSopenharmony_ci */
9642e5b6d6dSopenharmony_civoid
9652e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestVTimeZoneSimpleWrite(void) {
9662e5b6d6dSopenharmony_ci    const int32_t TESTDATES[][3] = {
9672e5b6d6dSopenharmony_ci        {2006,  UCAL_JANUARY,   1},
9682e5b6d6dSopenharmony_ci        {2006,  UCAL_MARCH,     15},
9692e5b6d6dSopenharmony_ci        {2006,  UCAL_MARCH,     31},
9702e5b6d6dSopenharmony_ci        {2006,  UCAL_OCTOBER,   25},
9712e5b6d6dSopenharmony_ci        {2006,  UCAL_NOVEMBER,  1},
9722e5b6d6dSopenharmony_ci        {2006,  UCAL_NOVEMBER,  5},
9732e5b6d6dSopenharmony_ci        {2007,  UCAL_JANUARY,   1},
9742e5b6d6dSopenharmony_ci        {0,     0,              0}
9752e5b6d6dSopenharmony_ci    };
9762e5b6d6dSopenharmony_ci
9772e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
9782e5b6d6dSopenharmony_ci    TestZIDEnumeration tzenum(!quick);
9792e5b6d6dSopenharmony_ci    while (true) {
9802e5b6d6dSopenharmony_ci        const UnicodeString *tzid = tzenum.snext(status);
9812e5b6d6dSopenharmony_ci        if (tzid == NULL) {
9822e5b6d6dSopenharmony_ci            break;
9832e5b6d6dSopenharmony_ci        }
9842e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
9852e5b6d6dSopenharmony_ci            errln("FAIL: error returned while enumerating timezone IDs.");
9862e5b6d6dSopenharmony_ci            break;
9872e5b6d6dSopenharmony_ci        }
9882e5b6d6dSopenharmony_ci        VTimeZone *vtz_org = VTimeZone::createVTimeZoneByID(*tzid);
9892e5b6d6dSopenharmony_ci        VTimeZone *vtz_new = NULL;
9902e5b6d6dSopenharmony_ci        UnicodeString vtzdata;
9912e5b6d6dSopenharmony_ci
9922e5b6d6dSopenharmony_ci        for (int32_t i = 0; TESTDATES[i][0] != 0; i++) {
9932e5b6d6dSopenharmony_ci            // Write out VTIMEZONE
9942e5b6d6dSopenharmony_ci            UDate time = getUTCMillis(TESTDATES[i][0], TESTDATES[i][1], TESTDATES[i][2]);
9952e5b6d6dSopenharmony_ci            vtz_org->writeSimple(time, vtzdata, status);
9962e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
9972e5b6d6dSopenharmony_ci                errln((UnicodeString)"FAIL: error returned while writing simple time zone rules for " +
9982e5b6d6dSopenharmony_ci                    *tzid + " into VTIMEZONE format at " + dateToString(time));
9992e5b6d6dSopenharmony_ci            } else {
10002e5b6d6dSopenharmony_ci                // Read VTIMEZONE data
10012e5b6d6dSopenharmony_ci                vtz_new = VTimeZone::createVTimeZone(vtzdata, status);
10022e5b6d6dSopenharmony_ci                if (U_FAILURE(status)) {
10032e5b6d6dSopenharmony_ci                    errln((UnicodeString)"FAIL: error returned while reading simple VTIMEZONE data for " + *tzid
10042e5b6d6dSopenharmony_ci                        + " at " + dateToString(time));
10052e5b6d6dSopenharmony_ci                } else {
10062e5b6d6dSopenharmony_ci                    // Check equivalency
10072e5b6d6dSopenharmony_ci                    int32_t raw0, dst0;
10082e5b6d6dSopenharmony_ci                    int32_t raw1, dst1;
10092e5b6d6dSopenharmony_ci                    vtz_org->getOffset(time, false, raw0, dst0, status);
10102e5b6d6dSopenharmony_ci                    vtz_new->getOffset(time, false, raw1, dst1, status);
10112e5b6d6dSopenharmony_ci                    if (U_SUCCESS(status)) {
10122e5b6d6dSopenharmony_ci                        if (raw0 != raw1 || dst0 != dst1) {
10132e5b6d6dSopenharmony_ci                            errln("FAIL: VTimeZone writeSimple for " + *tzid + " at "
10142e5b6d6dSopenharmony_ci                                + dateToString(time) + " failed to the round trip.");
10152e5b6d6dSopenharmony_ci                        }
10162e5b6d6dSopenharmony_ci                    } else {
10172e5b6d6dSopenharmony_ci                        errln("FAIL: getOffset returns error status");
10182e5b6d6dSopenharmony_ci                    }
10192e5b6d6dSopenharmony_ci                }
10202e5b6d6dSopenharmony_ci            }
10212e5b6d6dSopenharmony_ci            if (vtz_new != NULL) {
10222e5b6d6dSopenharmony_ci                delete vtz_new;
10232e5b6d6dSopenharmony_ci                vtz_new = NULL;
10242e5b6d6dSopenharmony_ci            }
10252e5b6d6dSopenharmony_ci        }
10262e5b6d6dSopenharmony_ci        delete vtz_org;
10272e5b6d6dSopenharmony_ci    }
10282e5b6d6dSopenharmony_ci}
10292e5b6d6dSopenharmony_ci
10302e5b6d6dSopenharmony_ci/*
10312e5b6d6dSopenharmony_ci * Write out time zone rules of OlsonTimeZone into VTIMEZONE format with RFC2445 header TZURL and
10322e5b6d6dSopenharmony_ci * LAST-MODIFIED, create a new VTimeZone from the VTIMEZONE data to see if the headers are preserved.
10332e5b6d6dSopenharmony_ci */
10342e5b6d6dSopenharmony_civoid
10352e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestVTimeZoneHeaderProps(void) {
10362e5b6d6dSopenharmony_ci    const UnicodeString TESTURL1("http://source.icu-project.org");
10372e5b6d6dSopenharmony_ci    const UnicodeString TESTURL2("http://www.ibm.com");
10382e5b6d6dSopenharmony_ci
10392e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
10402e5b6d6dSopenharmony_ci    UnicodeString tzurl;
10412e5b6d6dSopenharmony_ci    UDate lmod;
10422e5b6d6dSopenharmony_ci    UDate lastmod = getUTCMillis(2007, UCAL_JUNE, 1);
10432e5b6d6dSopenharmony_ci    VTimeZone *vtz = VTimeZone::createVTimeZoneByID("America/Chicago");
10442e5b6d6dSopenharmony_ci    vtz->setTZURL(TESTURL1);
10452e5b6d6dSopenharmony_ci    vtz->setLastModified(lastmod);
10462e5b6d6dSopenharmony_ci
10472e5b6d6dSopenharmony_ci    // Roundtrip conversion
10482e5b6d6dSopenharmony_ci    UnicodeString vtzdata;
10492e5b6d6dSopenharmony_ci    vtz->write(vtzdata, status);
10502e5b6d6dSopenharmony_ci    VTimeZone *newvtz1 = NULL;
10512e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
10522e5b6d6dSopenharmony_ci        errln("FAIL: error returned while writing VTIMEZONE data 1");
10532e5b6d6dSopenharmony_ci        return;
10542e5b6d6dSopenharmony_ci    }
10552e5b6d6dSopenharmony_ci    // Create a new one
10562e5b6d6dSopenharmony_ci    newvtz1 = VTimeZone::createVTimeZone(vtzdata, status);
10572e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
10582e5b6d6dSopenharmony_ci        errln("FAIL: error returned while loading VTIMEZONE data 1");
10592e5b6d6dSopenharmony_ci    } else {
10602e5b6d6dSopenharmony_ci        // Check if TZURL and LAST-MODIFIED properties are preserved
10612e5b6d6dSopenharmony_ci        newvtz1->getTZURL(tzurl);
10622e5b6d6dSopenharmony_ci        if (tzurl != TESTURL1) {
10632e5b6d6dSopenharmony_ci            errln("FAIL: TZURL 1 was not preserved");
10642e5b6d6dSopenharmony_ci        }
10652e5b6d6dSopenharmony_ci        vtz->getLastModified(lmod);
10662e5b6d6dSopenharmony_ci        if (lastmod != lmod) {
10672e5b6d6dSopenharmony_ci            errln("FAIL: LAST-MODIFIED was not preserved");
10682e5b6d6dSopenharmony_ci        }
10692e5b6d6dSopenharmony_ci    }
10702e5b6d6dSopenharmony_ci
10712e5b6d6dSopenharmony_ci    if (U_SUCCESS(status)) {
10722e5b6d6dSopenharmony_ci        // Set different tzurl
10732e5b6d6dSopenharmony_ci        newvtz1->setTZURL(TESTURL2);
10742e5b6d6dSopenharmony_ci
10752e5b6d6dSopenharmony_ci        // Second roundtrip, with a cutover
10762e5b6d6dSopenharmony_ci        newvtz1->write(vtzdata, status);
10772e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
10782e5b6d6dSopenharmony_ci            errln("FAIL: error returned while writing VTIMEZONE data 2");
10792e5b6d6dSopenharmony_ci        } else {
10802e5b6d6dSopenharmony_ci            VTimeZone *newvtz2 = VTimeZone::createVTimeZone(vtzdata, status);
10812e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
10822e5b6d6dSopenharmony_ci                errln("FAIL: error returned while loading VTIMEZONE data 2");
10832e5b6d6dSopenharmony_ci            } else {
10842e5b6d6dSopenharmony_ci                // Check if TZURL and LAST-MODIFIED properties are preserved
10852e5b6d6dSopenharmony_ci                newvtz2->getTZURL(tzurl);
10862e5b6d6dSopenharmony_ci                if (tzurl != TESTURL2) {
10872e5b6d6dSopenharmony_ci                    errln("FAIL: TZURL was not preserved in the second roundtrip");
10882e5b6d6dSopenharmony_ci                }
10892e5b6d6dSopenharmony_ci                vtz->getLastModified(lmod);
10902e5b6d6dSopenharmony_ci                if (lastmod != lmod) {
10912e5b6d6dSopenharmony_ci                    errln("FAIL: LAST-MODIFIED was not preserved in the second roundtrip");
10922e5b6d6dSopenharmony_ci                }
10932e5b6d6dSopenharmony_ci            }
10942e5b6d6dSopenharmony_ci            delete newvtz2;
10952e5b6d6dSopenharmony_ci        }
10962e5b6d6dSopenharmony_ci    }
10972e5b6d6dSopenharmony_ci    delete newvtz1;
10982e5b6d6dSopenharmony_ci    delete vtz;
10992e5b6d6dSopenharmony_ci}
11002e5b6d6dSopenharmony_ci
11012e5b6d6dSopenharmony_ci/*
11022e5b6d6dSopenharmony_ci * Extract simple rules from an OlsonTimeZone and make sure the rule format matches
11032e5b6d6dSopenharmony_ci * the expected format.
11042e5b6d6dSopenharmony_ci */
11052e5b6d6dSopenharmony_civoid
11062e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestGetSimpleRules(void) {
11072e5b6d6dSopenharmony_ci    UDate testTimes[] = {
11082e5b6d6dSopenharmony_ci        getUTCMillis(1970, UCAL_JANUARY, 1),
11092e5b6d6dSopenharmony_ci        getUTCMillis(2000, UCAL_MARCH, 31),
11102e5b6d6dSopenharmony_ci        getUTCMillis(2005, UCAL_JULY, 1),
11112e5b6d6dSopenharmony_ci        getUTCMillis(2010, UCAL_NOVEMBER, 1),
11122e5b6d6dSopenharmony_ci    };
11132e5b6d6dSopenharmony_ci    int32_t numTimes = UPRV_LENGTHOF(testTimes);
11142e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
11152e5b6d6dSopenharmony_ci    TestZIDEnumeration tzenum(!quick);
11162e5b6d6dSopenharmony_ci    InitialTimeZoneRule *initial;
11172e5b6d6dSopenharmony_ci    AnnualTimeZoneRule *std, *dst;
11182e5b6d6dSopenharmony_ci    for (int32_t i = 0; i < numTimes ; i++) {
11192e5b6d6dSopenharmony_ci        while (true) {
11202e5b6d6dSopenharmony_ci            const UnicodeString *tzid = tzenum.snext(status);
11212e5b6d6dSopenharmony_ci            if (tzid == NULL) {
11222e5b6d6dSopenharmony_ci                break;
11232e5b6d6dSopenharmony_ci            }
11242e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
11252e5b6d6dSopenharmony_ci                errln("FAIL: error returned while enumerating timezone IDs.");
11262e5b6d6dSopenharmony_ci                break;
11272e5b6d6dSopenharmony_ci            }
11282e5b6d6dSopenharmony_ci            BasicTimeZone *tz = (BasicTimeZone*)TimeZone::createTimeZone(*tzid);
11292e5b6d6dSopenharmony_ci            initial = NULL;
11302e5b6d6dSopenharmony_ci            std = dst = NULL;
11312e5b6d6dSopenharmony_ci            tz->getSimpleRulesNear(testTimes[i], initial, std, dst, status);
11322e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
11332e5b6d6dSopenharmony_ci                errln("FAIL: getSimpleRules failed.");
11342e5b6d6dSopenharmony_ci                break;
11352e5b6d6dSopenharmony_ci            }
11362e5b6d6dSopenharmony_ci            if (initial == NULL) {
11372e5b6d6dSopenharmony_ci                errln("FAIL: initial rule must not be NULL");
11382e5b6d6dSopenharmony_ci                break;
11392e5b6d6dSopenharmony_ci            } else if (!((std == NULL && dst == NULL) || (std != NULL && dst != NULL))) {
11402e5b6d6dSopenharmony_ci                errln("FAIL: invalid std/dst pair.");
11412e5b6d6dSopenharmony_ci                break;
11422e5b6d6dSopenharmony_ci            }
11432e5b6d6dSopenharmony_ci            if (std != NULL) {
11442e5b6d6dSopenharmony_ci                const DateTimeRule *dtr = std->getRule();
11452e5b6d6dSopenharmony_ci                if (dtr->getDateRuleType() != DateTimeRule::DOW) {
11462e5b6d6dSopenharmony_ci                    errln("FAIL: simple std rull must use DateTimeRule::DOW as date rule.");
11472e5b6d6dSopenharmony_ci                    break;
11482e5b6d6dSopenharmony_ci                }
11492e5b6d6dSopenharmony_ci                if (dtr->getTimeRuleType() != DateTimeRule::WALL_TIME) {
11502e5b6d6dSopenharmony_ci                    errln("FAIL: simple std rull must use DateTimeRule::WALL_TIME as time rule.");
11512e5b6d6dSopenharmony_ci                    break;
11522e5b6d6dSopenharmony_ci                }
11532e5b6d6dSopenharmony_ci                dtr = dst->getRule();
11542e5b6d6dSopenharmony_ci                if (dtr->getDateRuleType() != DateTimeRule::DOW) {
11552e5b6d6dSopenharmony_ci                    errln("FAIL: simple dst rull must use DateTimeRule::DOW as date rule.");
11562e5b6d6dSopenharmony_ci                    break;
11572e5b6d6dSopenharmony_ci                }
11582e5b6d6dSopenharmony_ci                if (dtr->getTimeRuleType() != DateTimeRule::WALL_TIME) {
11592e5b6d6dSopenharmony_ci                    errln("FAIL: simple dst rull must use DateTimeRule::WALL_TIME as time rule.");
11602e5b6d6dSopenharmony_ci                    break;
11612e5b6d6dSopenharmony_ci                }
11622e5b6d6dSopenharmony_ci            }
11632e5b6d6dSopenharmony_ci            // Create an RBTZ from the rules and compare the offsets at the date
11642e5b6d6dSopenharmony_ci            RuleBasedTimeZone *rbtz = new RuleBasedTimeZone(*tzid, initial);
11652e5b6d6dSopenharmony_ci            if (std != NULL) {
11662e5b6d6dSopenharmony_ci                rbtz->addTransitionRule(std, status);
11672e5b6d6dSopenharmony_ci                if (U_FAILURE(status)) {
11682e5b6d6dSopenharmony_ci                    errln("FAIL: couldn't add std rule.");
11692e5b6d6dSopenharmony_ci                }
11702e5b6d6dSopenharmony_ci                rbtz->addTransitionRule(dst, status);
11712e5b6d6dSopenharmony_ci                if (U_FAILURE(status)) {
11722e5b6d6dSopenharmony_ci                    errln("FAIL: couldn't add dst rule.");
11732e5b6d6dSopenharmony_ci                }
11742e5b6d6dSopenharmony_ci            }
11752e5b6d6dSopenharmony_ci            rbtz->complete(status);
11762e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
11772e5b6d6dSopenharmony_ci                errln("FAIL: couldn't complete rbtz for " + *tzid);
11782e5b6d6dSopenharmony_ci            }
11792e5b6d6dSopenharmony_ci
11802e5b6d6dSopenharmony_ci            int32_t raw0, dst0, raw1, dst1;
11812e5b6d6dSopenharmony_ci            tz->getOffset(testTimes[i], false, raw0, dst0, status);
11822e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
11832e5b6d6dSopenharmony_ci                errln("FAIL: couldn't get offsets from tz for " + *tzid);
11842e5b6d6dSopenharmony_ci            }
11852e5b6d6dSopenharmony_ci            rbtz->getOffset(testTimes[i], false, raw1, dst1, status);
11862e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
11872e5b6d6dSopenharmony_ci                errln("FAIL: couldn't get offsets from rbtz for " + *tzid);
11882e5b6d6dSopenharmony_ci            }
11892e5b6d6dSopenharmony_ci            if (raw0 != raw1 || dst0 != dst1) {
11902e5b6d6dSopenharmony_ci                errln("FAIL: rbtz created by simple rule does not match the original tz for tzid " + *tzid);
11912e5b6d6dSopenharmony_ci            }
11922e5b6d6dSopenharmony_ci            delete rbtz;
11932e5b6d6dSopenharmony_ci            delete tz;
11942e5b6d6dSopenharmony_ci        }
11952e5b6d6dSopenharmony_ci    }
11962e5b6d6dSopenharmony_ci}
11972e5b6d6dSopenharmony_ci
11982e5b6d6dSopenharmony_ci/*
11992e5b6d6dSopenharmony_ci * API coverage tests for TimeZoneRule
12002e5b6d6dSopenharmony_ci */
12012e5b6d6dSopenharmony_civoid
12022e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestTimeZoneRuleCoverage(void) {
12032e5b6d6dSopenharmony_ci    UDate time1 = getUTCMillis(2005, UCAL_JULY, 4);
12042e5b6d6dSopenharmony_ci    UDate time2 = getUTCMillis(2015, UCAL_JULY, 4);
12052e5b6d6dSopenharmony_ci    UDate time3 = getUTCMillis(1950, UCAL_JULY, 4);
12062e5b6d6dSopenharmony_ci
12072e5b6d6dSopenharmony_ci    DateTimeRule *dtr1 = new DateTimeRule(UCAL_FEBRUARY, 29, UCAL_SUNDAY, false,
12082e5b6d6dSopenharmony_ci            3*HOUR, DateTimeRule::WALL_TIME); // Last Sunday on or before Feb 29, at 3 AM, wall time
12092e5b6d6dSopenharmony_ci    DateTimeRule *dtr2 = new DateTimeRule(UCAL_MARCH, 11, 2*HOUR,
12102e5b6d6dSopenharmony_ci            DateTimeRule::STANDARD_TIME); // Mar 11, at 2 AM, standard time
12112e5b6d6dSopenharmony_ci    DateTimeRule *dtr3 = new DateTimeRule(UCAL_OCTOBER, -1, UCAL_SATURDAY,
12122e5b6d6dSopenharmony_ci            6*HOUR, DateTimeRule::UTC_TIME); //Last Saturday in Oct, at 6 AM, UTC
12132e5b6d6dSopenharmony_ci    DateTimeRule *dtr4 = new DateTimeRule(UCAL_MARCH, 8, UCAL_SUNDAY, true,
12142e5b6d6dSopenharmony_ci            2*HOUR, DateTimeRule::WALL_TIME); // First Sunday on or after Mar 8, at 2 AM, wall time
12152e5b6d6dSopenharmony_ci
12162e5b6d6dSopenharmony_ci    AnnualTimeZoneRule *a1 = new AnnualTimeZoneRule("a1", -3*HOUR, 1*HOUR, *dtr1,
12172e5b6d6dSopenharmony_ci            2000, AnnualTimeZoneRule::MAX_YEAR);
12182e5b6d6dSopenharmony_ci    AnnualTimeZoneRule *a2 = new AnnualTimeZoneRule("a2", -3*HOUR, 1*HOUR, *dtr1,
12192e5b6d6dSopenharmony_ci            2000, AnnualTimeZoneRule::MAX_YEAR);
12202e5b6d6dSopenharmony_ci    AnnualTimeZoneRule *a3 = new AnnualTimeZoneRule("a3", -3*HOUR, 1*HOUR, *dtr1,
12212e5b6d6dSopenharmony_ci            2000, 2010);
12222e5b6d6dSopenharmony_ci
12232e5b6d6dSopenharmony_ci    InitialTimeZoneRule *i1 = new InitialTimeZoneRule("i1", -3*HOUR, 0);
12242e5b6d6dSopenharmony_ci    InitialTimeZoneRule *i2 = new InitialTimeZoneRule("i2", -3*HOUR, 0);
12252e5b6d6dSopenharmony_ci    InitialTimeZoneRule *i3 = new InitialTimeZoneRule("i3", -3*HOUR, 1*HOUR);
12262e5b6d6dSopenharmony_ci
12272e5b6d6dSopenharmony_ci    UDate trtimes1[] = {0.0};
12282e5b6d6dSopenharmony_ci    UDate trtimes2[] = {0.0, 10000000.0};
12292e5b6d6dSopenharmony_ci
12302e5b6d6dSopenharmony_ci    TimeArrayTimeZoneRule *t1 = new TimeArrayTimeZoneRule("t1", -3*HOUR, 0, trtimes1, 1, DateTimeRule::UTC_TIME);
12312e5b6d6dSopenharmony_ci    TimeArrayTimeZoneRule *t2 = new TimeArrayTimeZoneRule("t2", -3*HOUR, 0, trtimes1, 1, DateTimeRule::UTC_TIME);
12322e5b6d6dSopenharmony_ci    TimeArrayTimeZoneRule *t3 = new TimeArrayTimeZoneRule("t3", -3*HOUR, 0, trtimes2, 2, DateTimeRule::UTC_TIME);
12332e5b6d6dSopenharmony_ci    TimeArrayTimeZoneRule *t4 = new TimeArrayTimeZoneRule("t4", -3*HOUR, 0, trtimes1, 1, DateTimeRule::STANDARD_TIME);
12342e5b6d6dSopenharmony_ci    TimeArrayTimeZoneRule *t5 = new TimeArrayTimeZoneRule("t5", -4*HOUR, 1*HOUR, trtimes1, 1, DateTimeRule::WALL_TIME);
12352e5b6d6dSopenharmony_ci
12362e5b6d6dSopenharmony_ci    // DateTimeRule::operator=/clone
12372e5b6d6dSopenharmony_ci    DateTimeRule dtr0(UCAL_MAY, 31, 2*HOUR, DateTimeRule::WALL_TIME);
12382e5b6d6dSopenharmony_ci    if (dtr0 == *dtr1 || !(dtr0 != *dtr1)) {
12392e5b6d6dSopenharmony_ci        errln("FAIL: DateTimeRule dtr0 is not equal to dtr1, but got wrong result");
12402e5b6d6dSopenharmony_ci    }
12412e5b6d6dSopenharmony_ci    dtr0 = *dtr1;
12422e5b6d6dSopenharmony_ci    if (dtr0 != *dtr1 || !(dtr0 == *dtr1)) {
12432e5b6d6dSopenharmony_ci        errln("FAIL: DateTimeRule dtr0 is equal to dtr1, but got wrong result");
12442e5b6d6dSopenharmony_ci    }
12452e5b6d6dSopenharmony_ci    DateTimeRule *dtr0c = dtr0.clone();
12462e5b6d6dSopenharmony_ci    if (*dtr0c != *dtr1 || !(*dtr0c == *dtr1)) {
12472e5b6d6dSopenharmony_ci        errln("FAIL: DateTimeRule dtr0c is equal to dtr1, but got wrong result");
12482e5b6d6dSopenharmony_ci    }
12492e5b6d6dSopenharmony_ci    delete dtr0c;
12502e5b6d6dSopenharmony_ci
12512e5b6d6dSopenharmony_ci    // AnnualTimeZonerule::operator=/clone
12522e5b6d6dSopenharmony_ci    AnnualTimeZoneRule a0("a0", 5*HOUR, 1*HOUR, *dtr1, 1990, AnnualTimeZoneRule::MAX_YEAR);
12532e5b6d6dSopenharmony_ci    if (a0 == *a1 || !(a0 != *a1)) {
12542e5b6d6dSopenharmony_ci        errln("FAIL: AnnualTimeZoneRule a0 is not equal to a1, but got wrong result");
12552e5b6d6dSopenharmony_ci    }
12562e5b6d6dSopenharmony_ci    a0 = *a1;
12572e5b6d6dSopenharmony_ci    if (a0 != *a1 || !(a0 == *a1)) {
12582e5b6d6dSopenharmony_ci        errln("FAIL: AnnualTimeZoneRule a0 is equal to a1, but got wrong result");
12592e5b6d6dSopenharmony_ci    }
12602e5b6d6dSopenharmony_ci    AnnualTimeZoneRule *a0c = a0.clone();
12612e5b6d6dSopenharmony_ci    if (*a0c != *a1 || !(*a0c == *a1)) {
12622e5b6d6dSopenharmony_ci        errln("FAIL: AnnualTimeZoneRule a0c is equal to a1, but got wrong result");
12632e5b6d6dSopenharmony_ci    }
12642e5b6d6dSopenharmony_ci    delete a0c;
12652e5b6d6dSopenharmony_ci
12662e5b6d6dSopenharmony_ci    // AnnualTimeZoneRule::getRule
12672e5b6d6dSopenharmony_ci    if (*(a1->getRule()) != *(a2->getRule())) {
12682e5b6d6dSopenharmony_ci        errln("FAIL: The same DateTimeRule must be returned from AnnualTimeZoneRule a1 and a2");
12692e5b6d6dSopenharmony_ci    }
12702e5b6d6dSopenharmony_ci
12712e5b6d6dSopenharmony_ci    // AnnualTimeZoneRule::getStartYear
12722e5b6d6dSopenharmony_ci    int32_t startYear = a1->getStartYear();
12732e5b6d6dSopenharmony_ci    if (startYear != 2000) {
12742e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: The start year of AnnualTimeZoneRule a1 must be 2000 - returned: " + startYear);
12752e5b6d6dSopenharmony_ci    }
12762e5b6d6dSopenharmony_ci
12772e5b6d6dSopenharmony_ci    // AnnualTimeZoneRule::getEndYear
12782e5b6d6dSopenharmony_ci    int32_t endYear = a1->getEndYear();
12792e5b6d6dSopenharmony_ci    if (endYear != AnnualTimeZoneRule::MAX_YEAR) {
12802e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: The start year of AnnualTimeZoneRule a1 must be MAX_YEAR - returned: " + endYear);
12812e5b6d6dSopenharmony_ci    }
12822e5b6d6dSopenharmony_ci    endYear = a3->getEndYear();
12832e5b6d6dSopenharmony_ci    if (endYear != 2010) {
12842e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: The start year of AnnualTimeZoneRule a3 must be 2010 - returned: " + endYear);
12852e5b6d6dSopenharmony_ci    }
12862e5b6d6dSopenharmony_ci
12872e5b6d6dSopenharmony_ci    // AnnualTimeZone::getStartInYear
12882e5b6d6dSopenharmony_ci    UBool b1, b2;
12892e5b6d6dSopenharmony_ci    UDate d1, d2;
12902e5b6d6dSopenharmony_ci    b1 = a1->getStartInYear(2005, -3*HOUR, 0, d1);
12912e5b6d6dSopenharmony_ci    b2 = a3->getStartInYear(2005, -3*HOUR, 0, d2);
12922e5b6d6dSopenharmony_ci    if (!b1 || !b2 || d1 != d2) {
12932e5b6d6dSopenharmony_ci        errln("FAIL: AnnualTimeZoneRule::getStartInYear did not work as expected");
12942e5b6d6dSopenharmony_ci    }
12952e5b6d6dSopenharmony_ci    b2 = a3->getStartInYear(2015, -3*HOUR, 0, d2);
12962e5b6d6dSopenharmony_ci    if (b2) {
12972e5b6d6dSopenharmony_ci        errln("FAIL: AnnualTimeZoneRule::getStartInYear returned true for 2015 which is out of rule range");
12982e5b6d6dSopenharmony_ci    }
12992e5b6d6dSopenharmony_ci
13002e5b6d6dSopenharmony_ci    // AnnualTimeZone::getFirstStart
13012e5b6d6dSopenharmony_ci    b1 = a1->getFirstStart(-3*HOUR, 0, d1);
13022e5b6d6dSopenharmony_ci    b2 = a1->getFirstStart(-4*HOUR, 1*HOUR, d2);
13032e5b6d6dSopenharmony_ci    if (!b1 || !b2 || d1 != d2) {
13042e5b6d6dSopenharmony_ci        errln("FAIL: The same start time should be returned by getFirstStart");
13052e5b6d6dSopenharmony_ci    }
13062e5b6d6dSopenharmony_ci
13072e5b6d6dSopenharmony_ci    // AnnualTimeZone::getFinalStart
13082e5b6d6dSopenharmony_ci    b1 = a1->getFinalStart(-3*HOUR, 0, d1);
13092e5b6d6dSopenharmony_ci    if (b1) {
13102e5b6d6dSopenharmony_ci        errln("FAIL: getFinalStart returned true for a1");
13112e5b6d6dSopenharmony_ci    }
13122e5b6d6dSopenharmony_ci    b1 = a1->getStartInYear(2010, -3*HOUR, 0, d1);
13132e5b6d6dSopenharmony_ci    b2 = a3->getFinalStart(-3*HOUR, 0, d2);
13142e5b6d6dSopenharmony_ci    if (!b1 || !b2 || d1 != d2) {
13152e5b6d6dSopenharmony_ci        errln("FAIL: Bad date is returned by getFinalStart");
13162e5b6d6dSopenharmony_ci    }
13172e5b6d6dSopenharmony_ci
13182e5b6d6dSopenharmony_ci    // AnnualTimeZone::getNextStart / getPreviousStart
13192e5b6d6dSopenharmony_ci    b1 = a1->getNextStart(time1, -3*HOUR, 0, false, d1);
13202e5b6d6dSopenharmony_ci    if (!b1) {
13212e5b6d6dSopenharmony_ci        errln("FAIL: getNextStart returned false for ai");
13222e5b6d6dSopenharmony_ci    } else {
13232e5b6d6dSopenharmony_ci        b2 = a1->getPreviousStart(d1, -3*HOUR, 0, true, d2);
13242e5b6d6dSopenharmony_ci        if (!b2 || d1 != d2) {
13252e5b6d6dSopenharmony_ci            errln("FAIL: Bad Date is returned by getPreviousStart");
13262e5b6d6dSopenharmony_ci        }
13272e5b6d6dSopenharmony_ci    }
13282e5b6d6dSopenharmony_ci    b1 = a3->getNextStart(time2, -3*HOUR, 0, false, d1);
13292e5b6d6dSopenharmony_ci    if (b1) {
13302e5b6d6dSopenharmony_ci        dataerrln("FAIL: getNextStart must return false when no start time is available after the base time");
13312e5b6d6dSopenharmony_ci    }
13322e5b6d6dSopenharmony_ci    b1 = a3->getFinalStart(-3*HOUR, 0, d1);
13332e5b6d6dSopenharmony_ci    b2 = a3->getPreviousStart(time2, -3*HOUR, 0, false, d2);
13342e5b6d6dSopenharmony_ci    if (!b1 || !b2 || d1 != d2) {
13352e5b6d6dSopenharmony_ci        dataerrln("FAIL: getPreviousStart does not match with getFinalStart after the end year");
13362e5b6d6dSopenharmony_ci    }
13372e5b6d6dSopenharmony_ci
13382e5b6d6dSopenharmony_ci    // AnnualTimeZone::isEquavalentTo
13392e5b6d6dSopenharmony_ci    if (!a1->isEquivalentTo(*a2)) {
13402e5b6d6dSopenharmony_ci        errln("FAIL: AnnualTimeZoneRule a1 is equivalent to a2, but returned false");
13412e5b6d6dSopenharmony_ci    }
13422e5b6d6dSopenharmony_ci    if (a1->isEquivalentTo(*a3)) {
13432e5b6d6dSopenharmony_ci        errln("FAIL: AnnualTimeZoneRule a1 is not equivalent to a3, but returned true");
13442e5b6d6dSopenharmony_ci    }
13452e5b6d6dSopenharmony_ci    if (!a1->isEquivalentTo(*a1)) {
13462e5b6d6dSopenharmony_ci        errln("FAIL: AnnualTimeZoneRule a1 is equivalent to itself, but returned false");
13472e5b6d6dSopenharmony_ci    }
13482e5b6d6dSopenharmony_ci    if (a1->isEquivalentTo(*t1)) {
13492e5b6d6dSopenharmony_ci        errln("FAIL: AnnualTimeZoneRule is not equivalent to TimeArrayTimeZoneRule, but returned true");
13502e5b6d6dSopenharmony_ci    }
13512e5b6d6dSopenharmony_ci
13522e5b6d6dSopenharmony_ci    // InitialTimezoneRule::operator=/clone
13532e5b6d6dSopenharmony_ci    InitialTimeZoneRule i0("i0", 10*HOUR, 0);
13542e5b6d6dSopenharmony_ci    if (i0 == *i1 || !(i0 != *i1)) {
13552e5b6d6dSopenharmony_ci        errln("FAIL: InitialTimeZoneRule i0 is not equal to i1, but got wrong result");
13562e5b6d6dSopenharmony_ci    }
13572e5b6d6dSopenharmony_ci    i0 = *i1;
13582e5b6d6dSopenharmony_ci    if (i0 != *i1 || !(i0 == *i1)) {
13592e5b6d6dSopenharmony_ci        errln("FAIL: InitialTimeZoneRule i0 is equal to i1, but got wrong result");
13602e5b6d6dSopenharmony_ci    }
13612e5b6d6dSopenharmony_ci    InitialTimeZoneRule *i0c = i0.clone();
13622e5b6d6dSopenharmony_ci    if (*i0c != *i1 || !(*i0c == *i1)) {
13632e5b6d6dSopenharmony_ci        errln("FAIL: InitialTimeZoneRule i0c is equal to i1, but got wrong result");
13642e5b6d6dSopenharmony_ci    }
13652e5b6d6dSopenharmony_ci    delete i0c;
13662e5b6d6dSopenharmony_ci
13672e5b6d6dSopenharmony_ci    // InitialTimeZoneRule::isEquivalentRule
13682e5b6d6dSopenharmony_ci    if (!i1->isEquivalentTo(*i2)) {
13692e5b6d6dSopenharmony_ci        errln("FAIL: InitialTimeZoneRule i1 is equivalent to i2, but returned false");
13702e5b6d6dSopenharmony_ci    }
13712e5b6d6dSopenharmony_ci    if (i1->isEquivalentTo(*i3)) {
13722e5b6d6dSopenharmony_ci        errln("FAIL: InitialTimeZoneRule i1 is not equivalent to i3, but returned true");
13732e5b6d6dSopenharmony_ci    }
13742e5b6d6dSopenharmony_ci    if (i1->isEquivalentTo(*a1)) {
13752e5b6d6dSopenharmony_ci        errln("FAIL: An InitialTimeZoneRule is not equivalent to an AnnualTimeZoneRule, but returned true");
13762e5b6d6dSopenharmony_ci    }
13772e5b6d6dSopenharmony_ci
13782e5b6d6dSopenharmony_ci    // InitialTimeZoneRule::getFirstStart/getFinalStart/getNextStart/getPreviousStart
13792e5b6d6dSopenharmony_ci    b1 = i1->getFirstStart(0, 0, d1);
13802e5b6d6dSopenharmony_ci    if (b1) {
13812e5b6d6dSopenharmony_ci        errln("FAIL: InitialTimeZone::getFirstStart returned true");
13822e5b6d6dSopenharmony_ci    }
13832e5b6d6dSopenharmony_ci    b1 = i1->getFinalStart(0, 0, d1);
13842e5b6d6dSopenharmony_ci    if (b1) {
13852e5b6d6dSopenharmony_ci        errln("FAIL: InitialTimeZone::getFinalStart returned true");
13862e5b6d6dSopenharmony_ci    }
13872e5b6d6dSopenharmony_ci    b1 = i1->getNextStart(time1, 0, 0, false, d1);
13882e5b6d6dSopenharmony_ci    if (b1) {
13892e5b6d6dSopenharmony_ci        errln("FAIL: InitialTimeZone::getNextStart returned true");
13902e5b6d6dSopenharmony_ci    }
13912e5b6d6dSopenharmony_ci    b1 = i1->getPreviousStart(time1, 0, 0, false, d1);
13922e5b6d6dSopenharmony_ci    if (b1) {
13932e5b6d6dSopenharmony_ci        errln("FAIL: InitialTimeZone::getPreviousStart returned true");
13942e5b6d6dSopenharmony_ci    }
13952e5b6d6dSopenharmony_ci
13962e5b6d6dSopenharmony_ci    // TimeArrayTimeZoneRule::operator=/clone
13972e5b6d6dSopenharmony_ci    TimeArrayTimeZoneRule t0("t0", 4*HOUR, 0, trtimes1, 1, DateTimeRule::UTC_TIME);
13982e5b6d6dSopenharmony_ci    if (t0 == *t1 || !(t0 != *t1)) {
13992e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule t0 is not equal to t1, but got wrong result");
14002e5b6d6dSopenharmony_ci    }
14012e5b6d6dSopenharmony_ci    t0 = *t1;
14022e5b6d6dSopenharmony_ci    if (t0 != *t1 || !(t0 == *t1)) {
14032e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule t0 is equal to t1, but got wrong result");
14042e5b6d6dSopenharmony_ci    }
14052e5b6d6dSopenharmony_ci    TimeArrayTimeZoneRule *t0c = t0.clone();
14062e5b6d6dSopenharmony_ci    if (*t0c != *t1 || !(*t0c == *t1)) {
14072e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule t0c is equal to t1, but got wrong result");
14082e5b6d6dSopenharmony_ci    }
14092e5b6d6dSopenharmony_ci    delete t0c;
14102e5b6d6dSopenharmony_ci
14112e5b6d6dSopenharmony_ci    // TimeArrayTimeZoneRule::countStartTimes
14122e5b6d6dSopenharmony_ci    if (t1->countStartTimes() != 1) {
14132e5b6d6dSopenharmony_ci        errln("FAIL: Bad start time count is returned by TimeArrayTimeZoneRule::countStartTimes");
14142e5b6d6dSopenharmony_ci    }
14152e5b6d6dSopenharmony_ci
14162e5b6d6dSopenharmony_ci    // TimeArrayTimeZoneRule::getStartTimeAt
14172e5b6d6dSopenharmony_ci    b1 = t1->getStartTimeAt(-1, d1);
14182e5b6d6dSopenharmony_ci    if (b1) {
14192e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned true for index -1");
14202e5b6d6dSopenharmony_ci    }
14212e5b6d6dSopenharmony_ci    b1 = t1->getStartTimeAt(0, d1);
14222e5b6d6dSopenharmony_ci    if (!b1 || d1 != trtimes1[0]) {
14232e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned incorrect result for index 0");
14242e5b6d6dSopenharmony_ci    }
14252e5b6d6dSopenharmony_ci    b1 = t1->getStartTimeAt(1, d1);
14262e5b6d6dSopenharmony_ci    if (b1) {
14272e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule::getStartTimeAt returned true for index 1");
14282e5b6d6dSopenharmony_ci    }
14292e5b6d6dSopenharmony_ci
14302e5b6d6dSopenharmony_ci    // TimeArrayTimeZoneRule::getTimeType
14312e5b6d6dSopenharmony_ci    if (t1->getTimeType() != DateTimeRule::UTC_TIME) {
14322e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule t1 uses UTC_TIME, but different type is returned");
14332e5b6d6dSopenharmony_ci    }
14342e5b6d6dSopenharmony_ci    if (t4->getTimeType() != DateTimeRule::STANDARD_TIME) {
14352e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule t4 uses STANDARD_TIME, but different type is returned");
14362e5b6d6dSopenharmony_ci    }
14372e5b6d6dSopenharmony_ci    if (t5->getTimeType() != DateTimeRule::WALL_TIME) {
14382e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule t5 uses WALL_TIME, but different type is returned");
14392e5b6d6dSopenharmony_ci    }
14402e5b6d6dSopenharmony_ci
14412e5b6d6dSopenharmony_ci    // TimeArrayTimeZoneRule::getFirstStart/getFinalStart
14422e5b6d6dSopenharmony_ci    b1 = t1->getFirstStart(0, 0, d1);
14432e5b6d6dSopenharmony_ci    if (!b1 || d1 != trtimes1[0]) {
14442e5b6d6dSopenharmony_ci        errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t1");
14452e5b6d6dSopenharmony_ci    }
14462e5b6d6dSopenharmony_ci    b1 = t1->getFinalStart(0, 0, d1);
14472e5b6d6dSopenharmony_ci    if (!b1 || d1 != trtimes1[0]) {
14482e5b6d6dSopenharmony_ci        errln("FAIL: Bad final start time returned from TimeArrayTimeZoneRule t1");
14492e5b6d6dSopenharmony_ci    }
14502e5b6d6dSopenharmony_ci    b1 = t4->getFirstStart(-4*HOUR, 1*HOUR, d1);
14512e5b6d6dSopenharmony_ci    if (!b1 || d1 != (trtimes1[0] + 4*HOUR)) {
14522e5b6d6dSopenharmony_ci        errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t4");
14532e5b6d6dSopenharmony_ci    }
14542e5b6d6dSopenharmony_ci    b1 = t5->getFirstStart(-4*HOUR, 1*HOUR, d1);
14552e5b6d6dSopenharmony_ci    if (!b1 || d1 != (trtimes1[0] + 3*HOUR)) {
14562e5b6d6dSopenharmony_ci        errln("FAIL: Bad first start time returned from TimeArrayTimeZoneRule t5");
14572e5b6d6dSopenharmony_ci    }
14582e5b6d6dSopenharmony_ci
14592e5b6d6dSopenharmony_ci    // TimeArrayTimeZoneRule::getNextStart/getPreviousStart
14602e5b6d6dSopenharmony_ci    b1 = t3->getNextStart(time1, -3*HOUR, 1*HOUR, false, d1);
14612e5b6d6dSopenharmony_ci    if (b1) {
14622e5b6d6dSopenharmony_ci        dataerrln("FAIL: getNextStart returned true after the final transition for t3");
14632e5b6d6dSopenharmony_ci    }
14642e5b6d6dSopenharmony_ci    b1 = t3->getPreviousStart(time1, -3*HOUR, 1*HOUR, false, d1);
14652e5b6d6dSopenharmony_ci    if (!b1 || d1 != trtimes2[1]) {
14662e5b6d6dSopenharmony_ci        dataerrln("FAIL: Bad start time returned by getPreviousStart for t3");
14672e5b6d6dSopenharmony_ci    } else {
14682e5b6d6dSopenharmony_ci        b2 = t3->getPreviousStart(d1, -3*HOUR, 1*HOUR, false, d2);
14692e5b6d6dSopenharmony_ci        if (!b2 || d2 != trtimes2[0]) {
14702e5b6d6dSopenharmony_ci            errln("FAIL: Bad start time returned by getPreviousStart for t3");
14712e5b6d6dSopenharmony_ci        }
14722e5b6d6dSopenharmony_ci    }
14732e5b6d6dSopenharmony_ci    b1 = t3->getPreviousStart(time3, -3*HOUR, 1*HOUR, false, d1); //time3 - year 1950, no result expected
14742e5b6d6dSopenharmony_ci    if (b1) {
14752e5b6d6dSopenharmony_ci        errln("FAIL: getPreviousStart returned true before the first transition for t3");
14762e5b6d6dSopenharmony_ci    }
14772e5b6d6dSopenharmony_ci
14782e5b6d6dSopenharmony_ci    // TimeArrayTimeZoneRule::isEquivalentTo
14792e5b6d6dSopenharmony_ci    if (!t1->isEquivalentTo(*t2)) {
14802e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule t1 is equivalent to t2, but returned false");
14812e5b6d6dSopenharmony_ci    }
14822e5b6d6dSopenharmony_ci    if (t1->isEquivalentTo(*t3)) {
14832e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule t1 is not equivalent to t3, but returned true");
14842e5b6d6dSopenharmony_ci    }
14852e5b6d6dSopenharmony_ci    if (t1->isEquivalentTo(*t4)) {
14862e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule t1 is not equivalent to t4, but returned true");
14872e5b6d6dSopenharmony_ci    }
14882e5b6d6dSopenharmony_ci    if (t1->isEquivalentTo(*a1)) {
14892e5b6d6dSopenharmony_ci        errln("FAIL: TimeArrayTimeZoneRule is not equivalent to AnnualTimeZoneRule, but returned true");
14902e5b6d6dSopenharmony_ci    }
14912e5b6d6dSopenharmony_ci
14922e5b6d6dSopenharmony_ci    delete dtr1;
14932e5b6d6dSopenharmony_ci    delete dtr2;
14942e5b6d6dSopenharmony_ci    delete dtr3;
14952e5b6d6dSopenharmony_ci    delete dtr4;
14962e5b6d6dSopenharmony_ci    delete a1;
14972e5b6d6dSopenharmony_ci    delete a2;
14982e5b6d6dSopenharmony_ci    delete a3;
14992e5b6d6dSopenharmony_ci    delete i1;
15002e5b6d6dSopenharmony_ci    delete i2;
15012e5b6d6dSopenharmony_ci    delete i3;
15022e5b6d6dSopenharmony_ci    delete t1;
15032e5b6d6dSopenharmony_ci    delete t2;
15042e5b6d6dSopenharmony_ci    delete t3;
15052e5b6d6dSopenharmony_ci    delete t4;
15062e5b6d6dSopenharmony_ci    delete t5;
15072e5b6d6dSopenharmony_ci}
15082e5b6d6dSopenharmony_ci
15092e5b6d6dSopenharmony_ci/*
15102e5b6d6dSopenharmony_ci * API coverage test for BasicTimeZone APIs in SimpleTimeZone
15112e5b6d6dSopenharmony_ci */
15122e5b6d6dSopenharmony_civoid
15132e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestSimpleTimeZoneCoverage(void) {
15142e5b6d6dSopenharmony_ci    UDate time1 = getUTCMillis(1990, UCAL_JUNE, 1);
15152e5b6d6dSopenharmony_ci    UDate time2 = getUTCMillis(2000, UCAL_JUNE, 1);
15162e5b6d6dSopenharmony_ci
15172e5b6d6dSopenharmony_ci    TimeZoneTransition tzt1, tzt2;
15182e5b6d6dSopenharmony_ci    UBool avail1, avail2;
15192e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
15202e5b6d6dSopenharmony_ci    const TimeZoneRule *trrules[2];
15212e5b6d6dSopenharmony_ci    const InitialTimeZoneRule *ir = NULL;
15222e5b6d6dSopenharmony_ci    int32_t numTzRules;
15232e5b6d6dSopenharmony_ci
15242e5b6d6dSopenharmony_ci    // BasicTimeZone API implementation in SimpleTimeZone
15252e5b6d6dSopenharmony_ci    SimpleTimeZone *stz1 = new SimpleTimeZone(-5*HOUR, "GMT-5");
15262e5b6d6dSopenharmony_ci
15272e5b6d6dSopenharmony_ci    avail1 = stz1->getNextTransition(time1, false, tzt1);
15282e5b6d6dSopenharmony_ci    if (avail1) {
15292e5b6d6dSopenharmony_ci        errln("FAIL: No transition must be returned by getNextTransition for SimpleTimeZone with no DST rule");
15302e5b6d6dSopenharmony_ci    }
15312e5b6d6dSopenharmony_ci    avail1 = stz1->getPreviousTransition(time1, false, tzt1);
15322e5b6d6dSopenharmony_ci    if (avail1) {
15332e5b6d6dSopenharmony_ci        errln("FAIL: No transition must be returned by getPreviousTransition  for SimpleTimeZone with no DST rule");
15342e5b6d6dSopenharmony_ci    }
15352e5b6d6dSopenharmony_ci
15362e5b6d6dSopenharmony_ci    numTzRules = stz1->countTransitionRules(status);
15372e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
15382e5b6d6dSopenharmony_ci        errln("FAIL: countTransitionRules failed");
15392e5b6d6dSopenharmony_ci    }
15402e5b6d6dSopenharmony_ci    if (numTzRules != 0) {
15412e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: countTransitionRules returned " + numTzRules);
15422e5b6d6dSopenharmony_ci    }
15432e5b6d6dSopenharmony_ci    numTzRules = 2;
15442e5b6d6dSopenharmony_ci    stz1->getTimeZoneRules(ir, trrules, numTzRules, status);
15452e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
15462e5b6d6dSopenharmony_ci        errln("FAIL: getTimeZoneRules failed");
15472e5b6d6dSopenharmony_ci    }
15482e5b6d6dSopenharmony_ci    if (numTzRules != 0) {
15492e5b6d6dSopenharmony_ci        errln("FAIL: Incorrect transition rule count");
15502e5b6d6dSopenharmony_ci    }
15512e5b6d6dSopenharmony_ci    if (ir == NULL || ir->getRawOffset() != stz1->getRawOffset()) {
15522e5b6d6dSopenharmony_ci        errln("FAIL: Bad initial time zone rule");
15532e5b6d6dSopenharmony_ci    }
15542e5b6d6dSopenharmony_ci
15552e5b6d6dSopenharmony_ci    // Set DST rule
15562e5b6d6dSopenharmony_ci    stz1->setStartRule(UCAL_MARCH, 11, 2*HOUR, status); // March 11
15572e5b6d6dSopenharmony_ci    stz1->setEndRule(UCAL_NOVEMBER, 1, UCAL_SUNDAY, 2*HOUR, status); // First Sunday in November
15582e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
15592e5b6d6dSopenharmony_ci        errln("FAIL: Failed to set DST rules in a SimpleTimeZone");
15602e5b6d6dSopenharmony_ci    }
15612e5b6d6dSopenharmony_ci
15622e5b6d6dSopenharmony_ci    avail1 = stz1->getNextTransition(time1, false, tzt1);
15632e5b6d6dSopenharmony_ci    if (!avail1) {
15642e5b6d6dSopenharmony_ci        errln("FAIL: Non-null transition must be returned by getNextTransition for SimpleTimeZone with a DST rule");
15652e5b6d6dSopenharmony_ci    }
15662e5b6d6dSopenharmony_ci    avail1 = stz1->getPreviousTransition(time1, false, tzt1);
15672e5b6d6dSopenharmony_ci    if (!avail1) {
15682e5b6d6dSopenharmony_ci        errln("FAIL: Non-null transition must be returned by getPreviousTransition  for SimpleTimeZone with a DST rule");
15692e5b6d6dSopenharmony_ci    }
15702e5b6d6dSopenharmony_ci
15712e5b6d6dSopenharmony_ci    numTzRules = stz1->countTransitionRules(status);
15722e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
15732e5b6d6dSopenharmony_ci        errln("FAIL: countTransitionRules failed");
15742e5b6d6dSopenharmony_ci    }
15752e5b6d6dSopenharmony_ci    if (numTzRules != 2) {
15762e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: countTransitionRules returned " + numTzRules);
15772e5b6d6dSopenharmony_ci    }
15782e5b6d6dSopenharmony_ci
15792e5b6d6dSopenharmony_ci    numTzRules = 2;
15802e5b6d6dSopenharmony_ci    trrules[0] = NULL;
15812e5b6d6dSopenharmony_ci    trrules[1] = NULL;
15822e5b6d6dSopenharmony_ci    stz1->getTimeZoneRules(ir, trrules, numTzRules, status);
15832e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
15842e5b6d6dSopenharmony_ci        errln("FAIL: getTimeZoneRules failed");
15852e5b6d6dSopenharmony_ci    }
15862e5b6d6dSopenharmony_ci    if (numTzRules != 2) {
15872e5b6d6dSopenharmony_ci        errln("FAIL: Incorrect transition rule count");
15882e5b6d6dSopenharmony_ci    }
15892e5b6d6dSopenharmony_ci    if (ir == NULL || ir->getRawOffset() != stz1->getRawOffset()) {
15902e5b6d6dSopenharmony_ci        errln("FAIL: Bad initial time zone rule");
15912e5b6d6dSopenharmony_ci    }
15922e5b6d6dSopenharmony_ci    if (trrules[0] == NULL || trrules[0]->getRawOffset() != stz1->getRawOffset()) {
15932e5b6d6dSopenharmony_ci        errln("FAIL: Bad transition rule 0");
15942e5b6d6dSopenharmony_ci    }
15952e5b6d6dSopenharmony_ci    if (trrules[1] == NULL || trrules[1]->getRawOffset() != stz1->getRawOffset()) {
15962e5b6d6dSopenharmony_ci        errln("FAIL: Bad transition rule 1");
15972e5b6d6dSopenharmony_ci    }
15982e5b6d6dSopenharmony_ci
15992e5b6d6dSopenharmony_ci    // Set DST start year
16002e5b6d6dSopenharmony_ci    stz1->setStartYear(2007);
16012e5b6d6dSopenharmony_ci    avail1 = stz1->getPreviousTransition(time1, false, tzt1);
16022e5b6d6dSopenharmony_ci    if (avail1) {
16032e5b6d6dSopenharmony_ci        errln("FAIL: No transition must be returned before 1990");
16042e5b6d6dSopenharmony_ci    }
16052e5b6d6dSopenharmony_ci    avail1 = stz1->getNextTransition(time1, false, tzt1); // transition after 1990-06-01
16062e5b6d6dSopenharmony_ci    avail2 = stz1->getNextTransition(time2, false, tzt2); // transition after 2000-06-01
16072e5b6d6dSopenharmony_ci    if (!avail1 || !avail2 || tzt1 != tzt2) {
16082e5b6d6dSopenharmony_ci        errln("FAIL: Bad transition returned by SimpleTimeZone::getNextTransition");
16092e5b6d6dSopenharmony_ci    }
16102e5b6d6dSopenharmony_ci    delete stz1;
16112e5b6d6dSopenharmony_ci}
16122e5b6d6dSopenharmony_ci
16132e5b6d6dSopenharmony_ci/*
16142e5b6d6dSopenharmony_ci * API coverage test for VTimeZone
16152e5b6d6dSopenharmony_ci */
16162e5b6d6dSopenharmony_civoid
16172e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestVTimeZoneCoverage(void) {
16182e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
16192e5b6d6dSopenharmony_ci    UnicodeString TZID("Europe/Moscow");
16202e5b6d6dSopenharmony_ci
16212e5b6d6dSopenharmony_ci    BasicTimeZone *otz = (BasicTimeZone*)TimeZone::createTimeZone(TZID);
16222e5b6d6dSopenharmony_ci    VTimeZone *vtz = VTimeZone::createVTimeZoneByID(TZID);
16232e5b6d6dSopenharmony_ci
16242e5b6d6dSopenharmony_ci    // getOffset(era, year, month, day, dayOfWeek, milliseconds, ec)
16252e5b6d6dSopenharmony_ci    int32_t offset1 = otz->getOffset(GregorianCalendar::AD, 2007, UCAL_JULY, 1, UCAL_SUNDAY, 0, status);
16262e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
16272e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(7 args) failed for otz");
16282e5b6d6dSopenharmony_ci    }
16292e5b6d6dSopenharmony_ci    int32_t offset2 = vtz->getOffset(GregorianCalendar::AD, 2007, UCAL_JULY, 1, UCAL_SUNDAY, 0, status);
16302e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
16312e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(7 args) failed for vtz");
16322e5b6d6dSopenharmony_ci    }
16332e5b6d6dSopenharmony_ci    if (offset1 != offset2) {
16342e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(7 args) returned different results in VTimeZone and OlsonTimeZone");
16352e5b6d6dSopenharmony_ci    }
16362e5b6d6dSopenharmony_ci
16372e5b6d6dSopenharmony_ci    // getOffset(era, year, month, day, dayOfWeek, milliseconds, monthLength, ec)
16382e5b6d6dSopenharmony_ci    offset1 = otz->getOffset(GregorianCalendar::AD, 2007, UCAL_JULY, 1, UCAL_SUNDAY, 0, 31, status);
16392e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
16402e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(8 args) failed for otz");
16412e5b6d6dSopenharmony_ci    }
16422e5b6d6dSopenharmony_ci    offset2 = vtz->getOffset(GregorianCalendar::AD, 2007, UCAL_JULY, 1, UCAL_SUNDAY, 0, 31, status);
16432e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
16442e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(8 args) failed for vtz");
16452e5b6d6dSopenharmony_ci    }
16462e5b6d6dSopenharmony_ci    if (offset1 != offset2) {
16472e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(8 args) returned different results in VTimeZone and OlsonTimeZone");
16482e5b6d6dSopenharmony_ci    }
16492e5b6d6dSopenharmony_ci
16502e5b6d6dSopenharmony_ci
16512e5b6d6dSopenharmony_ci    // getOffset(date, local, rawOffset, dstOffset, ec)
16522e5b6d6dSopenharmony_ci    UDate t = Calendar::getNow();
16532e5b6d6dSopenharmony_ci    int32_t rawOffset1, dstSavings1;
16542e5b6d6dSopenharmony_ci    int32_t rawOffset2, dstSavings2;
16552e5b6d6dSopenharmony_ci
16562e5b6d6dSopenharmony_ci    otz->getOffset(t, false, rawOffset1, dstSavings1, status);
16572e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
16582e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(5 args) failed for otz");
16592e5b6d6dSopenharmony_ci    }
16602e5b6d6dSopenharmony_ci    vtz->getOffset(t, false, rawOffset2, dstSavings2, status);
16612e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
16622e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(5 args) failed for vtz");
16632e5b6d6dSopenharmony_ci    }
16642e5b6d6dSopenharmony_ci    if (rawOffset1 != rawOffset2 || dstSavings1 != dstSavings2) {
16652e5b6d6dSopenharmony_ci        errln("FAIL: getOffset(long,boolean,int[]) returned different results in VTimeZone and OlsonTimeZone");
16662e5b6d6dSopenharmony_ci    }
16672e5b6d6dSopenharmony_ci
16682e5b6d6dSopenharmony_ci    // getRawOffset
16692e5b6d6dSopenharmony_ci    if (otz->getRawOffset() != vtz->getRawOffset()) {
16702e5b6d6dSopenharmony_ci        errln("FAIL: getRawOffset returned different results in VTimeZone and OlsonTimeZone");
16712e5b6d6dSopenharmony_ci    }
16722e5b6d6dSopenharmony_ci
16732e5b6d6dSopenharmony_ci    // inDaylightTime
16742e5b6d6dSopenharmony_ci    UBool inDst1, inDst2;
16752e5b6d6dSopenharmony_ci    inDst1 = otz->inDaylightTime(t, status);
16762e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
16772e5b6d6dSopenharmony_ci        dataerrln("FAIL: inDaylightTime failed for otz: %s", u_errorName(status));
16782e5b6d6dSopenharmony_ci    }
16792e5b6d6dSopenharmony_ci    inDst2 = vtz->inDaylightTime(t, status);
16802e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
16812e5b6d6dSopenharmony_ci        dataerrln("FAIL: inDaylightTime failed for vtz: %s", u_errorName(status));
16822e5b6d6dSopenharmony_ci    }
16832e5b6d6dSopenharmony_ci    if (inDst1 != inDst2) {
16842e5b6d6dSopenharmony_ci        errln("FAIL: inDaylightTime returned different results in VTimeZone and OlsonTimeZone");
16852e5b6d6dSopenharmony_ci    }
16862e5b6d6dSopenharmony_ci
16872e5b6d6dSopenharmony_ci    // useDaylightTime
16882e5b6d6dSopenharmony_ci    if (otz->useDaylightTime() != vtz->useDaylightTime()) {
16892e5b6d6dSopenharmony_ci        errln("FAIL: useDaylightTime returned different results in VTimeZone and OlsonTimeZone");
16902e5b6d6dSopenharmony_ci    }
16912e5b6d6dSopenharmony_ci
16922e5b6d6dSopenharmony_ci    // setRawOffset
16932e5b6d6dSopenharmony_ci    const int32_t RAW = -10*HOUR;
16942e5b6d6dSopenharmony_ci    VTimeZone *tmpvtz = vtz->clone();
16952e5b6d6dSopenharmony_ci    tmpvtz->setRawOffset(RAW);
16962e5b6d6dSopenharmony_ci    if (tmpvtz->getRawOffset() != RAW) {
16972e5b6d6dSopenharmony_ci        logln("setRawOffset is implemented in VTimeZone");
16982e5b6d6dSopenharmony_ci    }
16992e5b6d6dSopenharmony_ci
17002e5b6d6dSopenharmony_ci    // hasSameRules
17012e5b6d6dSopenharmony_ci    UBool bSame = otz->hasSameRules(*vtz);
17022e5b6d6dSopenharmony_ci    logln((UnicodeString)"OlsonTimeZone::hasSameRules(VTimeZone) should return false always for now - actual: " + bSame);
17032e5b6d6dSopenharmony_ci
17042e5b6d6dSopenharmony_ci    // getTZURL/setTZURL
17052e5b6d6dSopenharmony_ci    UnicodeString TZURL("http://icu-project.org/timezone");
17062e5b6d6dSopenharmony_ci    UnicodeString url;
17072e5b6d6dSopenharmony_ci    if (vtz->getTZURL(url)) {
17082e5b6d6dSopenharmony_ci        errln("FAIL: getTZURL returned true");
17092e5b6d6dSopenharmony_ci    }
17102e5b6d6dSopenharmony_ci    vtz->setTZURL(TZURL);
17112e5b6d6dSopenharmony_ci    if (!vtz->getTZURL(url) || url != TZURL) {
17122e5b6d6dSopenharmony_ci        errln("FAIL: URL returned by getTZURL does not match the one set by setTZURL");
17132e5b6d6dSopenharmony_ci    }
17142e5b6d6dSopenharmony_ci
17152e5b6d6dSopenharmony_ci    // getLastModified/setLastModified
17162e5b6d6dSopenharmony_ci    UDate lastmod;
17172e5b6d6dSopenharmony_ci    if (vtz->getLastModified(lastmod)) {
17182e5b6d6dSopenharmony_ci        errln("FAIL: getLastModified returned true");
17192e5b6d6dSopenharmony_ci    }
17202e5b6d6dSopenharmony_ci    vtz->setLastModified(t);
17212e5b6d6dSopenharmony_ci    if (!vtz->getLastModified(lastmod) || lastmod != t) {
17222e5b6d6dSopenharmony_ci        errln("FAIL: Date returned by getLastModified does not match the one set by setLastModified");
17232e5b6d6dSopenharmony_ci    }
17242e5b6d6dSopenharmony_ci
17252e5b6d6dSopenharmony_ci    // getNextTransition/getPreviousTransition
17262e5b6d6dSopenharmony_ci    UDate base = getUTCMillis(2007, UCAL_JULY, 1);
17272e5b6d6dSopenharmony_ci    TimeZoneTransition tzt1, tzt2;
17282e5b6d6dSopenharmony_ci    UBool btr1 = otz->getNextTransition(base, true, tzt1);
17292e5b6d6dSopenharmony_ci    UBool btr2 = vtz->getNextTransition(base, true, tzt2);
17302e5b6d6dSopenharmony_ci    if (!btr1 || !btr2 || tzt1 != tzt2) {
17312e5b6d6dSopenharmony_ci        dataerrln("FAIL: getNextTransition returned different results in VTimeZone and OlsonTimeZone");
17322e5b6d6dSopenharmony_ci    }
17332e5b6d6dSopenharmony_ci    btr1 = otz->getPreviousTransition(base, false, tzt1);
17342e5b6d6dSopenharmony_ci    btr2 = vtz->getPreviousTransition(base, false, tzt2);
17352e5b6d6dSopenharmony_ci    if (!btr1 || !btr2 || tzt1 != tzt2) {
17362e5b6d6dSopenharmony_ci        dataerrln("FAIL: getPreviousTransition returned different results in VTimeZone and OlsonTimeZone");
17372e5b6d6dSopenharmony_ci    }
17382e5b6d6dSopenharmony_ci
17392e5b6d6dSopenharmony_ci    // TimeZoneTransition constructor/clone
17402e5b6d6dSopenharmony_ci    TimeZoneTransition *tzt1c = tzt1.clone();
17412e5b6d6dSopenharmony_ci    if (*tzt1c != tzt1 || !(*tzt1c == tzt1)) {
17422e5b6d6dSopenharmony_ci        errln("FAIL: TimeZoneTransition tzt1c is equal to tzt1, but got wrong result");
17432e5b6d6dSopenharmony_ci    }
17442e5b6d6dSopenharmony_ci    delete tzt1c;
17452e5b6d6dSopenharmony_ci    TimeZoneTransition tzt3(tzt1);
17462e5b6d6dSopenharmony_ci    if (tzt3 != tzt1 || !(tzt3 == tzt1)) {
17472e5b6d6dSopenharmony_ci        errln("FAIL: TimeZoneTransition tzt3 is equal to tzt1, but got wrong result");
17482e5b6d6dSopenharmony_ci    }
17492e5b6d6dSopenharmony_ci
17502e5b6d6dSopenharmony_ci    // hasEquivalentTransitions
17512e5b6d6dSopenharmony_ci    UDate time1 = getUTCMillis(1950, UCAL_JANUARY, 1);
17522e5b6d6dSopenharmony_ci    UDate time2 = getUTCMillis(2020, UCAL_JANUARY, 1);
17532e5b6d6dSopenharmony_ci    UBool equiv = vtz->hasEquivalentTransitions(*otz, time1, time2, false, status);
17542e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
17552e5b6d6dSopenharmony_ci        dataerrln("FAIL: hasEquivalentTransitions failed for vtz/otz: %s", u_errorName(status));
17562e5b6d6dSopenharmony_ci    }
17572e5b6d6dSopenharmony_ci    if (!equiv) {
17582e5b6d6dSopenharmony_ci        dataerrln("FAIL: hasEquivalentTransitions returned false for the same time zone");
17592e5b6d6dSopenharmony_ci    }
17602e5b6d6dSopenharmony_ci
17612e5b6d6dSopenharmony_ci    // operator=/operator==/operator!=
17622e5b6d6dSopenharmony_ci    VTimeZone *vtz1 = VTimeZone::createVTimeZoneByID("America/Los_Angeles");
17632e5b6d6dSopenharmony_ci    if (*vtz1 == *vtz || !(*vtz1 != *vtz)) {
17642e5b6d6dSopenharmony_ci        errln("FAIL: VTimeZone vtz1 is not equal to vtz, but got wrong result");
17652e5b6d6dSopenharmony_ci    }
17662e5b6d6dSopenharmony_ci    *vtz1 = *vtz;
17672e5b6d6dSopenharmony_ci    if (*vtz1 != *vtz || !(*vtz1 == *vtz)) {
17682e5b6d6dSopenharmony_ci        errln("FAIL: VTimeZone vtz1 is equal to vtz, but got wrong result");
17692e5b6d6dSopenharmony_ci    }
17702e5b6d6dSopenharmony_ci
17712e5b6d6dSopenharmony_ci    // Creation from BasicTimeZone
17722e5b6d6dSopenharmony_ci    //
17732e5b6d6dSopenharmony_ci    status = U_ZERO_ERROR;
17742e5b6d6dSopenharmony_ci    VTimeZone *vtzFromBasic = NULL;
17752e5b6d6dSopenharmony_ci    SimpleTimeZone *simpleTZ = new SimpleTimeZone(28800000, "Asia/Singapore");
17762e5b6d6dSopenharmony_ci    simpleTZ->setStartYear(1970);
17772e5b6d6dSopenharmony_ci    simpleTZ->setStartRule(0,  // month
17782e5b6d6dSopenharmony_ci                          1,  // day of week
17792e5b6d6dSopenharmony_ci                          0,  // time
17802e5b6d6dSopenharmony_ci                          status);
17812e5b6d6dSopenharmony_ci    simpleTZ->setEndRule(1, 1, 0, status);
17822e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
17832e5b6d6dSopenharmony_ci        errln("File %s, line %d, failed with status = %s", __FILE__, __LINE__, u_errorName(status));
17842e5b6d6dSopenharmony_ci        goto end_basic_tz_test;
17852e5b6d6dSopenharmony_ci    }
17862e5b6d6dSopenharmony_ci    vtzFromBasic = VTimeZone::createVTimeZoneFromBasicTimeZone(*simpleTZ, status);
17872e5b6d6dSopenharmony_ci    if (U_FAILURE(status) || vtzFromBasic == NULL) {
17882e5b6d6dSopenharmony_ci        dataerrln("File %s, line %d, failed with status = %s", __FILE__, __LINE__, u_errorName(status));
17892e5b6d6dSopenharmony_ci        goto end_basic_tz_test;
17902e5b6d6dSopenharmony_ci    }
17912e5b6d6dSopenharmony_ci
17922e5b6d6dSopenharmony_ci    // delete the source time zone, to make sure there are no dependencies on it.
17932e5b6d6dSopenharmony_ci    delete simpleTZ;
17942e5b6d6dSopenharmony_ci
17952e5b6d6dSopenharmony_ci    // Create another simple time zone w the same rules, and check that it is the
17962e5b6d6dSopenharmony_ci    // same as the test VTimeZone created above.
17972e5b6d6dSopenharmony_ci    {
17982e5b6d6dSopenharmony_ci        SimpleTimeZone simpleTZ2(28800000, "Asia/Singapore");
17992e5b6d6dSopenharmony_ci        simpleTZ2.setStartYear(1970);
18002e5b6d6dSopenharmony_ci        simpleTZ2.setStartRule(0,  // month
18012e5b6d6dSopenharmony_ci                              1,  // day of week
18022e5b6d6dSopenharmony_ci                              0,  // time
18032e5b6d6dSopenharmony_ci                              status);
18042e5b6d6dSopenharmony_ci        simpleTZ2.setEndRule(1, 1, 0, status);
18052e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
18062e5b6d6dSopenharmony_ci            errln("File %s, line %d, failed with status = %s", __FILE__, __LINE__, u_errorName(status));
18072e5b6d6dSopenharmony_ci            goto end_basic_tz_test;
18082e5b6d6dSopenharmony_ci        }
18092e5b6d6dSopenharmony_ci        if (vtzFromBasic->hasSameRules(simpleTZ2) == false) {
18102e5b6d6dSopenharmony_ci            errln("File %s, line %d, failed hasSameRules() ", __FILE__, __LINE__);
18112e5b6d6dSopenharmony_ci            goto end_basic_tz_test;
18122e5b6d6dSopenharmony_ci        }
18132e5b6d6dSopenharmony_ci    }
18142e5b6d6dSopenharmony_ciend_basic_tz_test:
18152e5b6d6dSopenharmony_ci    delete vtzFromBasic;
18162e5b6d6dSopenharmony_ci
18172e5b6d6dSopenharmony_ci    delete otz;
18182e5b6d6dSopenharmony_ci    delete vtz;
18192e5b6d6dSopenharmony_ci    delete tmpvtz;
18202e5b6d6dSopenharmony_ci    delete vtz1;
18212e5b6d6dSopenharmony_ci}
18222e5b6d6dSopenharmony_ci
18232e5b6d6dSopenharmony_ci
18242e5b6d6dSopenharmony_civoid
18252e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestVTimeZoneParse(void) {
18262e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
18272e5b6d6dSopenharmony_ci
18282e5b6d6dSopenharmony_ci    // Trying to create VTimeZone from empty data
18292e5b6d6dSopenharmony_ci    UnicodeString emptyData;
18302e5b6d6dSopenharmony_ci    VTimeZone *empty = VTimeZone::createVTimeZone(emptyData, status);
18312e5b6d6dSopenharmony_ci    if (U_SUCCESS(status) || empty != NULL) {
18322e5b6d6dSopenharmony_ci        delete empty;
18332e5b6d6dSopenharmony_ci        errln("FAIL: Non-null VTimeZone is returned for empty VTIMEZONE data");
18342e5b6d6dSopenharmony_ci    }
18352e5b6d6dSopenharmony_ci    status = U_ZERO_ERROR;
18362e5b6d6dSopenharmony_ci
18372e5b6d6dSopenharmony_ci    // Create VTimeZone for Asia/Tokyo
18382e5b6d6dSopenharmony_ci    UnicodeString asiaTokyoID("Asia/Tokyo");
18392e5b6d6dSopenharmony_ci    static const UChar asiaTokyo[] = {
18402e5b6d6dSopenharmony_ci        /* "BEGIN:VTIMEZONE\x0D\x0A" */
18412e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4E,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,0x0D,0x0A,
18422e5b6d6dSopenharmony_ci        /* "TZID:Asia\x0D\x0A" */
18432e5b6d6dSopenharmony_ci        0x54,0x5A,0x49,0x44,0x3A,0x41,0x73,0x69,0x61,0x0D,0x0A,
18442e5b6d6dSopenharmony_ci        /* "\x09/Tokyo\x0D\x0A" */
18452e5b6d6dSopenharmony_ci        0x09,0x2F,0x54,0x6F,0x6B,0x79,0x6F,0x0D,0x0A,
18462e5b6d6dSopenharmony_ci        /* "BEGIN:STANDARD\x0D\x0A" */
18472e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4E,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A,
18482e5b6d6dSopenharmony_ci        /* "TZOFFSETFROM:+0900\x0D\x0A" */
18492e5b6d6dSopenharmony_ci        0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4F,0x4D,0x3A,0x2B,0x30,0x39,0x30,0x30,0x0D,0x0A,
18502e5b6d6dSopenharmony_ci        /* "TZOFFSETTO:+0900\x0D\x0A" */
18512e5b6d6dSopenharmony_ci        0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x54,0x4F,0x3A,0x2B,0x30,0x39,0x30,0x30,0x0D,0x0A,
18522e5b6d6dSopenharmony_ci        /* "TZNAME:JST\x0D\x0A" */
18532e5b6d6dSopenharmony_ci        0x54,0x5A,0x4E,0x41,0x4D,0x45,0x3A,0x4A,0x53,0x54,0x0D,0x0A,
18542e5b6d6dSopenharmony_ci        /* "DTSTART:19700101\x0D\x0A" */
18552e5b6d6dSopenharmony_ci        0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3A,0x31,0x39,0x37,0x30,0x30,0x31,0x30,0x31,0x0D,0x0A,
18562e5b6d6dSopenharmony_ci        /* " T000000\x0D\x0A" */
18572e5b6d6dSopenharmony_ci        0x20,0x54,0x30,0x30,0x30,0x30,0x30,0x30,0x0D,0x0A,
18582e5b6d6dSopenharmony_ci        /* "END:STANDARD\x0D\x0A" */
18592e5b6d6dSopenharmony_ci        0x45,0x4E,0x44,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A,
18602e5b6d6dSopenharmony_ci        /* "END:VTIMEZONE" */
18612e5b6d6dSopenharmony_ci        0x45,0x4E,0x44,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,
18622e5b6d6dSopenharmony_ci        0
18632e5b6d6dSopenharmony_ci    };
18642e5b6d6dSopenharmony_ci    VTimeZone *tokyo = VTimeZone::createVTimeZone(asiaTokyo, status);
18652e5b6d6dSopenharmony_ci    if (U_FAILURE(status) || tokyo == NULL) {
18662e5b6d6dSopenharmony_ci        errln("FAIL: Failed to create a VTimeZone tokyo");
18672e5b6d6dSopenharmony_ci    } else {
18682e5b6d6dSopenharmony_ci        // Check ID
18692e5b6d6dSopenharmony_ci        UnicodeString tzid;
18702e5b6d6dSopenharmony_ci        tokyo->getID(tzid);
18712e5b6d6dSopenharmony_ci        if (tzid != asiaTokyoID) {
18722e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: Invalid TZID: " + tzid);
18732e5b6d6dSopenharmony_ci        }
18742e5b6d6dSopenharmony_ci        // Make sure offsets are correct
18752e5b6d6dSopenharmony_ci        int32_t rawOffset, dstSavings;
18762e5b6d6dSopenharmony_ci        tokyo->getOffset(Calendar::getNow(), false, rawOffset, dstSavings, status);
18772e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
18782e5b6d6dSopenharmony_ci            errln("FAIL: getOffset failed for tokyo");
18792e5b6d6dSopenharmony_ci        }
18802e5b6d6dSopenharmony_ci        if (rawOffset != 9*HOUR || dstSavings != 0) {
18812e5b6d6dSopenharmony_ci            errln("FAIL: Bad offsets returned by a VTimeZone created for Tokyo");
18822e5b6d6dSopenharmony_ci        }
18832e5b6d6dSopenharmony_ci    }
18842e5b6d6dSopenharmony_ci    delete tokyo;
18852e5b6d6dSopenharmony_ci
18862e5b6d6dSopenharmony_ci        // Create VTimeZone from VTIMEZONE data
18872e5b6d6dSopenharmony_ci    static const UChar fooData[] = {
18882e5b6d6dSopenharmony_ci        /* "BEGIN:VCALENDAR\x0D\x0A" */
18892e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4E,0x3A,0x56,0x43,0x41,0x4C,0x45,0x4E,0x44,0x41,0x52,0x0D,0x0A,
18902e5b6d6dSopenharmony_ci        /* "BEGIN:VTIMEZONE\x0D\x0A" */
18912e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4E,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,0x0D,0x0A,
18922e5b6d6dSopenharmony_ci        /* "TZID:FOO\x0D\x0A" */
18932e5b6d6dSopenharmony_ci        0x54,0x5A,0x49,0x44,0x3A,0x46,0x4F,0x4F,0x0D,0x0A,
18942e5b6d6dSopenharmony_ci        /* "BEGIN:STANDARD\x0D\x0A" */
18952e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4E,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A,
18962e5b6d6dSopenharmony_ci        /* "TZOFFSETFROM:-0700\x0D\x0A" */
18972e5b6d6dSopenharmony_ci        0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4F,0x4D,0x3A,0x2D,0x30,0x37,0x30,0x30,0x0D,0x0A,
18982e5b6d6dSopenharmony_ci        /* "TZOFFSETTO:-0800\x0D\x0A" */
18992e5b6d6dSopenharmony_ci        0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x54,0x4F,0x3A,0x2D,0x30,0x38,0x30,0x30,0x0D,0x0A,
19002e5b6d6dSopenharmony_ci        /* "TZNAME:FST\x0D\x0A" */
19012e5b6d6dSopenharmony_ci        0x54,0x5A,0x4E,0x41,0x4D,0x45,0x3A,0x46,0x53,0x54,0x0D,0x0A,
19022e5b6d6dSopenharmony_ci        /* "DTSTART:20071010T010000\x0D\x0A" */
19032e5b6d6dSopenharmony_ci        0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3A,0x32,0x30,0x30,0x37,0x31,0x30,0x31,0x30,0x54,0x30,0x31,0x30,0x30,0x30,0x30,0x0D,0x0A,
19042e5b6d6dSopenharmony_ci        /* "RRULE:FREQ=YEARLY;BYDAY=WE;BYMONTHDAY=10,11,12,13,14,15,16;BYMONTH=10\x0D\x0A" */
19052e5b6d6dSopenharmony_ci        0x52,0x52,0x55,0x4C,0x45,0x3A,0x46,0x52,0x45,0x51,0x3D,0x59,0x45,0x41,0x52,0x4C,0x59,0x3B,0x42,0x59,0x44,0x41,0x59,0x3D,0x57,0x45,0x3B,0x42,0x59,0x4D,0x4F,0x4E,0x54,0x48,0x44,0x41,0x59,0x3D,0x31,0x30,0x2C,0x31,0x31,0x2C,0x31,0x32,0x2C,0x31,0x33,0x2C,0x31,0x34,0x2C,0x31,0x35,0x2C,0x31,0x36,0x3B,0x42,0x59,0x4D,0x4F,0x4E,0x54,0x48,0x3D,0x31,0x30,0x0D,0x0A,
19062e5b6d6dSopenharmony_ci        /* "END:STANDARD\x0D\x0A" */
19072e5b6d6dSopenharmony_ci        0x45,0x4E,0x44,0x3A,0x53,0x54,0x41,0x4E,0x44,0x41,0x52,0x44,0x0D,0x0A,
19082e5b6d6dSopenharmony_ci        /* "BEGIN:DAYLIGHT\x0D\x0A" */
19092e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4E,0x3A,0x44,0x41,0x59,0x4C,0x49,0x47,0x48,0x54,0x0D,0x0A,
19102e5b6d6dSopenharmony_ci        /* "TZOFFSETFROM:-0800\x0D\x0A" */
19112e5b6d6dSopenharmony_ci        0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4F,0x4D,0x3A,0x2D,0x30,0x38,0x30,0x30,0x0D,0x0A,
19122e5b6d6dSopenharmony_ci        /* "TZOFFSETTO:-0700\x0D\x0A" */
19132e5b6d6dSopenharmony_ci        0x54,0x5A,0x4F,0x46,0x46,0x53,0x45,0x54,0x54,0x4F,0x3A,0x2D,0x30,0x37,0x30,0x30,0x0D,0x0A,
19142e5b6d6dSopenharmony_ci        /* "TZNAME:FDT\x0D\x0A" */
19152e5b6d6dSopenharmony_ci        0x54,0x5A,0x4E,0x41,0x4D,0x45,0x3A,0x46,0x44,0x54,0x0D,0x0A,
19162e5b6d6dSopenharmony_ci        /* "DTSTART:20070415T010000\x0D\x0A" */
19172e5b6d6dSopenharmony_ci        0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3A,0x32,0x30,0x30,0x37,0x30,0x34,0x31,0x35,0x54,0x30,0x31,0x30,0x30,0x30,0x30,0x0D,0x0A,
19182e5b6d6dSopenharmony_ci        /* "RRULE:FREQ=YEARLY;BYMONTHDAY=15;BYMONTH=4\x0D\x0A" */
19192e5b6d6dSopenharmony_ci        0x52,0x52,0x55,0x4C,0x45,0x3A,0x46,0x52,0x45,0x51,0x3D,0x59,0x45,0x41,0x52,0x4C,0x59,0x3B,0x42,0x59,0x4D,0x4F,0x4E,0x54,0x48,0x44,0x41,0x59,0x3D,0x31,0x35,0x3B,0x42,0x59,0x4D,0x4F,0x4E,0x54,0x48,0x3D,0x34,0x0D,0x0A,
19202e5b6d6dSopenharmony_ci        /* "END:DAYLIGHT\x0D\x0A" */
19212e5b6d6dSopenharmony_ci        0x45,0x4E,0x44,0x3A,0x44,0x41,0x59,0x4C,0x49,0x47,0x48,0x54,0x0D,0x0A,
19222e5b6d6dSopenharmony_ci        /* "END:VTIMEZONE\x0D\x0A" */
19232e5b6d6dSopenharmony_ci        0x45,0x4E,0x44,0x3A,0x56,0x54,0x49,0x4D,0x45,0x5A,0x4F,0x4E,0x45,0x0D,0x0A,
19242e5b6d6dSopenharmony_ci        /* "END:VCALENDAR" */
19252e5b6d6dSopenharmony_ci        0x45,0x4E,0x44,0x3A,0x56,0x43,0x41,0x4C,0x45,0x4E,0x44,0x41,0x52,
19262e5b6d6dSopenharmony_ci        0
19272e5b6d6dSopenharmony_ci    };
19282e5b6d6dSopenharmony_ci
19292e5b6d6dSopenharmony_ci    VTimeZone *foo = VTimeZone::createVTimeZone(fooData, status);
19302e5b6d6dSopenharmony_ci    if (U_FAILURE(status) || foo == NULL) {
19312e5b6d6dSopenharmony_ci        errln("FAIL: Failed to create a VTimeZone foo");
19322e5b6d6dSopenharmony_ci    } else {
19332e5b6d6dSopenharmony_ci        // Write VTIMEZONE data
19342e5b6d6dSopenharmony_ci        UnicodeString fooData2;
19352e5b6d6dSopenharmony_ci        foo->write(getUTCMillis(2005, UCAL_JANUARY, 1), fooData2, status);
19362e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
19372e5b6d6dSopenharmony_ci            errln("FAIL: Failed to write VTIMEZONE data for foo");
19382e5b6d6dSopenharmony_ci        }
19392e5b6d6dSopenharmony_ci        logln(fooData2);
19402e5b6d6dSopenharmony_ci    }
19412e5b6d6dSopenharmony_ci    delete foo;
19422e5b6d6dSopenharmony_ci}
19432e5b6d6dSopenharmony_ci
19442e5b6d6dSopenharmony_civoid
19452e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestT6216(void) {
19462e5b6d6dSopenharmony_ci    // Test case in #6216
19472e5b6d6dSopenharmony_ci    static const UChar tokyoTZ[] = {
19482e5b6d6dSopenharmony_ci        /* "BEGIN:VCALENDAR\r\n" */
19492e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
19502e5b6d6dSopenharmony_ci        /* "VERSION:2.0\r\n" */
19512e5b6d6dSopenharmony_ci        0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x3a,0x32,0x2e,0x30,0x0d,0x0a,
19522e5b6d6dSopenharmony_ci        /* "PRODID:-//PYVOBJECT//NONSGML Version 1//EN\r\n" */
19532e5b6d6dSopenharmony_ci        0x50,0x52,0x4f,0x44,0x49,0x44,0x3a,0x2d,0x2f,0x2f,0x50,0x59,0x56,0x4f,0x42,0x4a,0x45,0x43,0x54,0x2f,0x2f,0x4e,0x4f,0x4e,0x53,0x47,0x4d,0x4c,0x20,0x56,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x31,0x2f,0x2f,0x45,0x4e,0x0d,0x0a,
19542e5b6d6dSopenharmony_ci        /* "BEGIN:VTIMEZONE\r\n" */
19552e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
19562e5b6d6dSopenharmony_ci        /* "TZID:Asia/Tokyo\r\n" */
19572e5b6d6dSopenharmony_ci        0x54,0x5a,0x49,0x44,0x3a,0x41,0x73,0x69,0x61,0x2f,0x54,0x6f,0x6b,0x79,0x6f,0x0d,0x0a,
19582e5b6d6dSopenharmony_ci        /* "BEGIN:STANDARD\r\n" */
19592e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
19602e5b6d6dSopenharmony_ci        /* "DTSTART:20000101T000000\r\n" */
19612e5b6d6dSopenharmony_ci        0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x30,0x30,0x31,0x30,0x31,0x54,0x30,0x30,0x30,0x30,0x30,0x30,0x0d,0x0a,
19622e5b6d6dSopenharmony_ci        /* "RRULE:FREQ=YEARLY;BYMONTH=1\r\n" */
19632e5b6d6dSopenharmony_ci        0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x0d,0x0a,
19642e5b6d6dSopenharmony_ci        /* "TZNAME:Asia/Tokyo\r\n" */
19652e5b6d6dSopenharmony_ci        0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x41,0x73,0x69,0x61,0x2f,0x54,0x6f,0x6b,0x79,0x6f,0x0d,0x0a,
19662e5b6d6dSopenharmony_ci        /* "TZOFFSETFROM:+0900\r\n" */
19672e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2b,0x30,0x39,0x30,0x30,0x0d,0x0a,
19682e5b6d6dSopenharmony_ci        /* "TZOFFSETTO:+0900\r\n" */
19692e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2b,0x30,0x39,0x30,0x30,0x0d,0x0a,
19702e5b6d6dSopenharmony_ci        /* "END:STANDARD\r\n" */
19712e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
19722e5b6d6dSopenharmony_ci        /* "END:VTIMEZONE\r\n" */
19732e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
19742e5b6d6dSopenharmony_ci        /* "END:VCALENDAR" */
19752e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
19762e5b6d6dSopenharmony_ci        0
19772e5b6d6dSopenharmony_ci    };
19782e5b6d6dSopenharmony_ci    // Single final rule, overlapping with another
19792e5b6d6dSopenharmony_ci    static const UChar finalOverlap[] = {
19802e5b6d6dSopenharmony_ci        /* "BEGIN:VCALENDAR\r\n" */
19812e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
19822e5b6d6dSopenharmony_ci        /* "BEGIN:VTIMEZONE\r\n" */
19832e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
19842e5b6d6dSopenharmony_ci        /* "TZID:FinalOverlap\r\n" */
19852e5b6d6dSopenharmony_ci        0x54,0x5a,0x49,0x44,0x3a,0x46,0x69,0x6e,0x61,0x6c,0x4f,0x76,0x65,0x72,0x6c,0x61,0x70,0x0d,0x0a,
19862e5b6d6dSopenharmony_ci        /* "BEGIN:STANDARD\r\n" */
19872e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
19882e5b6d6dSopenharmony_ci        /* "TZOFFSETFROM:-0200\r\n" */
19892e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
19902e5b6d6dSopenharmony_ci        /* "TZOFFSETTO:-0300\r\n" */
19912e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
19922e5b6d6dSopenharmony_ci        /* "TZNAME:STD\r\n" */
19932e5b6d6dSopenharmony_ci        0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x0d,0x0a,
19942e5b6d6dSopenharmony_ci        /* "DTSTART:20001029T020000\r\n" */
19952e5b6d6dSopenharmony_ci        0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x30,0x31,0x30,0x32,0x39,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a,
19962e5b6d6dSopenharmony_ci        /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\r\n" */
19972e5b6d6dSopenharmony_ci        0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x2d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x30,0x0d,0x0a,
19982e5b6d6dSopenharmony_ci        /* "END:STANDARD\r\n" */
19992e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
20002e5b6d6dSopenharmony_ci        /* "BEGIN:DAYLIGHT\r\n" */
20012e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
20022e5b6d6dSopenharmony_ci        /* "TZOFFSETFROM:-0300\r\n" */
20032e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
20042e5b6d6dSopenharmony_ci        /* "TZOFFSETTO:-0200\r\n" */
20052e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
20062e5b6d6dSopenharmony_ci        /* "TZNAME:DST\r\n" */
20072e5b6d6dSopenharmony_ci        0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x44,0x53,0x54,0x0d,0x0a,
20082e5b6d6dSopenharmony_ci        /* "DTSTART:19990404T020000\r\n" */
20092e5b6d6dSopenharmony_ci        0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x31,0x39,0x39,0x39,0x30,0x34,0x30,0x34,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a,
20102e5b6d6dSopenharmony_ci        /* "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=20050403T040000Z\r\n" */
20112e5b6d6dSopenharmony_ci        0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x34,0x3b,0x55,0x4e,0x54,0x49,0x4c,0x3d,0x32,0x30,0x30,0x35,0x30,0x34,0x30,0x33,0x54,0x30,0x34,0x30,0x30,0x30,0x30,0x5a,0x0d,0x0a,
20122e5b6d6dSopenharmony_ci        /* "END:DAYLIGHT\r\n" */
20132e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
20142e5b6d6dSopenharmony_ci        /* "END:VTIMEZONE\r\n" */
20152e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
20162e5b6d6dSopenharmony_ci        /* "END:VCALENDAR" */
20172e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
20182e5b6d6dSopenharmony_ci        0
20192e5b6d6dSopenharmony_ci    };
20202e5b6d6dSopenharmony_ci    // Single final rule, no overlapping with another
20212e5b6d6dSopenharmony_ci    static const UChar finalNonOverlap[] = {
20222e5b6d6dSopenharmony_ci        /* "BEGIN:VCALENDAR\r\n" */
20232e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
20242e5b6d6dSopenharmony_ci        /* "BEGIN:VTIMEZONE\r\n" */
20252e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
20262e5b6d6dSopenharmony_ci        /* "TZID:FinalNonOverlap\r\n" */
20272e5b6d6dSopenharmony_ci        0x54,0x5a,0x49,0x44,0x3a,0x46,0x69,0x6e,0x61,0x6c,0x4e,0x6f,0x6e,0x4f,0x76,0x65,0x72,0x6c,0x61,0x70,0x0d,0x0a,
20282e5b6d6dSopenharmony_ci        /* "BEGIN:STANDARD\r\n" */
20292e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
20302e5b6d6dSopenharmony_ci        /* "TZOFFSETFROM:-0200\r\n" */
20312e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
20322e5b6d6dSopenharmony_ci        /* "TZOFFSETTO:-0300\r\n" */
20332e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
20342e5b6d6dSopenharmony_ci        /* "TZNAME:STD\r\n" */
20352e5b6d6dSopenharmony_ci        0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x0d,0x0a,
20362e5b6d6dSopenharmony_ci        /* "DTSTART:20001029T020000\r\n" */
20372e5b6d6dSopenharmony_ci        0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x30,0x31,0x30,0x32,0x39,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a,
20382e5b6d6dSopenharmony_ci        /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10;UNTIL=20041031T040000Z\r\n" */
20392e5b6d6dSopenharmony_ci        0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x2d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x30,0x3b,0x55,0x4e,0x54,0x49,0x4c,0x3d,0x32,0x30,0x30,0x34,0x31,0x30,0x33,0x31,0x54,0x30,0x34,0x30,0x30,0x30,0x30,0x5a,0x0d,0x0a,
20402e5b6d6dSopenharmony_ci        /* "END:STANDARD\r\n" */
20412e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
20422e5b6d6dSopenharmony_ci        /* "BEGIN:DAYLIGHT\r\n" */
20432e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
20442e5b6d6dSopenharmony_ci        /* "TZOFFSETFROM:-0300\r\n" */
20452e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
20462e5b6d6dSopenharmony_ci        /* "TZOFFSETTO:-0200\r\n" */
20472e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
20482e5b6d6dSopenharmony_ci        /* "TZNAME:DST\r\n" */
20492e5b6d6dSopenharmony_ci        0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x44,0x53,0x54,0x0d,0x0a,
20502e5b6d6dSopenharmony_ci        /* "DTSTART:19990404T020000\r\n" */
20512e5b6d6dSopenharmony_ci        0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x31,0x39,0x39,0x39,0x30,0x34,0x30,0x34,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a,
20522e5b6d6dSopenharmony_ci        /* "RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;UNTIL=20050403T040000Z\r\n" */
20532e5b6d6dSopenharmony_ci        0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x34,0x3b,0x55,0x4e,0x54,0x49,0x4c,0x3d,0x32,0x30,0x30,0x35,0x30,0x34,0x30,0x33,0x54,0x30,0x34,0x30,0x30,0x30,0x30,0x5a,0x0d,0x0a,
20542e5b6d6dSopenharmony_ci        /* "END:DAYLIGHT\r\n" */
20552e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x44,0x41,0x59,0x4c,0x49,0x47,0x48,0x54,0x0d,0x0a,
20562e5b6d6dSopenharmony_ci        /* "BEGIN:STANDARD\r\n" */
20572e5b6d6dSopenharmony_ci        0x42,0x45,0x47,0x49,0x4e,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
20582e5b6d6dSopenharmony_ci        /* "TZOFFSETFROM:-0200\r\n" */
20592e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x46,0x52,0x4f,0x4d,0x3a,0x2d,0x30,0x32,0x30,0x30,0x0d,0x0a,
20602e5b6d6dSopenharmony_ci        /* "TZOFFSETTO:-0300\r\n" */
20612e5b6d6dSopenharmony_ci        0x54,0x5a,0x4f,0x46,0x46,0x53,0x45,0x54,0x54,0x4f,0x3a,0x2d,0x30,0x33,0x30,0x30,0x0d,0x0a,
20622e5b6d6dSopenharmony_ci        /* "TZNAME:STDFINAL\r\n" */
20632e5b6d6dSopenharmony_ci        0x54,0x5a,0x4e,0x41,0x4d,0x45,0x3a,0x53,0x54,0x44,0x46,0x49,0x4e,0x41,0x4c,0x0d,0x0a,
20642e5b6d6dSopenharmony_ci        /* "DTSTART:20071028T020000\r\n" */
20652e5b6d6dSopenharmony_ci        0x44,0x54,0x53,0x54,0x41,0x52,0x54,0x3a,0x32,0x30,0x30,0x37,0x31,0x30,0x32,0x38,0x54,0x30,0x32,0x30,0x30,0x30,0x30,0x0d,0x0a,
20662e5b6d6dSopenharmony_ci        /* "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10\r\n" */
20672e5b6d6dSopenharmony_ci        0x52,0x52,0x55,0x4c,0x45,0x3a,0x46,0x52,0x45,0x51,0x3d,0x59,0x45,0x41,0x52,0x4c,0x59,0x3b,0x42,0x59,0x44,0x41,0x59,0x3d,0x2d,0x31,0x53,0x55,0x3b,0x42,0x59,0x4d,0x4f,0x4e,0x54,0x48,0x3d,0x31,0x30,0x0d,0x0a,
20682e5b6d6dSopenharmony_ci        /* "END:STANDARD\r\n" */
20692e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x53,0x54,0x41,0x4e,0x44,0x41,0x52,0x44,0x0d,0x0a,
20702e5b6d6dSopenharmony_ci        /* "END:VTIMEZONE\r\n" */
20712e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x56,0x54,0x49,0x4d,0x45,0x5a,0x4f,0x4e,0x45,0x0d,0x0a,
20722e5b6d6dSopenharmony_ci        /* "END:VCALENDAR" */
20732e5b6d6dSopenharmony_ci        0x45,0x4e,0x44,0x3a,0x56,0x43,0x41,0x4c,0x45,0x4e,0x44,0x41,0x52,0x0d,0x0a,
20742e5b6d6dSopenharmony_ci        0
20752e5b6d6dSopenharmony_ci    };
20762e5b6d6dSopenharmony_ci
20772e5b6d6dSopenharmony_ci    static const int32_t TestDates[][3] = {
20782e5b6d6dSopenharmony_ci        {1995, UCAL_JANUARY, 1},
20792e5b6d6dSopenharmony_ci        {1995, UCAL_JULY, 1},
20802e5b6d6dSopenharmony_ci        {2000, UCAL_JANUARY, 1},
20812e5b6d6dSopenharmony_ci        {2000, UCAL_JULY, 1},
20822e5b6d6dSopenharmony_ci        {2005, UCAL_JANUARY, 1},
20832e5b6d6dSopenharmony_ci        {2005, UCAL_JULY, 1},
20842e5b6d6dSopenharmony_ci        {2010, UCAL_JANUARY, 1},
20852e5b6d6dSopenharmony_ci        {2010, UCAL_JULY, 1},
20862e5b6d6dSopenharmony_ci        {0, 0, 0}
20872e5b6d6dSopenharmony_ci    };
20882e5b6d6dSopenharmony_ci
20892e5b6d6dSopenharmony_ci    /*static*/ const UnicodeString TestZones[] = {
20902e5b6d6dSopenharmony_ci        UnicodeString(tokyoTZ),
20912e5b6d6dSopenharmony_ci        UnicodeString(finalOverlap),
20922e5b6d6dSopenharmony_ci        UnicodeString(finalNonOverlap),
20932e5b6d6dSopenharmony_ci        UnicodeString()
20942e5b6d6dSopenharmony_ci    };
20952e5b6d6dSopenharmony_ci
20962e5b6d6dSopenharmony_ci    int32_t Expected[][8] = {
20972e5b6d6dSopenharmony_ci      //  JAN90      JUL90      JAN00      JUL00      JAN05      JUL05      JAN10      JUL10
20982e5b6d6dSopenharmony_ci        { 32400000,  32400000,  32400000,  32400000,  32400000,  32400000,  32400000,  32400000},
20992e5b6d6dSopenharmony_ci        {-10800000, -10800000,  -7200000,  -7200000, -10800000,  -7200000, -10800000, -10800000},
21002e5b6d6dSopenharmony_ci        {-10800000, -10800000,  -7200000,  -7200000, -10800000,  -7200000, -10800000, -10800000}
21012e5b6d6dSopenharmony_ci    };
21022e5b6d6dSopenharmony_ci
21032e5b6d6dSopenharmony_ci    int32_t i, j;
21042e5b6d6dSopenharmony_ci
21052e5b6d6dSopenharmony_ci    // Get test times
21062e5b6d6dSopenharmony_ci    UDate times[UPRV_LENGTHOF(TestDates)];
21072e5b6d6dSopenharmony_ci    int32_t numTimes;
21082e5b6d6dSopenharmony_ci
21092e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
21102e5b6d6dSopenharmony_ci    TimeZone *utc = TimeZone::createTimeZone("Etc/GMT");
21112e5b6d6dSopenharmony_ci    GregorianCalendar cal(utc, status);
21122e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
21132e5b6d6dSopenharmony_ci        dataerrln("FAIL: Failed to create a GregorianCalendar: %s", u_errorName(status));
21142e5b6d6dSopenharmony_ci        return;
21152e5b6d6dSopenharmony_ci    }
21162e5b6d6dSopenharmony_ci    for (i = 0; TestDates[i][2] != 0; i++) {
21172e5b6d6dSopenharmony_ci        cal.clear();
21182e5b6d6dSopenharmony_ci        cal.set(TestDates[i][0], TestDates[i][1], TestDates[i][2]);
21192e5b6d6dSopenharmony_ci        times[i] = cal.getTime(status);
21202e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
21212e5b6d6dSopenharmony_ci            errln("FAIL: getTime failed");
21222e5b6d6dSopenharmony_ci            return;
21232e5b6d6dSopenharmony_ci        }
21242e5b6d6dSopenharmony_ci    }
21252e5b6d6dSopenharmony_ci    numTimes = i;
21262e5b6d6dSopenharmony_ci
21272e5b6d6dSopenharmony_ci    // Test offset
21282e5b6d6dSopenharmony_ci    for (i = 0; !TestZones[i].isEmpty(); i++) {
21292e5b6d6dSopenharmony_ci        VTimeZone *vtz = VTimeZone::createVTimeZone(TestZones[i], status);
21302e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
21312e5b6d6dSopenharmony_ci            errln("FAIL: failed to create VTimeZone");
21322e5b6d6dSopenharmony_ci            continue;
21332e5b6d6dSopenharmony_ci        }
21342e5b6d6dSopenharmony_ci        for (j = 0; j < numTimes; j++) {
21352e5b6d6dSopenharmony_ci            int32_t raw, dst;
21362e5b6d6dSopenharmony_ci            status = U_ZERO_ERROR;
21372e5b6d6dSopenharmony_ci            vtz->getOffset(times[j], false, raw, dst, status);
21382e5b6d6dSopenharmony_ci            if (U_FAILURE(status)) {
21392e5b6d6dSopenharmony_ci                errln((UnicodeString)"FAIL: getOffset failed for time zone " + i + " at " + times[j]);
21402e5b6d6dSopenharmony_ci            }
21412e5b6d6dSopenharmony_ci            int32_t offset = raw + dst;
21422e5b6d6dSopenharmony_ci            if (offset != Expected[i][j]) {
21432e5b6d6dSopenharmony_ci                errln((UnicodeString)"FAIL: Invalid offset at time(" + times[j] + "):" + offset + " Expected:" + Expected[i][j]);
21442e5b6d6dSopenharmony_ci            }
21452e5b6d6dSopenharmony_ci        }
21462e5b6d6dSopenharmony_ci        delete vtz;
21472e5b6d6dSopenharmony_ci    }
21482e5b6d6dSopenharmony_ci}
21492e5b6d6dSopenharmony_ci
21502e5b6d6dSopenharmony_civoid
21512e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestT6669(void) {
21522e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
21532e5b6d6dSopenharmony_ci    SimpleTimeZone stz(0, "CustomID", UCAL_JANUARY, 1, UCAL_SUNDAY, 0, UCAL_JULY, 1, UCAL_SUNDAY, 0, status);
21542e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
21552e5b6d6dSopenharmony_ci        errln("FAIL: Failed to create a SimpleTimeZone");
21562e5b6d6dSopenharmony_ci        return;
21572e5b6d6dSopenharmony_ci    }
21582e5b6d6dSopenharmony_ci
21592e5b6d6dSopenharmony_ci    UDate t = 1230681600000.0; //2008-12-31T00:00:00
21602e5b6d6dSopenharmony_ci    UDate expectedNext = 1231027200000.0; //2009-01-04T00:00:00
21612e5b6d6dSopenharmony_ci    UDate expectedPrev = 1215298800000.0; //2008-07-06T00:00:00
21622e5b6d6dSopenharmony_ci
21632e5b6d6dSopenharmony_ci    TimeZoneTransition tzt;
21642e5b6d6dSopenharmony_ci    UBool avail = stz.getNextTransition(t, false, tzt);
21652e5b6d6dSopenharmony_ci    if (!avail) {
21662e5b6d6dSopenharmony_ci        errln("FAIL: No transition returned by getNextTransition.");
21672e5b6d6dSopenharmony_ci    } else if (tzt.getTime() != expectedNext) {
21682e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: Wrong transition time returned by getNextTransition - "
21692e5b6d6dSopenharmony_ci            + tzt.getTime() + " Expected: " + expectedNext);
21702e5b6d6dSopenharmony_ci    }
21712e5b6d6dSopenharmony_ci
21722e5b6d6dSopenharmony_ci    avail = stz.getPreviousTransition(t, true, tzt);
21732e5b6d6dSopenharmony_ci    if (!avail) {
21742e5b6d6dSopenharmony_ci        errln("FAIL: No transition returned by getPreviousTransition.");
21752e5b6d6dSopenharmony_ci    } else if (tzt.getTime() != expectedPrev) {
21762e5b6d6dSopenharmony_ci        errln((UnicodeString)"FAIL: Wrong transition time returned by getPreviousTransition - "
21772e5b6d6dSopenharmony_ci            + tzt.getTime() + " Expected: " + expectedPrev);
21782e5b6d6dSopenharmony_ci    }
21792e5b6d6dSopenharmony_ci}
21802e5b6d6dSopenharmony_ci
21812e5b6d6dSopenharmony_civoid
21822e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestVTimeZoneWrapper(void) {
21832e5b6d6dSopenharmony_ci#if 0
21842e5b6d6dSopenharmony_ci    // local variables
21852e5b6d6dSopenharmony_ci    UBool b;
21862e5b6d6dSopenharmony_ci    UChar * data = NULL;
21872e5b6d6dSopenharmony_ci    int32_t length = 0;
21882e5b6d6dSopenharmony_ci    int32_t i;
21892e5b6d6dSopenharmony_ci    UDate result;
21902e5b6d6dSopenharmony_ci    UDate base = 1231027200000.0; //2009-01-04T00:00:00
21912e5b6d6dSopenharmony_ci    UErrorCode status;
21922e5b6d6dSopenharmony_ci
21932e5b6d6dSopenharmony_ci    const char *name = "Test Initial";
21942e5b6d6dSopenharmony_ci    UChar uname[20];
21952e5b6d6dSopenharmony_ci
21962e5b6d6dSopenharmony_ci    UClassID cid1;
21972e5b6d6dSopenharmony_ci    UClassID cid2;
21982e5b6d6dSopenharmony_ci
21992e5b6d6dSopenharmony_ci    ZRule * r;
22002e5b6d6dSopenharmony_ci    IZRule* ir1;
22012e5b6d6dSopenharmony_ci    IZRule* ir2;
22022e5b6d6dSopenharmony_ci    ZTrans* zt1;
22032e5b6d6dSopenharmony_ci    ZTrans* zt2;
22042e5b6d6dSopenharmony_ci    VZone*  v1;
22052e5b6d6dSopenharmony_ci    VZone*  v2;
22062e5b6d6dSopenharmony_ci
22072e5b6d6dSopenharmony_ci    uprv_memset(uname, 0, sizeof(uname));
22082e5b6d6dSopenharmony_ci    u_uastrcpy(uname, name);
22092e5b6d6dSopenharmony_ci
22102e5b6d6dSopenharmony_ci    // create rules
22112e5b6d6dSopenharmony_ci    ir1 = izrule_open(uname, 13, 2*HOUR, 0);
22122e5b6d6dSopenharmony_ci    ir2 = izrule_clone(ir1);
22132e5b6d6dSopenharmony_ci
22142e5b6d6dSopenharmony_ci    // test equality
22152e5b6d6dSopenharmony_ci    b = izrule_equals(ir1, ir2);
22162e5b6d6dSopenharmony_ci    b = izrule_isEquivalentTo(ir1, ir2);
22172e5b6d6dSopenharmony_ci
22182e5b6d6dSopenharmony_ci    // test accessors
22192e5b6d6dSopenharmony_ci    izrule_getName(ir1, data, length);
22202e5b6d6dSopenharmony_ci    i = izrule_getRawOffset(ir1);
22212e5b6d6dSopenharmony_ci    i = izrule_getDSTSavings(ir1);
22222e5b6d6dSopenharmony_ci
22232e5b6d6dSopenharmony_ci    b = izrule_getFirstStart(ir1, 2*HOUR, 0, result);
22242e5b6d6dSopenharmony_ci    b = izrule_getFinalStart(ir1, 2*HOUR, 0, result);
22252e5b6d6dSopenharmony_ci    b = izrule_getNextStart(ir1, base , 2*HOUR, 0, true, result);
22262e5b6d6dSopenharmony_ci    b = izrule_getPreviousStart(ir1, base, 2*HOUR, 0, true, result);
22272e5b6d6dSopenharmony_ci
22282e5b6d6dSopenharmony_ci    // test class ids
22292e5b6d6dSopenharmony_ci    cid1 = izrule_getStaticClassID(ir1);
22302e5b6d6dSopenharmony_ci    cid2 = izrule_getDynamicClassID(ir1);
22312e5b6d6dSopenharmony_ci
22322e5b6d6dSopenharmony_ci    // test transitions
22332e5b6d6dSopenharmony_ci    zt1 = ztrans_open(base, ir1, ir2);
22342e5b6d6dSopenharmony_ci    zt2 = ztrans_clone(zt1);
22352e5b6d6dSopenharmony_ci    zt2 = ztrans_openEmpty();
22362e5b6d6dSopenharmony_ci
22372e5b6d6dSopenharmony_ci    // test equality
22382e5b6d6dSopenharmony_ci    b = ztrans_equals(zt1, zt2);
22392e5b6d6dSopenharmony_ci
22402e5b6d6dSopenharmony_ci    // test accessors
22412e5b6d6dSopenharmony_ci    result = ztrans_getTime(zt1);
22422e5b6d6dSopenharmony_ci    ztrans_setTime(zt1, result);
22432e5b6d6dSopenharmony_ci
22442e5b6d6dSopenharmony_ci    r = (ZRule*)ztrans_getFrom(zt1);
22452e5b6d6dSopenharmony_ci    ztrans_setFrom(zt1, (void*)ir1);
22462e5b6d6dSopenharmony_ci    ztrans_adoptFrom(zt1, (void*)ir1);
22472e5b6d6dSopenharmony_ci
22482e5b6d6dSopenharmony_ci    r = (ZRule*)ztrans_getTo(zt1);
22492e5b6d6dSopenharmony_ci    ztrans_setTo(zt1, (void*)ir2);
22502e5b6d6dSopenharmony_ci    ztrans_adoptTo(zt1, (void*)ir2);
22512e5b6d6dSopenharmony_ci
22522e5b6d6dSopenharmony_ci    // test class ids
22532e5b6d6dSopenharmony_ci    cid1 = ztrans_getStaticClassID(zt1);
22542e5b6d6dSopenharmony_ci    cid2 = ztrans_getDynamicClassID(zt2);
22552e5b6d6dSopenharmony_ci
22562e5b6d6dSopenharmony_ci    // test vzone
22572e5b6d6dSopenharmony_ci    v1 = vzone_openID((UChar*)"America/Chicago", sizeof("America/Chicago"));
22582e5b6d6dSopenharmony_ci    v2 = vzone_clone(v1);
22592e5b6d6dSopenharmony_ci    //v2 = vzone_openData(const UChar* vtzdata, int32_t vtzdataLength, UErrorCode& status);
22602e5b6d6dSopenharmony_ci
22612e5b6d6dSopenharmony_ci    // test equality
22622e5b6d6dSopenharmony_ci    b = vzone_equals(v1, v2);
22632e5b6d6dSopenharmony_ci    b = vzone_hasSameRules(v1, v2);
22642e5b6d6dSopenharmony_ci
22652e5b6d6dSopenharmony_ci    // test accessors
22662e5b6d6dSopenharmony_ci    b = vzone_getTZURL(v1, data, length);
22672e5b6d6dSopenharmony_ci    vzone_setTZURL(v1, data, length);
22682e5b6d6dSopenharmony_ci
22692e5b6d6dSopenharmony_ci    b = vzone_getLastModified(v1, result);
22702e5b6d6dSopenharmony_ci    vzone_setLastModified(v1, result);
22712e5b6d6dSopenharmony_ci
22722e5b6d6dSopenharmony_ci    // test writers
22732e5b6d6dSopenharmony_ci    vzone_write(v1, data, length, status);
22742e5b6d6dSopenharmony_ci    vzone_writeFromStart(v1, result, data, length, status);
22752e5b6d6dSopenharmony_ci    vzone_writeSimple(v1, result, data, length, status);
22762e5b6d6dSopenharmony_ci
22772e5b6d6dSopenharmony_ci    // test more accessors
22782e5b6d6dSopenharmony_ci    i = vzone_getRawOffset(v1);
22792e5b6d6dSopenharmony_ci    vzone_setRawOffset(v1, i);
22802e5b6d6dSopenharmony_ci
22812e5b6d6dSopenharmony_ci    b = vzone_useDaylightTime(v1);
22822e5b6d6dSopenharmony_ci    b = vzone_inDaylightTime(v1, result, status);
22832e5b6d6dSopenharmony_ci
22842e5b6d6dSopenharmony_ci    b = vzone_getNextTransition(v1, result, false, zt1);
22852e5b6d6dSopenharmony_ci    b = vzone_getPreviousTransition(v1, result, false, zt1);
22862e5b6d6dSopenharmony_ci    i = vzone_countTransitionRules(v1, status);
22872e5b6d6dSopenharmony_ci
22882e5b6d6dSopenharmony_ci    cid1 = vzone_getStaticClassID(v1);
22892e5b6d6dSopenharmony_ci    cid2 = vzone_getDynamicClassID(v1);
22902e5b6d6dSopenharmony_ci
22912e5b6d6dSopenharmony_ci    // cleanup
22922e5b6d6dSopenharmony_ci    vzone_close(v1);
22932e5b6d6dSopenharmony_ci    vzone_close(v2);
22942e5b6d6dSopenharmony_ci    ztrans_close(zt1);
22952e5b6d6dSopenharmony_ci    ztrans_close(zt2);
22962e5b6d6dSopenharmony_ci#endif
22972e5b6d6dSopenharmony_ci}
22982e5b6d6dSopenharmony_ci
22992e5b6d6dSopenharmony_ci//----------- private test helpers -------------------------------------------------
23002e5b6d6dSopenharmony_ci
23012e5b6d6dSopenharmony_ciUDate
23022e5b6d6dSopenharmony_ciTimeZoneRuleTest::getUTCMillis(int32_t y, int32_t m, int32_t d,
23032e5b6d6dSopenharmony_ci                               int32_t hr, int32_t min, int32_t sec, int32_t msec) {
23042e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
23052e5b6d6dSopenharmony_ci    const TimeZone *tz = TimeZone::getGMT();
23062e5b6d6dSopenharmony_ci    Calendar *cal = Calendar::createInstance(*tz, status);
23072e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
23082e5b6d6dSopenharmony_ci        delete cal;
23092e5b6d6dSopenharmony_ci        dataerrln("FAIL: Calendar::createInstance failed: %s", u_errorName(status));
23102e5b6d6dSopenharmony_ci        return 0.0;
23112e5b6d6dSopenharmony_ci    }
23122e5b6d6dSopenharmony_ci    cal->set(y, m, d, hr, min, sec);
23132e5b6d6dSopenharmony_ci    cal->set(UCAL_MILLISECOND, msec);
23142e5b6d6dSopenharmony_ci    UDate utc = cal->getTime(status);
23152e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
23162e5b6d6dSopenharmony_ci        delete cal;
23172e5b6d6dSopenharmony_ci        errln("FAIL: Calendar::getTime failed");
23182e5b6d6dSopenharmony_ci        return 0.0;
23192e5b6d6dSopenharmony_ci    }
23202e5b6d6dSopenharmony_ci    delete cal;
23212e5b6d6dSopenharmony_ci    return utc;
23222e5b6d6dSopenharmony_ci}
23232e5b6d6dSopenharmony_ci
23242e5b6d6dSopenharmony_ci/*
23252e5b6d6dSopenharmony_ci * Check if a time shift really happens on each transition returned by getNextTransition or
23262e5b6d6dSopenharmony_ci * getPreviousTransition in the specified time range
23272e5b6d6dSopenharmony_ci */
23282e5b6d6dSopenharmony_civoid
23292e5b6d6dSopenharmony_ciTimeZoneRuleTest::verifyTransitions(BasicTimeZone& icutz, UDate start, UDate end) {
23302e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
23312e5b6d6dSopenharmony_ci    UDate time;
23322e5b6d6dSopenharmony_ci    int32_t raw, dst, raw0, dst0;
23332e5b6d6dSopenharmony_ci    TimeZoneTransition tzt, tzt0;
23342e5b6d6dSopenharmony_ci    UBool avail;
23352e5b6d6dSopenharmony_ci    UBool first = true;
23362e5b6d6dSopenharmony_ci    UnicodeString tzid;
23372e5b6d6dSopenharmony_ci
23382e5b6d6dSopenharmony_ci    // Ascending
23392e5b6d6dSopenharmony_ci    time = start;
23402e5b6d6dSopenharmony_ci    while (true) {
23412e5b6d6dSopenharmony_ci        avail = icutz.getNextTransition(time, false, tzt);
23422e5b6d6dSopenharmony_ci        if (!avail) {
23432e5b6d6dSopenharmony_ci            break;
23442e5b6d6dSopenharmony_ci        }
23452e5b6d6dSopenharmony_ci        time = tzt.getTime();
23462e5b6d6dSopenharmony_ci        if (time >= end) {
23472e5b6d6dSopenharmony_ci            break;
23482e5b6d6dSopenharmony_ci        }
23492e5b6d6dSopenharmony_ci        icutz.getOffset(time, false, raw, dst, status);
23502e5b6d6dSopenharmony_ci        icutz.getOffset(time - 1, false, raw0, dst0, status);
23512e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
23522e5b6d6dSopenharmony_ci            errln("FAIL: Error in getOffset");
23532e5b6d6dSopenharmony_ci            break;
23542e5b6d6dSopenharmony_ci        }
23552e5b6d6dSopenharmony_ci
23562e5b6d6dSopenharmony_ci        if (raw == raw0 && dst == dst0) {
23572e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: False transition returned by getNextTransition for "
23582e5b6d6dSopenharmony_ci                + icutz.getID(tzid) + " at " + dateToString(time));
23592e5b6d6dSopenharmony_ci        }
23602e5b6d6dSopenharmony_ci        if (!first &&
23612e5b6d6dSopenharmony_ci                (tzt0.getTo()->getRawOffset() != tzt.getFrom()->getRawOffset()
23622e5b6d6dSopenharmony_ci                || tzt0.getTo()->getDSTSavings() != tzt.getFrom()->getDSTSavings())) {
23632e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: TO rule of the previous transition does not match FROM rule of this transition at "
23642e5b6d6dSopenharmony_ci                    + dateToString(time) + " for " + icutz.getID(tzid));
23652e5b6d6dSopenharmony_ci        }
23662e5b6d6dSopenharmony_ci        tzt0 = tzt;
23672e5b6d6dSopenharmony_ci        first = false;
23682e5b6d6dSopenharmony_ci    }
23692e5b6d6dSopenharmony_ci
23702e5b6d6dSopenharmony_ci    // Descending
23712e5b6d6dSopenharmony_ci    first = true;
23722e5b6d6dSopenharmony_ci    time = end;
23732e5b6d6dSopenharmony_ci    while(true) {
23742e5b6d6dSopenharmony_ci        avail = icutz.getPreviousTransition(time, false, tzt);
23752e5b6d6dSopenharmony_ci        if (!avail) {
23762e5b6d6dSopenharmony_ci            break;
23772e5b6d6dSopenharmony_ci        }
23782e5b6d6dSopenharmony_ci        time = tzt.getTime();
23792e5b6d6dSopenharmony_ci        if (time <= start) {
23802e5b6d6dSopenharmony_ci            break;
23812e5b6d6dSopenharmony_ci        }
23822e5b6d6dSopenharmony_ci        icutz.getOffset(time, false, raw, dst, status);
23832e5b6d6dSopenharmony_ci        icutz.getOffset(time - 1, false, raw0, dst0, status);
23842e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
23852e5b6d6dSopenharmony_ci            errln("FAIL: Error in getOffset");
23862e5b6d6dSopenharmony_ci            break;
23872e5b6d6dSopenharmony_ci        }
23882e5b6d6dSopenharmony_ci
23892e5b6d6dSopenharmony_ci        if (raw == raw0 && dst == dst0) {
23902e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: False transition returned by getPreviousTransition for "
23912e5b6d6dSopenharmony_ci                + icutz.getID(tzid) + " at " + dateToString(time));
23922e5b6d6dSopenharmony_ci        }
23932e5b6d6dSopenharmony_ci
23942e5b6d6dSopenharmony_ci        if (!first &&
23952e5b6d6dSopenharmony_ci                (tzt0.getFrom()->getRawOffset() != tzt.getTo()->getRawOffset()
23962e5b6d6dSopenharmony_ci                || tzt0.getFrom()->getDSTSavings() != tzt.getTo()->getDSTSavings())) {
23972e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: TO rule of the next transition does not match FROM rule in this transition at "
23982e5b6d6dSopenharmony_ci                    + dateToString(time) + " for " + icutz.getID(tzid));
23992e5b6d6dSopenharmony_ci        }
24002e5b6d6dSopenharmony_ci        tzt0 = tzt;
24012e5b6d6dSopenharmony_ci        first = false;
24022e5b6d6dSopenharmony_ci    }
24032e5b6d6dSopenharmony_ci}
24042e5b6d6dSopenharmony_ci
24052e5b6d6dSopenharmony_ci/*
24062e5b6d6dSopenharmony_ci * Compare all time transitions in 2 time zones in the specified time range in ascending order
24072e5b6d6dSopenharmony_ci */
24082e5b6d6dSopenharmony_civoid
24092e5b6d6dSopenharmony_ciTimeZoneRuleTest::compareTransitionsAscending(BasicTimeZone& z1, BasicTimeZone& z2,
24102e5b6d6dSopenharmony_ci                                              UDate start, UDate end, UBool inclusive) {
24112e5b6d6dSopenharmony_ci    UnicodeString zid1, zid2;
24122e5b6d6dSopenharmony_ci    TimeZoneTransition tzt1, tzt2;
24132e5b6d6dSopenharmony_ci    UBool avail1, avail2;
24142e5b6d6dSopenharmony_ci    UBool inRange1, inRange2;
24152e5b6d6dSopenharmony_ci
24162e5b6d6dSopenharmony_ci    z1.getID(zid1);
24172e5b6d6dSopenharmony_ci    z2.getID(zid2);
24182e5b6d6dSopenharmony_ci
24192e5b6d6dSopenharmony_ci    UDate time = start;
24202e5b6d6dSopenharmony_ci    while (true) {
24212e5b6d6dSopenharmony_ci        avail1 = z1.getNextTransition(time, inclusive, tzt1);
24222e5b6d6dSopenharmony_ci        avail2 = z2.getNextTransition(time, inclusive, tzt2);
24232e5b6d6dSopenharmony_ci
24242e5b6d6dSopenharmony_ci        inRange1 = inRange2 = false;
24252e5b6d6dSopenharmony_ci        if (avail1) {
24262e5b6d6dSopenharmony_ci            if (tzt1.getTime() < end || (inclusive && tzt1.getTime() == end)) {
24272e5b6d6dSopenharmony_ci                inRange1 = true;
24282e5b6d6dSopenharmony_ci            }
24292e5b6d6dSopenharmony_ci        }
24302e5b6d6dSopenharmony_ci        if (avail2) {
24312e5b6d6dSopenharmony_ci            if (tzt2.getTime() < end || (inclusive && tzt2.getTime() == end)) {
24322e5b6d6dSopenharmony_ci                inRange2 = true;
24332e5b6d6dSopenharmony_ci            }
24342e5b6d6dSopenharmony_ci        }
24352e5b6d6dSopenharmony_ci        if (!inRange1 && !inRange2) {
24362e5b6d6dSopenharmony_ci            // No more transition in the range
24372e5b6d6dSopenharmony_ci            break;
24382e5b6d6dSopenharmony_ci        }
24392e5b6d6dSopenharmony_ci        if (!inRange1) {
24402e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: " + zid1 + " does not have any transitions after "
24412e5b6d6dSopenharmony_ci                + dateToString(time) + " before " + dateToString(end));
24422e5b6d6dSopenharmony_ci            break;
24432e5b6d6dSopenharmony_ci        }
24442e5b6d6dSopenharmony_ci        if (!inRange2) {
24452e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: " + zid2 + " does not have any transitions after "
24462e5b6d6dSopenharmony_ci                + dateToString(time) + " before " + dateToString(end));
24472e5b6d6dSopenharmony_ci            break;
24482e5b6d6dSopenharmony_ci        }
24492e5b6d6dSopenharmony_ci        if (tzt1.getTime() != tzt2.getTime()) {
24502e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: First transition after " + dateToString(time) + " "
24512e5b6d6dSopenharmony_ci                    + zid1 + "[" + dateToString(tzt1.getTime()) + "] "
24522e5b6d6dSopenharmony_ci                    + zid2 + "[" + dateToString(tzt2.getTime()) + "]");
24532e5b6d6dSopenharmony_ci            break;
24542e5b6d6dSopenharmony_ci        }
24552e5b6d6dSopenharmony_ci        time = tzt1.getTime();
24562e5b6d6dSopenharmony_ci        if (inclusive) {
24572e5b6d6dSopenharmony_ci            time += 1;
24582e5b6d6dSopenharmony_ci        }
24592e5b6d6dSopenharmony_ci    }
24602e5b6d6dSopenharmony_ci}
24612e5b6d6dSopenharmony_ci
24622e5b6d6dSopenharmony_ci/*
24632e5b6d6dSopenharmony_ci * Compare all time transitions in 2 time zones in the specified time range in descending order
24642e5b6d6dSopenharmony_ci */
24652e5b6d6dSopenharmony_civoid
24662e5b6d6dSopenharmony_ciTimeZoneRuleTest::compareTransitionsDescending(BasicTimeZone& z1, BasicTimeZone& z2,
24672e5b6d6dSopenharmony_ci                                               UDate start, UDate end, UBool inclusive) {
24682e5b6d6dSopenharmony_ci    UnicodeString zid1, zid2;
24692e5b6d6dSopenharmony_ci    TimeZoneTransition tzt1, tzt2;
24702e5b6d6dSopenharmony_ci    UBool avail1, avail2;
24712e5b6d6dSopenharmony_ci    UBool inRange1, inRange2;
24722e5b6d6dSopenharmony_ci
24732e5b6d6dSopenharmony_ci    z1.getID(zid1);
24742e5b6d6dSopenharmony_ci    z2.getID(zid2);
24752e5b6d6dSopenharmony_ci
24762e5b6d6dSopenharmony_ci    UDate time = end;
24772e5b6d6dSopenharmony_ci    while (true) {
24782e5b6d6dSopenharmony_ci        avail1 = z1.getPreviousTransition(time, inclusive, tzt1);
24792e5b6d6dSopenharmony_ci        avail2 = z2.getPreviousTransition(time, inclusive, tzt2);
24802e5b6d6dSopenharmony_ci
24812e5b6d6dSopenharmony_ci        inRange1 = inRange2 = false;
24822e5b6d6dSopenharmony_ci        if (avail1) {
24832e5b6d6dSopenharmony_ci            if (tzt1.getTime() > start || (inclusive && tzt1.getTime() == start)) {
24842e5b6d6dSopenharmony_ci                inRange1 = true;
24852e5b6d6dSopenharmony_ci            }
24862e5b6d6dSopenharmony_ci        }
24872e5b6d6dSopenharmony_ci        if (avail2) {
24882e5b6d6dSopenharmony_ci            if (tzt2.getTime() > start || (inclusive && tzt2.getTime() == start)) {
24892e5b6d6dSopenharmony_ci                inRange2 = true;
24902e5b6d6dSopenharmony_ci            }
24912e5b6d6dSopenharmony_ci        }
24922e5b6d6dSopenharmony_ci        if (!inRange1 && !inRange2) {
24932e5b6d6dSopenharmony_ci            // No more transition in the range
24942e5b6d6dSopenharmony_ci            break;
24952e5b6d6dSopenharmony_ci        }
24962e5b6d6dSopenharmony_ci        if (!inRange1) {
24972e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: " + zid1 + " does not have any transitions before "
24982e5b6d6dSopenharmony_ci                + dateToString(time) + " after " + dateToString(start));
24992e5b6d6dSopenharmony_ci            break;
25002e5b6d6dSopenharmony_ci        }
25012e5b6d6dSopenharmony_ci        if (!inRange2) {
25022e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: " + zid2 + " does not have any transitions before "
25032e5b6d6dSopenharmony_ci                + dateToString(time) + " after " + dateToString(start));
25042e5b6d6dSopenharmony_ci            break;
25052e5b6d6dSopenharmony_ci        }
25062e5b6d6dSopenharmony_ci        if (tzt1.getTime() != tzt2.getTime()) {
25072e5b6d6dSopenharmony_ci            errln((UnicodeString)"FAIL: Last transition before " + dateToString(time) + " "
25082e5b6d6dSopenharmony_ci                    + zid1 + "[" + dateToString(tzt1.getTime()) + "] "
25092e5b6d6dSopenharmony_ci                    + zid2 + "[" + dateToString(tzt2.getTime()) + "]");
25102e5b6d6dSopenharmony_ci            break;
25112e5b6d6dSopenharmony_ci        }
25122e5b6d6dSopenharmony_ci        time = tzt1.getTime();
25132e5b6d6dSopenharmony_ci        if (inclusive) {
25142e5b6d6dSopenharmony_ci            time -= 1;
25152e5b6d6dSopenharmony_ci        }
25162e5b6d6dSopenharmony_ci    }
25172e5b6d6dSopenharmony_ci}
25182e5b6d6dSopenharmony_ci
25192e5b6d6dSopenharmony_ci// Slightly modified version of BasicTimeZone::hasEquivalentTransitions.
25202e5b6d6dSopenharmony_ci// This version returns true if transition time delta is within the given
25212e5b6d6dSopenharmony_ci// delta range.
25222e5b6d6dSopenharmony_cistatic UBool hasEquivalentTransitions(/*const*/ BasicTimeZone& tz1, /*const*/BasicTimeZone& tz2,
25232e5b6d6dSopenharmony_ci                                        UDate start, UDate end,
25242e5b6d6dSopenharmony_ci                                        UBool ignoreDstAmount, int32_t maxTransitionTimeDelta,
25252e5b6d6dSopenharmony_ci                                        UErrorCode& status) {
25262e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
25272e5b6d6dSopenharmony_ci        return false;
25282e5b6d6dSopenharmony_ci    }
25292e5b6d6dSopenharmony_ci    if (tz1.hasSameRules(tz2)) {
25302e5b6d6dSopenharmony_ci        return true;
25312e5b6d6dSopenharmony_ci    }
25322e5b6d6dSopenharmony_ci    // Check the offsets at the start time
25332e5b6d6dSopenharmony_ci    int32_t raw1, raw2, dst1, dst2;
25342e5b6d6dSopenharmony_ci    tz1.getOffset(start, false, raw1, dst1, status);
25352e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
25362e5b6d6dSopenharmony_ci        return false;
25372e5b6d6dSopenharmony_ci    }
25382e5b6d6dSopenharmony_ci    tz2.getOffset(start, false, raw2, dst2, status);
25392e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
25402e5b6d6dSopenharmony_ci        return false;
25412e5b6d6dSopenharmony_ci    }
25422e5b6d6dSopenharmony_ci    if (ignoreDstAmount) {
25432e5b6d6dSopenharmony_ci        if ((raw1 + dst1 != raw2 + dst2)
25442e5b6d6dSopenharmony_ci            || (dst1 != 0 && dst2 == 0)
25452e5b6d6dSopenharmony_ci            || (dst1 == 0 && dst2 != 0)) {
25462e5b6d6dSopenharmony_ci            return false;
25472e5b6d6dSopenharmony_ci        }
25482e5b6d6dSopenharmony_ci    } else {
25492e5b6d6dSopenharmony_ci        if (raw1 != raw2 || dst1 != dst2) {
25502e5b6d6dSopenharmony_ci            return false;
25512e5b6d6dSopenharmony_ci        }
25522e5b6d6dSopenharmony_ci    }
25532e5b6d6dSopenharmony_ci    // Check transitions in the range
25542e5b6d6dSopenharmony_ci    UDate time = start;
25552e5b6d6dSopenharmony_ci    TimeZoneTransition tr1, tr2;
25562e5b6d6dSopenharmony_ci    while (true) {
25572e5b6d6dSopenharmony_ci        UBool avail1 = tz1.getNextTransition(time, false, tr1);
25582e5b6d6dSopenharmony_ci        UBool avail2 = tz2.getNextTransition(time, false, tr2);
25592e5b6d6dSopenharmony_ci
25602e5b6d6dSopenharmony_ci        if (ignoreDstAmount) {
25612e5b6d6dSopenharmony_ci            // Skip a transition which only differ the amount of DST savings
25622e5b6d6dSopenharmony_ci            while (true) {
25632e5b6d6dSopenharmony_ci                if (avail1
25642e5b6d6dSopenharmony_ci                        && tr1.getTime() <= end
25652e5b6d6dSopenharmony_ci                        && (tr1.getFrom()->getRawOffset() + tr1.getFrom()->getDSTSavings()
25662e5b6d6dSopenharmony_ci                                == tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings())
25672e5b6d6dSopenharmony_ci                        && (tr1.getFrom()->getDSTSavings() != 0 && tr1.getTo()->getDSTSavings() != 0)) {
25682e5b6d6dSopenharmony_ci                    tz1.getNextTransition(tr1.getTime(), false, tr1);
25692e5b6d6dSopenharmony_ci                } else {
25702e5b6d6dSopenharmony_ci                    break;
25712e5b6d6dSopenharmony_ci                }
25722e5b6d6dSopenharmony_ci            }
25732e5b6d6dSopenharmony_ci            while (true) {
25742e5b6d6dSopenharmony_ci                if (avail2
25752e5b6d6dSopenharmony_ci                        && tr2.getTime() <= end
25762e5b6d6dSopenharmony_ci                        && (tr2.getFrom()->getRawOffset() + tr2.getFrom()->getDSTSavings()
25772e5b6d6dSopenharmony_ci                                == tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings())
25782e5b6d6dSopenharmony_ci                        && (tr2.getFrom()->getDSTSavings() != 0 && tr2.getTo()->getDSTSavings() != 0)) {
25792e5b6d6dSopenharmony_ci                    tz2.getNextTransition(tr2.getTime(), false, tr2);
25802e5b6d6dSopenharmony_ci                } else {
25812e5b6d6dSopenharmony_ci                    break;
25822e5b6d6dSopenharmony_ci                }
25832e5b6d6dSopenharmony_ci            }
25842e5b6d6dSopenharmony_ci        }
25852e5b6d6dSopenharmony_ci
25862e5b6d6dSopenharmony_ci        UBool inRange1 = (avail1 && tr1.getTime() <= end);
25872e5b6d6dSopenharmony_ci        UBool inRange2 = (avail2 && tr2.getTime() <= end);
25882e5b6d6dSopenharmony_ci        if (!inRange1 && !inRange2) {
25892e5b6d6dSopenharmony_ci            // No more transition in the range
25902e5b6d6dSopenharmony_ci            break;
25912e5b6d6dSopenharmony_ci        }
25922e5b6d6dSopenharmony_ci        if (!inRange1 || !inRange2) {
25932e5b6d6dSopenharmony_ci            return false;
25942e5b6d6dSopenharmony_ci        }
25952e5b6d6dSopenharmony_ci        double delta = tr1.getTime() >= tr2.getTime() ? tr1.getTime() - tr2.getTime() : tr2.getTime() - tr1.getTime();
25962e5b6d6dSopenharmony_ci        if (delta > (double)maxTransitionTimeDelta) {
25972e5b6d6dSopenharmony_ci            return false;
25982e5b6d6dSopenharmony_ci        }
25992e5b6d6dSopenharmony_ci        if (ignoreDstAmount) {
26002e5b6d6dSopenharmony_ci            if (tr1.getTo()->getRawOffset() + tr1.getTo()->getDSTSavings()
26012e5b6d6dSopenharmony_ci                        != tr2.getTo()->getRawOffset() + tr2.getTo()->getDSTSavings()
26022e5b6d6dSopenharmony_ci                    || (tr1.getTo()->getDSTSavings() != 0 &&  tr2.getTo()->getDSTSavings() == 0)
26032e5b6d6dSopenharmony_ci                    || (tr1.getTo()->getDSTSavings() == 0 &&  tr2.getTo()->getDSTSavings() != 0)) {
26042e5b6d6dSopenharmony_ci                return false;
26052e5b6d6dSopenharmony_ci            }
26062e5b6d6dSopenharmony_ci        } else {
26072e5b6d6dSopenharmony_ci            if (tr1.getTo()->getRawOffset() != tr2.getTo()->getRawOffset() ||
26082e5b6d6dSopenharmony_ci                tr1.getTo()->getDSTSavings() != tr2.getTo()->getDSTSavings()) {
26092e5b6d6dSopenharmony_ci                return false;
26102e5b6d6dSopenharmony_ci            }
26112e5b6d6dSopenharmony_ci        }
26122e5b6d6dSopenharmony_ci        time = tr1.getTime() > tr2.getTime() ? tr1.getTime() : tr2.getTime();
26132e5b6d6dSopenharmony_ci    }
26142e5b6d6dSopenharmony_ci    return true;
26152e5b6d6dSopenharmony_ci}
26162e5b6d6dSopenharmony_ci
26172e5b6d6dSopenharmony_ci// Test case for ticket#8943
26182e5b6d6dSopenharmony_ci// RuleBasedTimeZone#getOffsets throws NPE
26192e5b6d6dSopenharmony_civoid
26202e5b6d6dSopenharmony_ciTimeZoneRuleTest::TestT8943(void) {
26212e5b6d6dSopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
26222e5b6d6dSopenharmony_ci    UnicodeString id("Ekaterinburg Time");
26232e5b6d6dSopenharmony_ci    UnicodeString stdName("Ekaterinburg Standard Time");
26242e5b6d6dSopenharmony_ci    UnicodeString dstName("Ekaterinburg Daylight Time");
26252e5b6d6dSopenharmony_ci
26262e5b6d6dSopenharmony_ci    InitialTimeZoneRule *initialRule = new InitialTimeZoneRule(stdName, 18000000, 0);
26272e5b6d6dSopenharmony_ci    RuleBasedTimeZone *rbtz = new RuleBasedTimeZone(id, initialRule);
26282e5b6d6dSopenharmony_ci
26292e5b6d6dSopenharmony_ci    DateTimeRule *dtRule = new DateTimeRule(UCAL_OCTOBER, -1, UCAL_SUNDAY, 10800000, DateTimeRule::WALL_TIME);
26302e5b6d6dSopenharmony_ci    AnnualTimeZoneRule *atzRule = new AnnualTimeZoneRule(stdName, 18000000, 0, dtRule, 2000, 2010);
26312e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(atzRule, status);
26322e5b6d6dSopenharmony_ci
26332e5b6d6dSopenharmony_ci    dtRule = new DateTimeRule(UCAL_MARCH, -1, UCAL_SUNDAY, 7200000, DateTimeRule::WALL_TIME);
26342e5b6d6dSopenharmony_ci    atzRule = new AnnualTimeZoneRule(dstName, 18000000, 3600000, dtRule, 2000, 2010);
26352e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(atzRule, status);
26362e5b6d6dSopenharmony_ci
26372e5b6d6dSopenharmony_ci    dtRule = new DateTimeRule(UCAL_JANUARY, 1, 0, DateTimeRule::WALL_TIME);
26382e5b6d6dSopenharmony_ci    atzRule = new AnnualTimeZoneRule(stdName, 21600000, 0, dtRule, 2011, AnnualTimeZoneRule::MAX_YEAR);
26392e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(atzRule, status);
26402e5b6d6dSopenharmony_ci
26412e5b6d6dSopenharmony_ci    dtRule = new DateTimeRule(UCAL_JANUARY, 1, 1, DateTimeRule::WALL_TIME);
26422e5b6d6dSopenharmony_ci    atzRule = new AnnualTimeZoneRule(dstName, 21600000, 0, dtRule, 2011, AnnualTimeZoneRule::MAX_YEAR);
26432e5b6d6dSopenharmony_ci    rbtz->addTransitionRule(atzRule, status);
26442e5b6d6dSopenharmony_ci    rbtz->complete(status);
26452e5b6d6dSopenharmony_ci
26462e5b6d6dSopenharmony_ci    if (U_FAILURE(status)) {
26472e5b6d6dSopenharmony_ci        errln("Failed to construct a RuleBasedTimeZone");
26482e5b6d6dSopenharmony_ci    } else {
26492e5b6d6dSopenharmony_ci        int32_t raw, dst;
26502e5b6d6dSopenharmony_ci        rbtz->getOffset(1293822000000.0 /* 2010-12-31 19:00:00 UTC */, false, raw, dst, status);
26512e5b6d6dSopenharmony_ci        if (U_FAILURE(status)) {
26522e5b6d6dSopenharmony_ci            errln("Error invoking getOffset");
26532e5b6d6dSopenharmony_ci        } else if (raw != 21600000 || dst != 0) {
26542e5b6d6dSopenharmony_ci            errln(UnicodeString("Fail: Wrong offsets: ") + raw + "/" + dst + " Expected: 21600000/0");
26552e5b6d6dSopenharmony_ci        }
26562e5b6d6dSopenharmony_ci    }
26572e5b6d6dSopenharmony_ci
26582e5b6d6dSopenharmony_ci    delete rbtz;
26592e5b6d6dSopenharmony_ci}
26602e5b6d6dSopenharmony_ci
26612e5b6d6dSopenharmony_ci#endif /* #if !UCONFIG_NO_FORMATTING */
26622e5b6d6dSopenharmony_ci
26632e5b6d6dSopenharmony_ci//eof
2664