1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
38393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius* Copyright (C) 2007-2013, International Business Machines Corporation and    *
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* others. All Rights Reserved.                                                *
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "tzfmttst.h"
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "simplethread.h"
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/timezone.h"
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/simpletz.h"
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/calendar.h"
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/strenum.h"
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/smpdtfmt.h"
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/uchar.h"
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/basictz.h"
218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "unicode/tzfmt.h"
228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "unicode/localpointer.h"
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius#include "zonemeta.h"
258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const char* PATTERNS[] = {
278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "z",
288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "zzzz",
298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "Z",    // equivalent to "xxxx"
308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "ZZZZ", // equivalent to "OOOO"
318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "v",
328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "vvvv",
338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "O",
348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "OOOO",
358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "X",
368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "XX",
378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "XXX",
388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "XXXX",
398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "XXXXX",
408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "x",
418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "xx",
428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "xxx",
438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "xxxx",
448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "xxxxx",
458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "V",
468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "VV",
478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "VVV",
488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    "VVVV"
498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius};
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int NUM_PATTERNS = sizeof(PATTERNS)/sizeof(const char*);
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const UChar ETC_UNKNOWN[] = {0x45, 0x74, 0x63, 0x2F, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0};
538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const UChar ETC_SLASH[] = { 0x45, 0x74, 0x63, 0x2F, 0 }; // "Etc/"
558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const UChar SYSTEMV_SLASH[] = { 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x56, 0x2F, 0 }; // "SystemV/
568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const UChar RIYADH8[] = { 0x52, 0x69, 0x79, 0x61, 0x64, 0x68, 0x38, 0 }; // "Riyadh8"
578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic UBool contains(const char** list, const char* str) {
598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    for (int32_t i = 0; list[i]; i++) {
608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if (uprv_strcmp(list[i], str) == 0) {
618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            return TRUE;
628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    return FALSE;
658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZoneFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (exec) {
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        logln("TestSuite TimeZoneFormatTest");
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    switch (index) {
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        TESTCASE(0, TestTimeZoneRoundTrip);
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        TESTCASE(1, TestTimeRoundTrip);
768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        TESTCASE(2, TestParse);
778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        TESTCASE(3, TestISOFormat);
7859d709d503bab6e2b61931737e662dd293b40578ccornelius        TESTCASE(4, TestFormat);
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default: name = ""; break;
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZoneFormatTest::TestTimeZoneRoundTrip(void) {
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    SimpleTimeZone unknownZone(-31415, ETC_UNKNOWN);
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t badDstOffset = -1234;
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t badZoneOffset = -2345;
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t testDateData[][3] = {
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {2007, 1, 15},
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {2007, 6, 15},
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {1990, 1, 15},
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {1990, 6, 15},
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {1960, 1, 15},
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        {1960, 6, 15},
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    };
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    Calendar *cal = Calendar::createInstance(TimeZone::createTimeZone((UnicodeString)"UTC"), status);
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
10250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        dataerrln("Calendar::createInstance failed: %s", u_errorName(status));
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Set up rule equivalency test range
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate low, high;
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cal->set(1900, UCAL_JANUARY, 1);
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    low = cal->getTime(status);
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cal->set(2040, UCAL_JANUARY, 1);
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    high = cal->getTime(status);
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("getTime failed");
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Set up test dates
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate DATES[(sizeof(testDateData)/sizeof(int32_t))/3];
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const int32_t nDates = (sizeof(testDateData)/sizeof(int32_t))/3;
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cal->clear();
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i = 0; i < nDates; i++) {
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        cal->set(testDateData[i][0], testDateData[i][1], testDateData[i][2]);
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DATES[i] = cal->getTime(status);
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(status)) {
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            errln("getTime failed");
126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return;
127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Set up test locales
131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const Locale testLocales[] = {
132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Locale("en"),
133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Locale("en_CA"),
134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Locale("fr"),
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Locale("zh_Hant")
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    };
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const Locale *LOCALES;
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t nLocales;
140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (quick) {
142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        LOCALES = testLocales;
143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        nLocales = sizeof(testLocales)/sizeof(Locale);
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        LOCALES = Locale::getAvailableLocales(nLocales);
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    StringEnumeration *tzids = TimeZone::createEnumeration();
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t inRaw, inDst;
150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t outRaw, outDst;
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Run the roundtrip test
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t locidx = 0; locidx < nLocales; locidx++) {
154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString localGMTString;
155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        SimpleDateFormat gmtFmt(UnicodeString("ZZZZ"), LOCALES[locidx], status);
156103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (U_FAILURE(status)) {
157103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            dataerrln("Error creating SimpleDateFormat - %s", u_errorName(status));
158103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            continue;
159103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        gmtFmt.setTimeZone(*TimeZone::getGMT());
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        gmtFmt.format(0.0, localGMTString);
162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        for (int32_t patidx = 0; patidx < NUM_PATTERNS; patidx++) {
164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)PATTERNS[patidx], LOCALES[locidx], status);
166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_FAILURE(status)) {
167103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                dataerrln((UnicodeString)"new SimpleDateFormat failed for pattern " +
1686d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru                    PATTERNS[patidx] + " for locale " + LOCALES[locidx].getName() + " - " + u_errorName(status));
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                status = U_ZERO_ERROR;
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                continue;
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            tzids->reset(status);
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const UnicodeString *tzid;
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            while ((tzid = tzids->snext(status))) {
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                TimeZone *tz = TimeZone::createTimeZone(*tzid);
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                for (int32_t datidx = 0; datidx < nDates; datidx++) {
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UnicodeString tzstr;
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    FieldPosition fpos(0);
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Format
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    sdf->setTimeZone(*tz);
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    sdf->format(DATES[datidx], tzstr, fpos);
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Before parse, set unknown zone to SimpleDateFormat instance
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // just for making sure that it does not depends on the time zone
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // originally set.
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    sdf->setTimeZone(unknownZone);
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Parse
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    ParsePosition pos(0);
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    Calendar *outcal = Calendar::createInstance(unknownZone, status);
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (U_FAILURE(status)) {
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        errln("Failed to create an instance of calendar for receiving parse result.");
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        status = U_ZERO_ERROR;
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        continue;
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    outcal->set(UCAL_DST_OFFSET, badDstOffset);
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    outcal->set(UCAL_ZONE_OFFSET, badZoneOffset);
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    sdf->parse(tzstr, *outcal, pos);
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // Check the result
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    const TimeZone &outtz = outcal->getTimeZone();
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    UnicodeString outtzid;
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    outtz.getID(outtzid);
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    tz->getOffset(DATES[datidx], false, inRaw, inDst, status);
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (U_FAILURE(status)) {
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        errln((UnicodeString)"Failed to get offsets from time zone" + *tzid);
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        status = U_ZERO_ERROR;
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    outtz.getOffset(DATES[datidx], false, outRaw, outDst, status);
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    if (U_FAILURE(status)) {
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        errln((UnicodeString)"Failed to get offsets from time zone" + outtzid);
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        status = U_ZERO_ERROR;
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    if (uprv_strcmp(PATTERNS[patidx], "V") == 0) {
2208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        // Short zone ID - should support roundtrip for canonical CLDR IDs
2218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        UnicodeString canonicalID;
2228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        TimeZone::getCanonicalID(*tzid, canonicalID, status);
2238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        if (U_FAILURE(status)) {
2248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            // Uknown ID - we should not get here
2258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            errln((UnicodeString)"Unknown ID " + *tzid);
2268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            status = U_ZERO_ERROR;
2278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        } else if (outtzid != canonicalID) {
2288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            if (outtzid.compare(ETC_UNKNOWN, -1) == 0) {
2298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                // Note that some zones like Asia/Riyadh87 does not have
2308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                // short zone ID and "unk" is used as fallback
2318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                logln((UnicodeString)"Canonical round trip failed (probably as expected); tz=" + *tzid
2328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                        + ", locale=" + LOCALES[locidx].getName() + ", pattern=" + PATTERNS[patidx]
2338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                        + ", time=" + DATES[datidx] + ", str=" + tzstr
2348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                        + ", outtz=" + outtzid);
2358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            } else {
2368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                errln((UnicodeString)"Canonical round trip failed; tz=" + *tzid
2378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                    + ", locale=" + LOCALES[locidx].getName() + ", pattern=" + PATTERNS[patidx]
2388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                    + ", time=" + DATES[datidx] + ", str=" + tzstr
2398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                    + ", outtz=" + outtzid);
2408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            }
2418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        }
2428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    } else if (uprv_strcmp(PATTERNS[patidx], "VV") == 0) {
2438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        // Zone ID - full roundtrip support
2448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        if (outtzid != *tzid) {
2458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            errln((UnicodeString)"Zone ID round trip failued; tz="  + *tzid
2468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                + ", locale=" + LOCALES[locidx].getName() + ", pattern=" + PATTERNS[patidx]
2478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                + ", time=" + DATES[datidx] + ", str=" + tzstr
2488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                + ", outtz=" + outtzid);
2498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        }
2508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    } else if (uprv_strcmp(PATTERNS[patidx], "VVV") == 0 || uprv_strcmp(PATTERNS[patidx], "VVVV") == 0) {
251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        // Location: time zone rule must be preserved except
252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        // zones not actually associated with a specific location.
253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        // Time zones in this category do not have "/" in its ID.
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        UnicodeString canonical;
255c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        TimeZone::getCanonicalID(*tzid, canonical, status);
256c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        if (U_FAILURE(status)) {
257c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                            // Uknown ID - we should not get here
258c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                            errln((UnicodeString)"Unknown ID " + *tzid);
259c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                            status = U_ZERO_ERROR;
260c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        } else if (outtzid != canonical) {
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            // Canonical ID did not match - check the rules
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            if (!((BasicTimeZone*)&outtz)->hasEquivalentTransitions((BasicTimeZone&)*tz, low, high, TRUE, status)) {
263b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                if (canonical.indexOf((UChar)0x27 /*'/'*/) == -1) {
264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                    // Exceptional cases, such as CET, EET, MET and WET
2658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                    logln((UnicodeString)"Canonical round trip failed (as expected); tz=" + *tzid
266b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                            + ", locale=" + LOCALES[locidx].getName() + ", pattern=" + PATTERNS[patidx]
267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                            + ", time=" + DATES[datidx] + ", str=" + tzstr
268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                            + ", outtz=" + outtzid);
269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                } else {
2708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                    errln((UnicodeString)"Canonical round trip failed; tz=" + *tzid
271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                        + ", locale=" + LOCALES[locidx].getName() + ", pattern=" + PATTERNS[patidx]
272b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                        + ", time=" + DATES[datidx] + ", str=" + tzstr
273b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                        + ", outtz=" + outtzid);
274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                }
275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                if (U_FAILURE(status)) {
276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                    errln("hasEquivalentTransitions failed");
277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                    status = U_ZERO_ERROR;
278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                }
279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            }
280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        }
281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                    } else {
2838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        UBool isOffsetFormat = (*PATTERNS[patidx] == 'Z'
2848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                                || *PATTERNS[patidx] == 'O'
2858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                                || *PATTERNS[patidx] == 'X'
2868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                                || *PATTERNS[patidx] == 'x');
2878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        UBool minutesOffset = FALSE;
2888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        if (*PATTERNS[patidx] == 'X' || *PATTERNS[patidx] == 'x') {
2898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            minutesOffset = (uprv_strlen(PATTERNS[patidx]) <= 3);
2908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        }
2918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
292103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        if (!isOffsetFormat) {
293103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                            // Check if localized GMT format is used as a fallback of name styles
294103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                            int32_t numDigits = 0;
295103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                            for (int n = 0; n < tzstr.length(); n++) {
296103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                if (u_isdigit(tzstr.charAt(n))) {
297103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                    numDigits++;
298103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                }
299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            }
3008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            isOffsetFormat = (numDigits > 0);
301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        }
302103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                        if (isOffsetFormat || tzstr == localGMTString) {
3038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            // Localized GMT or ISO: total offset (raw + dst) must be preserved.
304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            int32_t inOffset = inRaw + inDst;
305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            int32_t outOffset = outRaw + outDst;
3068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            int32_t diff = outOffset - inOffset;
3078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            if (minutesOffset) {
3088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                diff = (diff / 60000) * 60000;
3098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            }
3108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            if (diff != 0) {
311b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                errln((UnicodeString)"Offset round trip failed; tz=" + *tzid
312b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    + ", locale=" + LOCALES[locidx].getName() + ", pattern=" + PATTERNS[patidx]
313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                    + ", time=" + DATES[datidx] + ", str=" + tzstr
314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                    + ", inOffset=" + inOffset + ", outOffset=" + outOffset);
315b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                        } else {
317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            // Specific or generic: raw offset must be preserved.
318b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                            if (inRaw != outRaw) {
319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                errln((UnicodeString)"Raw offset round trip failed; tz=" + *tzid
320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                    + ", locale=" + LOCALES[locidx].getName() + ", pattern=" + PATTERNS[patidx]
321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                    + ", time=" + DATES[datidx] + ", str=" + tzstr
322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                                    + ", inRawOffset=" + inRaw + ", outRawOffset=" + outRaw);
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                            }
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        }
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    delete outcal;
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete tz;
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete sdf;
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete cal;
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete tzids;
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
33750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostruct LocaleData {
33850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t index;
33950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t testCounts;
34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UDate *times;
34150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const Locale* locales; // Static
34250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t nLocales; // Static
34350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UBool quick; // Static
34450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UDate START_TIME; // Static
34550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UDate END_TIME; // Static
34650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t numDone;
34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho};
34850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
34950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoclass TestTimeRoundTripThread: public SimpleThread {
35050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehopublic:
35150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    TestTimeRoundTripThread(IntlTest& tlog, LocaleData &ld, int32_t i)
35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        : log(tlog), data(ld), index(i) {}
35350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    virtual void run() {
35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UErrorCode status = U_ZERO_ERROR;
35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UBool REALLY_VERBOSE = FALSE;
35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
3578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // These patterns are ambiguous at DST->STD local time overlap
3588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        const char* AMBIGUOUS_DST_DECESSION[] = { "v", "vvvv", "V", "VV", "VVV", "VVVV", 0 };
3598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
3608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // These patterns are ambiguous at STD->STD/DST->DST local time overlap
3618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        const char* AMBIGUOUS_NEGATIVE_SHIFT[] = { "z", "zzzz", "v", "vvvv", "V", "VV", "VVV", "VVVV", 0 };
3628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
3638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // These patterns only support integer minutes offset
3648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        const char* MINUTES_OFFSET[] = { "X", "XX", "XXX", "x", "xx", "xxx", 0 };
36550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
36650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        // Workaround for #6338
36750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        //UnicodeString BASEPATTERN("yyyy-MM-dd'T'HH:mm:ss.SSS");
36850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UnicodeString BASEPATTERN("yyyy.MM.dd HH:mm:ss.SSS");
36950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
37050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        // timer for performance analysis
37150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UDate timer;
37250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UDate testTimes[4];
37350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UBool expectedRoundTrip[4];
37450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t testLen = 0;
37550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        StringEnumeration *tzids = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status);
37750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (U_FAILURE(status)) {
378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (status == U_MISSING_RESOURCE_ERROR) {
379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                /* This error is generally caused by data not being present. However, an infinite loop will occur
380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                 * because the thread thinks that the test data is never done so we should treat the data as done.
381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                 */
382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                log.dataerrln("TimeZone::createTimeZoneIDEnumeration failed - %s", u_errorName(status));
383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                data.numDone = data.nLocales;
384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                log.errln("TimeZone::createTimeZoneIDEnumeration failed: %s", u_errorName(status));
386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
38750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return;
38850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
39050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t locidx = -1;
39150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UDate times[NUM_PATTERNS];
39250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        for (int32_t i = 0; i < NUM_PATTERNS; i++) {
39350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            times[i] = 0;
39450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
39550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
39650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t testCounts = 0;
39750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
39850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        while (true) {
39950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            umtx_lock(NULL); // Lock to increment the index
40050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            for (int32_t i = 0; i < NUM_PATTERNS; i++) {
40150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                data.times[i] += times[i];
40250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                data.testCounts += testCounts;
40350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
40450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if (data.index < data.nLocales) {
40550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                locidx = data.index;
40650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                data.index++;
40750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            } else {
40850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                locidx = -1;
40950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
41050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            umtx_unlock(NULL); // Unlock for other threads to use
41150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
41250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if (locidx == -1) {
41350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                log.logln((UnicodeString) "Thread " + index + " is done.");
41450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                break;
41550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
41650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
41750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            log.logln((UnicodeString) "\nThread " + index + ": Locale: " + UnicodeString(data.locales[locidx].getName()));
41850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
41950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            for (int32_t patidx = 0; patidx < NUM_PATTERNS; patidx++) {
42050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                log.logln((UnicodeString) "    Pattern: " + PATTERNS[patidx]);
42150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                times[patidx] = 0;
42250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
42350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                UnicodeString pattern(BASEPATTERN);
42450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                pattern.append(" ").append(PATTERNS[patidx]);
42550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
42650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                SimpleDateFormat *sdf = new SimpleDateFormat(pattern, data.locales[locidx], status);
42750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if (U_FAILURE(status)) {
42850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    log.errcheckln(status, (UnicodeString) "new SimpleDateFormat failed for pattern " +
42950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        pattern + " for locale " + data.locales[locidx].getName() + " - " + u_errorName(status));
43050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    status = U_ZERO_ERROR;
43150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    continue;
43250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
43350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
4348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                UBool minutesOffset = contains(MINUTES_OFFSET, PATTERNS[patidx]);
4358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
43650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                tzids->reset(status);
43750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                const UnicodeString *tzid;
43850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
43950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                timer = Calendar::getNow();
44050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
44150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                while ((tzid = tzids->snext(status))) {
4428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    if (uprv_strcmp(PATTERNS[patidx], "V") == 0) {
4438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        // Some zones do not have short ID assigned, such as Asia/Riyadh87.
4448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        // The time roundtrip will fail for such zones with pattern "V" (short zone ID).
4458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        // This is expected behavior.
4468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        const UChar* shortZoneID = ZoneMeta::getShortID(*tzid);
4478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        if (shortZoneID == NULL) {
4488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            continue;
4498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        }
4508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    } else if (uprv_strcmp(PATTERNS[patidx], "VVV") == 0) {
4518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        // Some zones are not associated with any region, such as Etc/GMT+8.
4528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        // The time roundtrip will fail for such zone with pattern "VVV" (exemplar location).
4538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        // This is expected behavior.
4548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        if (tzid->indexOf((UChar)0x2F) < 0 || tzid->indexOf(ETC_SLASH, -1, 0) >= 0
4558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            || tzid->indexOf(SYSTEMV_SLASH, -1, 0) >= 0 || tzid->indexOf(RIYADH8, -1, 0) >= 0) {
4568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            continue;
4578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        }
4588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    }
4598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
46050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    BasicTimeZone *tz = (BasicTimeZone*) TimeZone::createTimeZone(*tzid);
46150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    sdf->setTimeZone(*tz);
46250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
46350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    UDate t = data.START_TIME;
46450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    TimeZoneTransition tzt;
46550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    UBool tztAvail = FALSE;
46650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    UBool middle = TRUE;
46750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
46850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    while (t < data.END_TIME) {
46950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        if (!tztAvail) {
47050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            testTimes[0] = t;
47150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            expectedRoundTrip[0] = TRUE;
47250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            testLen = 1;
47350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        } else {
47450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            int32_t fromOffset = tzt.getFrom()->getRawOffset() + tzt.getFrom()->getDSTSavings();
47550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            int32_t toOffset = tzt.getTo()->getRawOffset() + tzt.getTo()->getDSTSavings();
47650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            int32_t delta = toOffset - fromOffset;
47750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            if (delta < 0) {
47850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                UBool isDstDecession = tzt.getFrom()->getDSTSavings() > 0 && tzt.getTo()->getDSTSavings() == 0;
47950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                testTimes[0] = t + delta - 1;
48050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                expectedRoundTrip[0] = TRUE;
48150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                testTimes[1] = t + delta;
4828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                expectedRoundTrip[1] = isDstDecession ?
4838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                    !contains(AMBIGUOUS_DST_DECESSION, PATTERNS[patidx]) :
4848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                    !contains(AMBIGUOUS_NEGATIVE_SHIFT, PATTERNS[patidx]);
48550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                testTimes[2] = t - 1;
4868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                expectedRoundTrip[2] = isDstDecession ?
4878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                    !contains(AMBIGUOUS_DST_DECESSION, PATTERNS[patidx]) :
4888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                    !contains(AMBIGUOUS_NEGATIVE_SHIFT, PATTERNS[patidx]);
48950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                testTimes[3] = t;
49050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                expectedRoundTrip[3] = TRUE;
49150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                testLen = 4;
49250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            } else {
49350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                testTimes[0] = t - 1;
49450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                expectedRoundTrip[0] = TRUE;
49550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                testTimes[1] = t;
49650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                expectedRoundTrip[1] = TRUE;
49750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                testLen = 2;
49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            }
49950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        }
50050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        for (int32_t testidx = 0; testidx < testLen; testidx++) {
50150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            if (data.quick) {
50250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                // reduce regular test time
50350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                if (!expectedRoundTrip[testidx]) {
50450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                    continue;
50550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                }
50650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            }
50750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
50850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            testCounts++;
50950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
51050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            UnicodeString text;
51150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            FieldPosition fpos(0);
51250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            sdf->format(testTimes[testidx], text, fpos);
51350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
51450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            UDate parsedDate = sdf->parse(text, status);
51550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            if (U_FAILURE(status)) {
51650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                log.errln((UnicodeString) "Parse failure for text=" + text + ", tzid=" + *tzid + ", locale=" + data.locales[locidx].getName()
51750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                        + ", pattern=" + PATTERNS[patidx] + ", time=" + testTimes[testidx]);
51850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                status = U_ZERO_ERROR;
51950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                continue;
52050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            }
5218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
5228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            int32_t timeDiff = (int32_t)(parsedDate - testTimes[testidx]);
5238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            UBool bTimeMatch = minutesOffset ?
5248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                                (timeDiff/60000)*60000 == 0 : timeDiff == 0;
5258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                            if (!bTimeMatch) {
52650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                UnicodeString msg = (UnicodeString) "Time round trip failed for " + "tzid=" + *tzid + ", locale=" + data.locales[locidx].getName() + ", pattern=" + PATTERNS[patidx]
52750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                        + ", text=" + text + ", time=" + testTimes[testidx] + ", restime=" + parsedDate + ", diff=" + (parsedDate - testTimes[testidx]);
528103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                                // Timebomb for TZData update
52950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                if (expectedRoundTrip[testidx]) {
53050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                    log.errln((UnicodeString) "FAIL: " + msg);
53150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                } else if (REALLY_VERBOSE) {
53250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                    log.logln(msg);
53350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                                }
53450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            }
53550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        }
53650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        tztAvail = tz->getNextTransition(t, FALSE, tzt);
53750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        if (!tztAvail) {
53850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            break;
53950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        }
54050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        if (middle) {
54150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            // Test the date in the middle of two transitions.
54250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            t += (int64_t) ((tzt.getTime() - t) / 2);
54350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            middle = FALSE;
54450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            tztAvail = FALSE;
54550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        } else {
54650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                            t = tzt.getTime();
54750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                        }
54850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    }
54950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    delete tz;
55050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
55150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                times[patidx] += (Calendar::getNow() - timer);
55250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                delete sdf;
55350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
55450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            umtx_lock(NULL);
55550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            data.numDone++;
55650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            umtx_unlock(NULL);
55750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
55850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        delete tzids;
55950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
56050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoprivate:
56150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    IntlTest& log;
56250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    LocaleData& data;
56350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t index;
56450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho};
56550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZoneFormatTest::TestTimeRoundTrip(void) {
56850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t nThreads = threadCount;
56950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const Locale *LOCALES;
57050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t nLocales;
57150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t testCounts = 0;
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
57350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UErrorCode status = U_ZERO_ERROR;
57450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    Calendar *cal = Calendar::createInstance(TimeZone::createTimeZone((UnicodeString) "UTC"), status);
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
57650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        dataerrln("Calendar::createInstance failed: %s", u_errorName(status));
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
580b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    const char* testAllProp = getProperty("TimeZoneRoundTripAll");
581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    UBool bTestAll = (testAllProp && uprv_strcmp(testAllProp, "true") == 0);
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
58350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UDate START_TIME, END_TIME;
584b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (bTestAll || !quick) {
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        cal->set(1900, UCAL_JANUARY, 1);
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
587b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        cal->set(1990, UCAL_JANUARY, 1);
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    START_TIME = cal->getTime(status);
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    cal->set(2015, UCAL_JANUARY, 1);
592b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    END_TIME = cal->getTime(status);
59350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
594b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(status)) {
595b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        errln("getTime failed");
596b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
597b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
598b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
599b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate times[NUM_PATTERNS];
600b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i = 0; i < NUM_PATTERNS; i++) {
601b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        times[i] = 0;
602b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
603b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
604b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Set up test locales
60550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const Locale locales1[] = {Locale("en")};
606b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const Locale locales2[] = {
607b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        Locale("ar_EG"), Locale("bg_BG"), Locale("ca_ES"), Locale("da_DK"), Locale("de"),
608b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        Locale("de_DE"), Locale("el_GR"), Locale("en"), Locale("en_AU"), Locale("en_CA"),
609b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        Locale("en_US"), Locale("es"), Locale("es_ES"), Locale("es_MX"), Locale("fi_FI"),
610b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        Locale("fr"), Locale("fr_CA"), Locale("fr_FR"), Locale("he_IL"), Locale("hu_HU"),
611b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        Locale("it"), Locale("it_IT"), Locale("ja"), Locale("ja_JP"), Locale("ko"),
612b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        Locale("ko_KR"), Locale("nb_NO"), Locale("nl_NL"), Locale("nn_NO"), Locale("pl_PL"),
613b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        Locale("pt"), Locale("pt_BR"), Locale("pt_PT"), Locale("ru_RU"), Locale("sv_SE"),
614b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        Locale("th_TH"), Locale("tr_TR"), Locale("zh"), Locale("zh_Hans"), Locale("zh_Hans_CN"),
615b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        Locale("zh_Hant"), Locale("zh_Hant_TW")
616b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    };
617b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
618b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru    if (bTestAll) {
619b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LOCALES = Locale::getAvailableLocales(nLocales);
620b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else if (quick) {
621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LOCALES = locales1;
622b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        nLocales = sizeof(locales1)/sizeof(Locale);
623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
624b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        LOCALES = locales2;
625b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        nLocales = sizeof(locales2)/sizeof(Locale);
626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
627b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
62850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    LocaleData data;
62950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    data.index = 0;
63050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    data.testCounts = testCounts;
63150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    data.times = times;
63250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    data.locales = LOCALES;
63350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    data.nLocales = nLocales;
63450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    data.quick = quick;
63550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    data.START_TIME = START_TIME;
63650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    data.END_TIME = END_TIME;
63750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    data.numDone = 0;
63850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
63950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if (ICU_USE_THREADS==0)
64050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    TestTimeRoundTripThread fakeThread(*this, data, 0);
64150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    fakeThread.run();
64250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#else
64350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    TestTimeRoundTripThread **threads = new TestTimeRoundTripThread*[threadCount];
64450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t i;
64550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    for (i = 0; i < nThreads; i++) {
64650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        threads[i] = new TestTimeRoundTripThread(*this, data, i);
64750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (threads[i]->start() != 0) {
64850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            errln("Error starting thread %d", i);
64950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
65250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UBool done = false;
65350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    while (true) {
65450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        umtx_lock(NULL);
65550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (data.numDone == nLocales) {
65650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            done = true;
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
65850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        umtx_unlock(NULL);
65950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (done)
66050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            break;
66150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        SimpleThread::sleep(1000);
66250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
66350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
66450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    for (i = 0; i < nThreads; i++) {
66550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        delete threads[i];
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
66750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    delete [] threads;
66850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
66950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UDate total = 0;
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    logln("### Elapsed time by patterns ###");
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t i = 0; i < NUM_PATTERNS; i++) {
67350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        logln(UnicodeString("") + data.times[i] + "ms (" + PATTERNS[i] + ")");
67450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        total += data.times[i];
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
67650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    logln((UnicodeString) "Total: " + total + "ms");
67750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    logln((UnicodeString) "Iteration: " + data.testCounts);
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete cal;
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
6828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliustypedef struct {
6848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const char*     text;
6858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    int32_t         inPos;
6868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const char*     locale;
6878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UTimeZoneFormatStyle    style;
6888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UBool           parseAll;
6898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const char*     expected;
6908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    int32_t         outPos;
6918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UTimeZoneFormatTimeType timeType;
6928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius} ParseTestData;
6938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
6948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusvoid
6958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusTimeZoneFormatTest::TestParse(void) {
6968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const ParseTestData DATA[] = {
6978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        //   text               inPos   locale      style                               parseAll    expected            outPos  timeType
6988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"Z",               0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,     false,      "Etc/GMT",          1,      UTZFMT_TIME_TYPE_UNKNOWN},
6998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"Z",               0,      "en_US",    UTZFMT_STYLE_SPECIFIC_LONG,         false,      "Etc/GMT",          1,      UTZFMT_TIME_TYPE_UNKNOWN},
7008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"Zambia time",     0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,     true,       "Etc/GMT",          1,      UTZFMT_TIME_TYPE_UNKNOWN},
7018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"Zambia time",     0,      "en_US",    UTZFMT_STYLE_GENERIC_LOCATION,      false,      "Africa/Lusaka",    11,     UTZFMT_TIME_TYPE_UNKNOWN},
7028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"Zambia time",     0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,  true,       "Africa/Lusaka",    11,     UTZFMT_TIME_TYPE_UNKNOWN},
7038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"+00:00",          0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,     false,      "Etc/GMT",          6,      UTZFMT_TIME_TYPE_UNKNOWN},
7048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"-01:30:45",       0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,     false,      "GMT-01:30:45",     9,      UTZFMT_TIME_TYPE_UNKNOWN},
7058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"-7",              0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,  false,      "GMT-07:00",        2,      UTZFMT_TIME_TYPE_UNKNOWN},
7068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"-2222",           0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,  false,      "GMT-22:22",        5,      UTZFMT_TIME_TYPE_UNKNOWN},
7078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"-3333",           0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,  false,      "GMT-03:33",        4,      UTZFMT_TIME_TYPE_UNKNOWN},
7088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"XXX+01:30YYY",    3,      "en_US",    UTZFMT_STYLE_LOCALIZED_GMT,         false,      "GMT+01:30",        9,      UTZFMT_TIME_TYPE_UNKNOWN},
7098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"GMT0",            0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,        false,      "Etc/GMT",          3,      UTZFMT_TIME_TYPE_UNKNOWN},
7108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"EST",             0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,        false,      "America/New_York", 3,      UTZFMT_TIME_TYPE_STANDARD},
7118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"ESTx",            0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,        false,      "America/New_York", 3,      UTZFMT_TIME_TYPE_STANDARD},
7128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"EDTx",            0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,        false,      "America/New_York", 3,      UTZFMT_TIME_TYPE_DAYLIGHT},
7138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"EST",             0,      "en_US",    UTZFMT_STYLE_SPECIFIC_LONG,         false,      NULL,               0,      UTZFMT_TIME_TYPE_UNKNOWN},
7148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"EST",             0,      "en_US",    UTZFMT_STYLE_SPECIFIC_LONG,         true,       "America/New_York", 3,      UTZFMT_TIME_TYPE_STANDARD},
7158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {"EST",             0,      "en_CA",    UTZFMT_STYLE_SPECIFIC_SHORT,        false,      "America/Toronto",  3,      UTZFMT_TIME_TYPE_STANDARD},
7168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            {NULL,              0,      NULL,       UTZFMT_STYLE_GENERIC_LOCATION,      false,      NULL,               0,      UTZFMT_TIME_TYPE_UNKNOWN}
7178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    };
7188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    for (int32_t i = 0; DATA[i].text; i++) {
7208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        UErrorCode status = U_ZERO_ERROR;
7218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(Locale(DATA[i].locale), status));
7228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if (U_FAILURE(status)) {
7238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            dataerrln("Fail TimeZoneFormat::createInstance: %s", u_errorName(status));
7248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            continue;
7258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
7268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        UTimeZoneFormatTimeType ttype = UTZFMT_TIME_TYPE_UNKNOWN;
7278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        ParsePosition pos(DATA[i].inPos);
7288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        int32_t parseOptions = DATA[i].parseAll ? UTZFMT_PARSE_OPTION_ALL_STYLES : UTZFMT_PARSE_OPTION_NONE;
7298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        TimeZone* tz = tzfmt->parse(DATA[i].style, DATA[i].text, pos, parseOptions, &ttype);
7308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        UnicodeString errMsg;
7328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if (tz) {
7338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            UnicodeString outID;
7348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            tz->getID(outID);
7358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (outID != UnicodeString(DATA[i].expected)) {
7368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                errMsg = (UnicodeString)"Time zone ID: " + outID + " - expected: " + DATA[i].expected;
7378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            } else if (pos.getIndex() != DATA[i].outPos) {
7388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                errMsg = (UnicodeString)"Parsed pos: " + pos.getIndex() + " - expected: " + DATA[i].outPos;
7398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            } else if (ttype != DATA[i].timeType) {
7408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                errMsg = (UnicodeString)"Time type: " + ttype + " - expected: " + DATA[i].timeType;
7418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
7428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            delete tz;
7438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        } else {
7448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (DATA[i].expected) {
7458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                errln((UnicodeString)"Fail: Parse failure - expected: " + DATA[i].expected);
7468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
7478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
7488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        if (errMsg.length() > 0) {
7498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            errln((UnicodeString)"Fail: " + errMsg + " [text=" + DATA[i].text + ", pos=" + DATA[i].inPos + ", style=" + DATA[i].style + "]");
7508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
7518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
7528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
7538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusvoid
7558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusTimeZoneFormatTest::TestISOFormat(void) {
7568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const int32_t OFFSET[] = {
7578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        0,          // 0
7588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        999,        // 0.999s
7598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        -59999,     // -59.999s
7608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        60000,      // 1m
7618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        -77777,     // -1m 17.777s
7628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        1800000,    // 30m
7638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        -3600000,   // -1h
7648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        36000000,   // 10h
7658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        -37800000,  // -10h 30m
7668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        -37845000,  // -10h 30m 45s
7678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        108000000,  // 30h
7688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    };
7698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
7708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const char* ISO_STR[][11] = {
7718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // 0
7728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
7738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "Z", "Z", "Z", "Z", "Z",
7748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+00", "+0000", "+00:00", "+0000", "+00:00",
7758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+0000"
7768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        },
7778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // 999
7788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
7798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "Z", "Z", "Z", "Z", "Z",
7808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+00", "+0000", "+00:00", "+0000", "+00:00",
7818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+0000"
7828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        },
7838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // -59999
7848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
7858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "Z", "Z", "Z", "-000059", "-00:00:59",
7868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+00", "+0000", "+00:00", "-000059", "-00:00:59",
7878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-000059"
7888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        },
7898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // 60000
7908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
7918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+0001", "+0001", "+00:01", "+0001", "+00:01",
7928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+0001", "+0001", "+00:01", "+0001", "+00:01",
7938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+0001"
7948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        },
7958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // -77777
7968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
7978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-0001", "-0001", "-00:01", "-000117", "-00:01:17",
7988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-0001", "-0001", "-00:01", "-000117", "-00:01:17",
7998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-000117"
8008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        },
8018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // 1800000
8028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
8038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+0030", "+0030", "+00:30", "+0030", "+00:30",
8048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+0030", "+0030", "+00:30", "+0030", "+00:30",
8058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+0030"
8068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        },
8078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // -3600000
8088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
8098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-01", "-0100", "-01:00", "-0100", "-01:00",
8108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-01", "-0100", "-01:00", "-0100", "-01:00",
8118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-0100"
8128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        },
8138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // 36000000
8148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
8158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+10", "+1000", "+10:00", "+1000", "+10:00",
8168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+10", "+1000", "+10:00", "+1000", "+10:00",
8178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "+1000"
8188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        },
8198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // -37800000
8208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
8218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-1030", "-1030", "-10:30", "-1030", "-10:30",
8228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-1030", "-1030", "-10:30", "-1030", "-10:30",
8238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-1030"
8248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        },
8258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // -37845000
8268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
8278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-1030", "-1030", "-10:30", "-103045", "-10:30:45",
8288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-1030", "-1030", "-10:30", "-103045", "-10:30:45",
8298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            "-103045"
8308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        },
8318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        // 108000000
8328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        {
8338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            0, 0, 0, 0, 0,
8348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            0, 0, 0, 0, 0,
8358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            0
8368393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
8378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    };
8388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
8398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const char* PATTERN[] = {
8408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        "X", "XX", "XXX", "XXXX", "XXXXX",
8418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        "x", "xx", "xxx", "xxxx", "xxxxx",
8428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        "Z", // equivalent to "xxxx"
8438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        0
8448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    };
8458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
8468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    const int32_t MIN_OFFSET_UNIT[] = {
8478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        60000, 60000, 60000, 1000, 1000,
8488393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        60000, 60000, 60000, 1000, 1000,
8498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        1000,
8508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    };
8518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
8528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // Formatting
8538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UErrorCode status = U_ZERO_ERROR;
8548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    LocalPointer<SimpleDateFormat> sdf(new SimpleDateFormat(status));
8558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (U_FAILURE(status)) {
8568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
8578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return;
8588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
8598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    UDate d = Calendar::getNow();
8608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
8618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    for (uint32_t i = 0; i < sizeof(OFFSET)/sizeof(OFFSET[0]); i++) {
8628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        SimpleTimeZone* tz = new SimpleTimeZone(OFFSET[i], UnicodeString("Zone Offset:") + OFFSET[i] + "ms");
8638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        sdf->adoptTimeZone(tz);
8648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        for (int32_t j = 0; PATTERN[j] != 0; j++) {
8658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            sdf->applyPattern(UnicodeString(PATTERN[j]));
8668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            UnicodeString result;
8678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            sdf->format(d, result);
8688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
8698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (ISO_STR[i][j]) {
8708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                if (result != UnicodeString(ISO_STR[i][j])) {
8718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    errln((UnicodeString)"FAIL: pattern=" + PATTERN[j] + ", offset=" + OFFSET[i] + " -> "
8728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        + result + " (expected: " + ISO_STR[i][j] + ")");
8738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                }
8748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            } else {
8758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                // Offset out of range
8768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                // Note: for now, there is no way to propagate the error status through
8778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                // the SimpleDateFormat::format above.
8788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                if (result.length() > 0) {
8798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    errln((UnicodeString)"FAIL: Non-Empty result for pattern=" + PATTERN[j] + ", offset=" + OFFSET[i]
8808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                        + " (expected: empty result)");
8818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                }
8828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
8838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
8848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
8858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
8868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    // Parsing
8878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    LocalPointer<Calendar> outcal(Calendar::createInstance(status));
8888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    if (U_FAILURE(status)) {
8898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        dataerrln("Fail new Calendar: %s", u_errorName(status));
8908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        return;
8918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
8928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    for (int32_t i = 0; ISO_STR[i][0] != NULL; i++) {
8938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        for (int32_t j = 0; PATTERN[j] != 0; j++) {
8948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (ISO_STR[i][j] == 0) {
8958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                continue;
8968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
8978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            ParsePosition pos(0);
8988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            SimpleTimeZone* bogusTZ = new SimpleTimeZone(-1, UnicodeString("Zone Offset: -1ms"));
8998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            outcal->adoptTimeZone(bogusTZ);
9008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            sdf->applyPattern(PATTERN[j]);
9018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
9028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            sdf->parse(UnicodeString(ISO_STR[i][j]), *(outcal.getAlias()), pos);
9038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
9048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (pos.getIndex() != (int32_t)uprv_strlen(ISO_STR[i][j])) {
9058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                errln((UnicodeString)"FAIL: Failed to parse the entire input string: " + ISO_STR[i][j]);
9068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
9078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
9088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            const TimeZone& outtz = outcal->getTimeZone();
9098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            int32_t outOffset = outtz.getRawOffset();
9108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            int32_t adjustedOffset = OFFSET[i] / MIN_OFFSET_UNIT[j] * MIN_OFFSET_UNIT[j];
9118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (outOffset != adjustedOffset) {
9128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                errln((UnicodeString)"FAIL: Incorrect offset:" + outOffset + "ms for input string: " + ISO_STR[i][j]
9138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                    + " (expected:" + adjustedOffset + "ms)");
9148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
9158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius        }
9168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius    }
9178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius}
9188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
9198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius
92059d709d503bab6e2b61931737e662dd293b40578ccorneliustypedef struct {
92159d709d503bab6e2b61931737e662dd293b40578ccornelius    const char*     locale;
92259d709d503bab6e2b61931737e662dd293b40578ccornelius    const char*     tzid;
92359d709d503bab6e2b61931737e662dd293b40578ccornelius    UDate           date;
92459d709d503bab6e2b61931737e662dd293b40578ccornelius    UTimeZoneFormatStyle    style;
92559d709d503bab6e2b61931737e662dd293b40578ccornelius    const char*     expected;
92659d709d503bab6e2b61931737e662dd293b40578ccornelius    UTimeZoneFormatTimeType timeType;
92759d709d503bab6e2b61931737e662dd293b40578ccornelius} FormatTestData;
92859d709d503bab6e2b61931737e662dd293b40578ccornelius
92959d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid
93059d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZoneFormatTest::TestFormat(void) {
93159d709d503bab6e2b61931737e662dd293b40578ccornelius    UDate dateJan = 1358208000000.0;    // 2013-01-15T00:00:00Z
93259d709d503bab6e2b61931737e662dd293b40578ccornelius    UDate dateJul = 1373846400000.0;    // 2013-07-15T00:00:00Z
93359d709d503bab6e2b61931737e662dd293b40578ccornelius
93459d709d503bab6e2b61931737e662dd293b40578ccornelius    const FormatTestData DATA[] = {
93559d709d503bab6e2b61931737e662dd293b40578ccornelius        {
93659d709d503bab6e2b61931737e662dd293b40578ccornelius            "en",
93759d709d503bab6e2b61931737e662dd293b40578ccornelius            "America/Los_Angeles",
93859d709d503bab6e2b61931737e662dd293b40578ccornelius            dateJan,
93959d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_STYLE_GENERIC_LOCATION,
94059d709d503bab6e2b61931737e662dd293b40578ccornelius            "Los Angeles Time",
94159d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_TIME_TYPE_UNKNOWN
94259d709d503bab6e2b61931737e662dd293b40578ccornelius        },
94359d709d503bab6e2b61931737e662dd293b40578ccornelius        {
94459d709d503bab6e2b61931737e662dd293b40578ccornelius            "en",
94559d709d503bab6e2b61931737e662dd293b40578ccornelius            "America/Los_Angeles",
94659d709d503bab6e2b61931737e662dd293b40578ccornelius            dateJan,
94759d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_STYLE_GENERIC_LONG,
94859d709d503bab6e2b61931737e662dd293b40578ccornelius            "Pacific Time",
94959d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_TIME_TYPE_UNKNOWN
95059d709d503bab6e2b61931737e662dd293b40578ccornelius        },
95159d709d503bab6e2b61931737e662dd293b40578ccornelius        {
95259d709d503bab6e2b61931737e662dd293b40578ccornelius            "en",
95359d709d503bab6e2b61931737e662dd293b40578ccornelius            "America/Los_Angeles",
95459d709d503bab6e2b61931737e662dd293b40578ccornelius            dateJan,
95559d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_STYLE_SPECIFIC_LONG,
95659d709d503bab6e2b61931737e662dd293b40578ccornelius            "Pacific Standard Time",
95759d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_TIME_TYPE_STANDARD
95859d709d503bab6e2b61931737e662dd293b40578ccornelius        },
95959d709d503bab6e2b61931737e662dd293b40578ccornelius        {
96059d709d503bab6e2b61931737e662dd293b40578ccornelius            "en",
96159d709d503bab6e2b61931737e662dd293b40578ccornelius            "America/Los_Angeles",
96259d709d503bab6e2b61931737e662dd293b40578ccornelius            dateJul,
96359d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_STYLE_SPECIFIC_LONG,
96459d709d503bab6e2b61931737e662dd293b40578ccornelius            "Pacific Daylight Time",
96559d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_TIME_TYPE_DAYLIGHT
96659d709d503bab6e2b61931737e662dd293b40578ccornelius        },
96759d709d503bab6e2b61931737e662dd293b40578ccornelius        {
96859d709d503bab6e2b61931737e662dd293b40578ccornelius            "ja",
96959d709d503bab6e2b61931737e662dd293b40578ccornelius            "America/Los_Angeles",
97059d709d503bab6e2b61931737e662dd293b40578ccornelius            dateJan,
97159d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_STYLE_ZONE_ID,
97259d709d503bab6e2b61931737e662dd293b40578ccornelius            "America/Los_Angeles",
97359d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_TIME_TYPE_UNKNOWN
97459d709d503bab6e2b61931737e662dd293b40578ccornelius        },
97559d709d503bab6e2b61931737e662dd293b40578ccornelius        {
97659d709d503bab6e2b61931737e662dd293b40578ccornelius            "fr",
97759d709d503bab6e2b61931737e662dd293b40578ccornelius            "America/Los_Angeles",
97859d709d503bab6e2b61931737e662dd293b40578ccornelius            dateJul,
97959d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_STYLE_ZONE_ID_SHORT,
98059d709d503bab6e2b61931737e662dd293b40578ccornelius            "uslax",
98159d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_TIME_TYPE_UNKNOWN
98259d709d503bab6e2b61931737e662dd293b40578ccornelius        },
98359d709d503bab6e2b61931737e662dd293b40578ccornelius        {
98459d709d503bab6e2b61931737e662dd293b40578ccornelius            "en",
98559d709d503bab6e2b61931737e662dd293b40578ccornelius            "America/Los_Angeles",
98659d709d503bab6e2b61931737e662dd293b40578ccornelius            dateJan,
98759d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_STYLE_EXEMPLAR_LOCATION,
98859d709d503bab6e2b61931737e662dd293b40578ccornelius            "Los Angeles",
98959d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_TIME_TYPE_UNKNOWN
99059d709d503bab6e2b61931737e662dd293b40578ccornelius        },
99159d709d503bab6e2b61931737e662dd293b40578ccornelius
99259d709d503bab6e2b61931737e662dd293b40578ccornelius        {
99359d709d503bab6e2b61931737e662dd293b40578ccornelius            "ja",
99459d709d503bab6e2b61931737e662dd293b40578ccornelius            "Asia/Tokyo",
99559d709d503bab6e2b61931737e662dd293b40578ccornelius            dateJan,
99659d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_STYLE_GENERIC_LONG,
99759d709d503bab6e2b61931737e662dd293b40578ccornelius            "\\u65E5\\u672C\\u6A19\\u6E96\\u6642",
99859d709d503bab6e2b61931737e662dd293b40578ccornelius            UTZFMT_TIME_TYPE_UNKNOWN
99959d709d503bab6e2b61931737e662dd293b40578ccornelius        },
100059d709d503bab6e2b61931737e662dd293b40578ccornelius
100159d709d503bab6e2b61931737e662dd293b40578ccornelius        {0, 0, 0.0, UTZFMT_STYLE_GENERIC_LOCATION, 0, UTZFMT_TIME_TYPE_UNKNOWN}
100259d709d503bab6e2b61931737e662dd293b40578ccornelius    };
100359d709d503bab6e2b61931737e662dd293b40578ccornelius
100459d709d503bab6e2b61931737e662dd293b40578ccornelius    for (int32_t i = 0; DATA[i].locale; i++) {
100559d709d503bab6e2b61931737e662dd293b40578ccornelius        UErrorCode status = U_ZERO_ERROR;
100659d709d503bab6e2b61931737e662dd293b40578ccornelius        LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(Locale(DATA[i].locale), status));
100759d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_FAILURE(status)) {
100859d709d503bab6e2b61931737e662dd293b40578ccornelius            dataerrln("Fail TimeZoneFormat::createInstance: %s", u_errorName(status));
100959d709d503bab6e2b61931737e662dd293b40578ccornelius            continue;
101059d709d503bab6e2b61931737e662dd293b40578ccornelius        }
101159d709d503bab6e2b61931737e662dd293b40578ccornelius
101259d709d503bab6e2b61931737e662dd293b40578ccornelius        LocalPointer<TimeZone> tz(TimeZone::createTimeZone(DATA[i].tzid));
101359d709d503bab6e2b61931737e662dd293b40578ccornelius        UnicodeString out;
101459d709d503bab6e2b61931737e662dd293b40578ccornelius        UTimeZoneFormatTimeType timeType;
101559d709d503bab6e2b61931737e662dd293b40578ccornelius
101659d709d503bab6e2b61931737e662dd293b40578ccornelius        tzfmt->format(DATA[i].style, *(tz.getAlias()), DATA[i].date, out, &timeType);
101759d709d503bab6e2b61931737e662dd293b40578ccornelius        UnicodeString expected(DATA[i].expected, -1, US_INV);
101859d709d503bab6e2b61931737e662dd293b40578ccornelius        expected = expected.unescape();
101959d709d503bab6e2b61931737e662dd293b40578ccornelius
102059d709d503bab6e2b61931737e662dd293b40578ccornelius        assertEquals(UnicodeString("Format result for ") + DATA[i].tzid + " (Test Case " + i + ")", expected, out);
102159d709d503bab6e2b61931737e662dd293b40578ccornelius        if (DATA[i].timeType != timeType) {
102259d709d503bab6e2b61931737e662dd293b40578ccornelius            dataerrln(UnicodeString("Formatted time zone type (Test Case ") + i + "), returned="
102359d709d503bab6e2b61931737e662dd293b40578ccornelius                + timeType + ", expected=" + DATA[i].timeType);
102459d709d503bab6e2b61931737e662dd293b40578ccornelius        }
102559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
102659d709d503bab6e2b61931737e662dd293b40578ccornelius}
102759d709d503bab6e2b61931737e662dd293b40578ccornelius
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
1029