1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2013, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 ********************************************************************/
6
7#include "unicode/utypes.h"
8
9#if !UCONFIG_NO_FORMATTING
10
11#include "dtfmttst.h"
12#include "unicode/localpointer.h"
13#include "unicode/timezone.h"
14#include "unicode/gregocal.h"
15#include "unicode/smpdtfmt.h"
16#include "unicode/datefmt.h"
17#include "unicode/dtptngen.h"
18#include "unicode/simpletz.h"
19#include "unicode/strenum.h"
20#include "unicode/dtfmtsym.h"
21#include "cmemory.h"
22#include "cstring.h"
23#include "caltest.h"  // for fieldName
24#include <stdio.h> // for sprintf
25
26#if U_PLATFORM_HAS_WIN32_API
27#include "windttst.h"
28#endif
29
30#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
31
32#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
33
34#define ASSERT_OK(status)  if(U_FAILURE(status)) {errcheckln(status, #status " = %s @ %s:%d", u_errorName(status), __FILE__, __LINE__); return; }
35
36// *****************************************************************************
37// class DateFormatTest
38// *****************************************************************************
39
40void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
41{
42    if(exec) {
43        logln("TestSuite DateFormatTest: ");
44    }
45    TESTCASE_AUTO_BEGIN;
46    TESTCASE_AUTO(TestPatterns);
47    TESTCASE_AUTO(TestEquals);
48    TESTCASE_AUTO(TestTwoDigitYearDSTParse);
49    TESTCASE_AUTO(TestFieldPosition);
50    TESTCASE_AUTO(TestPartialParse994);
51    TESTCASE_AUTO(TestRunTogetherPattern985);
52    TESTCASE_AUTO(TestRunTogetherPattern917);
53    TESTCASE_AUTO(TestCzechMonths459);
54    TESTCASE_AUTO(TestLetterDPattern212);
55    TESTCASE_AUTO(TestDayOfYearPattern195);
56    TESTCASE_AUTO(TestQuotePattern161);
57    TESTCASE_AUTO(TestBadInput135);
58    TESTCASE_AUTO(TestBadInput135a);
59    TESTCASE_AUTO(TestTwoDigitYear);
60    TESTCASE_AUTO(TestDateFormatZone061);
61    TESTCASE_AUTO(TestDateFormatZone146);
62    TESTCASE_AUTO(TestLocaleDateFormat);
63    TESTCASE_AUTO(TestWallyWedel);
64    TESTCASE_AUTO(TestDateFormatCalendar);
65    TESTCASE_AUTO(TestSpaceParsing);
66    TESTCASE_AUTO(TestExactCountFormat);
67    TESTCASE_AUTO(TestWhiteSpaceParsing);
68    TESTCASE_AUTO(TestInvalidPattern);
69    TESTCASE_AUTO(TestGeneral);
70    TESTCASE_AUTO(TestGreekMay);
71    TESTCASE_AUTO(TestGenericTime);
72    TESTCASE_AUTO(TestGenericTimeZoneOrder);
73    TESTCASE_AUTO(TestHost);
74    TESTCASE_AUTO(TestEras);
75    TESTCASE_AUTO(TestNarrowNames);
76    TESTCASE_AUTO(TestShortDays);
77    TESTCASE_AUTO(TestStandAloneDays);
78    TESTCASE_AUTO(TestStandAloneMonths);
79    TESTCASE_AUTO(TestQuarters);
80    TESTCASE_AUTO(TestZTimeZoneParsing);
81    TESTCASE_AUTO(TestRelative);
82    TESTCASE_AUTO(TestRelativeClone);
83    TESTCASE_AUTO(TestHostClone);
84    TESTCASE_AUTO(TestTimeZoneDisplayName);
85    TESTCASE_AUTO(TestRoundtripWithCalendar);
86    TESTCASE_AUTO(Test6338);
87    TESTCASE_AUTO(Test6726);
88    TESTCASE_AUTO(TestGMTParsing);
89    TESTCASE_AUTO(Test6880);
90    TESTCASE_AUTO(TestISOEra);
91    TESTCASE_AUTO(TestFormalChineseDate);
92    TESTCASE_AUTO(TestNumberAsStringParsing);
93    TESTCASE_AUTO(TestStandAloneGMTParse);
94    TESTCASE_AUTO(TestParsePosition);
95    TESTCASE_AUTO(TestMonthPatterns);
96    TESTCASE_AUTO(TestContext);
97    TESTCASE_AUTO(TestNonGregoFmtParse);
98    /*
99    TESTCASE_AUTO(TestRelativeError);
100    TESTCASE_AUTO(TestRelativeOther);
101    */
102    TESTCASE_AUTO(TestDotAndAtLeniency);
103    TESTCASE_AUTO(TestDateFormatLeniency);
104    TESTCASE_AUTO_END;
105}
106
107void DateFormatTest::TestPatterns() {
108    static const struct {
109        const char *actualPattern;
110        const char *expectedPattern;
111        const char *localeID;
112        const char *expectedLocalPattern;
113    } EXPECTED[] = {
114        {UDAT_YEAR, "y","en","y"},
115
116        {UDAT_QUARTER, "QQQQ", "en", "QQQQ"},
117        {UDAT_ABBR_QUARTER, "QQQ", "en", "QQQ"},
118        {UDAT_YEAR_QUARTER, "yQQQQ", "en", "QQQQ y"},
119        {UDAT_YEAR_ABBR_QUARTER, "yQQQ", "en", "QQQ y"},
120
121        {UDAT_NUM_MONTH, "M", "en", "L"},
122        {UDAT_ABBR_MONTH, "MMM", "en", "LLL"},
123        {UDAT_MONTH, "MMMM", "en", "LLLL"},
124        {UDAT_YEAR_NUM_MONTH, "yM","en","M/y"},
125        {UDAT_YEAR_ABBR_MONTH, "yMMM","en","MMM y"},
126        {UDAT_YEAR_MONTH, "yMMMM","en","MMMM y"},
127
128        {UDAT_DAY, "d","en","d"},
129        {UDAT_YEAR_NUM_MONTH_DAY, "yMd", "en", "M/d/y"},
130        {UDAT_YEAR_ABBR_MONTH_DAY, "yMMMd", "en", "MMM d, y"},
131        {UDAT_YEAR_MONTH_DAY, "yMMMMd", "en", "MMMM d, y"},
132        {UDAT_YEAR_NUM_MONTH_WEEKDAY_DAY, "yMEd", "en", "EEE, M/d/y"},
133        {UDAT_YEAR_ABBR_MONTH_WEEKDAY_DAY, "yMMMEd", "en", "EEE, MMM d, y"},
134        {UDAT_YEAR_MONTH_WEEKDAY_DAY, "yMMMMEEEEd", "en", "EEEE, MMMM d, y"},
135
136        {UDAT_NUM_MONTH_DAY, "Md","en","M/d"},
137        {UDAT_ABBR_MONTH_DAY, "MMMd","en","MMM d"},
138        {UDAT_MONTH_DAY, "MMMMd","en","MMMM d"},
139        {UDAT_NUM_MONTH_WEEKDAY_DAY, "MEd","en","EEE, M/d"},
140        {UDAT_ABBR_MONTH_WEEKDAY_DAY, "MMMEd","en","EEE, MMM d"},
141        {UDAT_MONTH_WEEKDAY_DAY, "MMMMEEEEd","en","EEEE, MMMM d"},
142
143        {UDAT_HOUR, "j", "en", "h a"}, // (fixed expected result per ticket 6872<-6626)
144        {UDAT_HOUR24, "H", "en", "HH"}, // (fixed expected result per ticket 6872<-6626
145
146        {UDAT_MINUTE, "m", "en", "m"},
147        {UDAT_HOUR_MINUTE, "jm","en","h:mm a"}, // (fixed expected result per ticket 6872<-7180)
148        {UDAT_HOUR24_MINUTE, "Hm", "en", "HH:mm"}, // (fixed expected result per ticket 6872<-6626)
149
150        {UDAT_SECOND, "s", "en", "s"},
151        {UDAT_HOUR_MINUTE_SECOND, "jms","en","h:mm:ss a"}, // (fixed expected result per ticket 6872<-7180)
152        {UDAT_HOUR24_MINUTE_SECOND, "Hms","en","HH:mm:ss"}, // (fixed expected result per ticket 6872<-6626)
153        {UDAT_MINUTE_SECOND, "ms", "en", "mm:ss"}, // (fixed expected result per ticket 6872<-6626)
154
155        {UDAT_LOCATION_TZ, "VVVV", "en", "VVVV"},
156        {UDAT_GENERIC_TZ, "vvvv", "en", "vvvv"},
157        {UDAT_ABBR_GENERIC_TZ, "v", "en", "v"},
158        {UDAT_SPECIFIC_TZ, "zzzz", "en", "zzzz"},
159        {UDAT_ABBR_SPECIFIC_TZ, "z", "en", "z"},
160        {UDAT_ABBR_UTC_TZ, "ZZZZ", "en", "ZZZZ"},
161
162        {UDAT_YEAR_NUM_MONTH_DAY UDAT_ABBR_UTC_TZ, "yMdZZZZ", "en", "M/d/y, ZZZZ"},
163        {UDAT_MONTH_DAY UDAT_LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d, VVVV"}
164    };
165
166    IcuTestErrorCode errorCode(*this, "TestPatterns()");
167    for (int32_t i = 0; i < LENGTHOF(EXPECTED); i++) {
168        // Verify that patterns have the correct values
169        UnicodeString actualPattern(EXPECTED[i].actualPattern, -1, US_INV);
170        UnicodeString expectedPattern(EXPECTED[i].expectedPattern, -1, US_INV);
171        Locale locale(EXPECTED[i].localeID);
172        if (actualPattern != expectedPattern) {
173            errln("FAILURE! Expected pattern: " + expectedPattern +
174                    " but was: " + actualPattern);
175        }
176
177        // Verify that DataFormat instances produced contain the correct
178        // localized patterns
179        // TODO: use DateFormat::getInstanceForSkeleton(), ticket #9029
180        // Java test code:
181        // DateFormat date1 = DateFormat.getPatternInstance(actualPattern,
182        //         locale);
183        // DateFormat date2 = DateFormat.getPatternInstance(Calendar.getInstance(locale),
184        //         actualPattern, locale);
185        LocalPointer<DateTimePatternGenerator> generator(
186                DateTimePatternGenerator::createInstance(locale, errorCode));
187        if(errorCode.logDataIfFailureAndReset("DateTimePatternGenerator::createInstance() failed for locale ID \"%s\"", EXPECTED[i].localeID)) {
188            continue;
189        }
190        UnicodeString pattern = generator->getBestPattern(actualPattern, errorCode);
191        SimpleDateFormat date1(pattern, locale, errorCode);
192        SimpleDateFormat date2(pattern, locale, errorCode);
193        date2.adoptCalendar(Calendar::createInstance(locale, errorCode));
194        if(errorCode.logIfFailureAndReset("DateFormat::getInstanceForSkeleton() failed")) {
195            errln("  for actualPattern \"%s\" & locale ID \"%s\"",
196                  EXPECTED[i].actualPattern, EXPECTED[i].localeID);
197            continue;
198        }
199
200        UnicodeString expectedLocalPattern(EXPECTED[i].expectedLocalPattern, -1, US_INV);
201        UnicodeString actualLocalPattern1;
202        UnicodeString actualLocalPattern2;
203        date1.toLocalizedPattern(actualLocalPattern1, errorCode);
204        date2.toLocalizedPattern(actualLocalPattern2, errorCode);
205        if (actualLocalPattern1 != expectedLocalPattern) {
206            errln("FAILURE! Expected local pattern: " + expectedLocalPattern
207                    + " but was: " + actualLocalPattern1);
208        }
209        if (actualLocalPattern2 != expectedLocalPattern) {
210            errln("FAILURE! Expected local pattern: " + expectedLocalPattern
211                    + " but was: " + actualLocalPattern2);
212        }
213    }
214}
215
216// Test written by Wally Wedel and emailed to me.
217void DateFormatTest::TestWallyWedel()
218{
219    UErrorCode status = U_ZERO_ERROR;
220    /*
221     * Instantiate a TimeZone so we can get the ids.
222     */
223    TimeZone *tz = new SimpleTimeZone(7,"");
224    /*
225     * Computational variables.
226     */
227    int32_t offset, hours, minutes, seconds;
228    /*
229     * Instantiate a SimpleDateFormat set up to produce a full time
230     zone name.
231     */
232    SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)"zzzz", status);
233    /*
234     * A String array for the time zone ids.
235     */
236    int32_t ids_length;
237    StringEnumeration* ids = TimeZone::createEnumeration();
238    if (ids == NULL) {
239        dataerrln("Unable to create TimeZone enumeration.");
240        if (sdf != NULL) {
241            delete sdf;
242        }
243        return;
244    }
245    ids_length = ids->count(status);
246    /*
247     * How many ids do we have?
248     */
249    logln("Time Zone IDs size: %d", ids_length);
250    /*
251     * Column headings (sort of)
252     */
253    logln("Ordinal ID offset(h:m) name");
254    /*
255     * Loop through the tzs.
256     */
257    UDate today = Calendar::getNow();
258    Calendar *cal = Calendar::createInstance(status);
259    for (int32_t i = 0; i < ids_length; i++) {
260        // logln(i + " " + ids[i]);
261        const UnicodeString* id = ids->snext(status);
262        TimeZone *ttz = TimeZone::createTimeZone(*id);
263        // offset = ttz.getRawOffset();
264        cal->setTimeZone(*ttz);
265        cal->setTime(today, status);
266        offset = cal->get(UCAL_ZONE_OFFSET, status) + cal->get(UCAL_DST_OFFSET, status);
267        // logln(i + " " + ids[i] + " offset " + offset);
268        const char* sign = "+";
269        if (offset < 0) {
270            sign = "-";
271            offset = -offset;
272        }
273        hours = offset/3600000;
274        minutes = (offset%3600000)/60000;
275        seconds = (offset%60000)/1000;
276        UnicodeString dstOffset = (UnicodeString)"" + sign + (hours < 10 ? "0" : "") +
277            (int32_t)hours + ":" + (minutes < 10 ? "0" : "") + (int32_t)minutes;
278        if (seconds != 0) {
279            dstOffset = dstOffset + ":" + (seconds < 10 ? "0" : "") + seconds;
280        }
281        /*
282         * Instantiate a date so we can display the time zone name.
283         */
284        sdf->setTimeZone(*ttz);
285        /*
286         * Format the output.
287         */
288        UnicodeString fmtOffset;
289        FieldPosition pos(0);
290        sdf->format(today,fmtOffset, pos);
291        // UnicodeString fmtOffset = tzS.toString();
292        UnicodeString *fmtDstOffset = 0;
293        if (fmtOffset.startsWith("GMT") && fmtOffset.length() != 3)
294        {
295            //fmtDstOffset = fmtOffset->substring(3);
296            fmtDstOffset = new UnicodeString();
297            fmtOffset.extract(3, fmtOffset.length(), *fmtDstOffset);
298        }
299        /*
300         * Show our result.
301         */
302        UBool ok = fmtDstOffset == 0 || *fmtDstOffset == dstOffset;
303        if (ok)
304        {
305            logln(UnicodeString() + i + " " + *id + " " + dstOffset +
306                  " " + fmtOffset +
307                  (fmtDstOffset != 0 ? " ok" : " ?"));
308        }
309        else
310        {
311            errln(UnicodeString() + i + " " + *id + " " + dstOffset +
312                  " " + fmtOffset + " *** FAIL ***");
313        }
314        delete ttz;
315        delete fmtDstOffset;
316    }
317    delete cal;
318    //  delete ids;   // TODO:  BAD API
319    delete ids;
320    delete sdf;
321    delete tz;
322}
323
324// -------------------------------------
325
326/**
327 * Test operator==
328 */
329void
330DateFormatTest::TestEquals()
331{
332    DateFormat* fmtA = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
333    DateFormat* fmtB = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
334    if ( fmtA == NULL || fmtB == NULL){
335        dataerrln("Error calling DateFormat::createDateTimeInstance");
336        delete fmtA;
337        delete fmtB;
338        return;
339    }
340
341    if (!(*fmtA == *fmtB)) errln((UnicodeString)"FAIL");
342    delete fmtA;
343    delete fmtB;
344
345    TimeZone* test = TimeZone::createTimeZone("PDT");
346    delete test;
347}
348
349// -------------------------------------
350
351/**
352 * Test the parsing of 2-digit years.
353 */
354void
355DateFormatTest::TestTwoDigitYearDSTParse(void)
356{
357    UErrorCode status = U_ZERO_ERROR;
358    SimpleDateFormat* fullFmt = new SimpleDateFormat((UnicodeString)"EEE MMM dd HH:mm:ss.SSS zzz yyyy G", status);
359    SimpleDateFormat *fmt = new SimpleDateFormat((UnicodeString)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status);
360    //DateFormat* fmt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, Locale::ENGLISH);
361    UnicodeString* s = new UnicodeString("03-Apr-04 2:20:47 o'clock AM PST", "");
362    TimeZone* defaultTZ = TimeZone::createDefault();
363    TimeZone* PST = TimeZone::createTimeZone("PST");
364    int32_t defaultOffset = defaultTZ->getRawOffset();
365    int32_t PSTOffset = PST->getRawOffset();
366    int32_t hour = 2 + (defaultOffset - PSTOffset) / (60*60*1000);
367    // hour is the expected hour of day, in units of seconds
368    hour = ((hour < 0) ? hour + 24 : hour) * 60*60;
369
370    UnicodeString str;
371
372    if(U_FAILURE(status)) {
373        dataerrln("Could not set up test. exitting - %s", u_errorName(status));
374        return;
375    }
376
377    UDate d = fmt->parse(*s, status);
378    logln(*s + " P> " + ((DateFormat*)fullFmt)->format(d, str));
379    int32_t y, m, day, hr, min, sec;
380    dateToFields(d, y, m, day, hr, min, sec);
381    hour += defaultTZ->inDaylightTime(d, status) ? 1 : 0;
382    hr = hr*60*60;
383    if (hr != hour)
384        errln((UnicodeString)"FAIL: Should parse to hour " + hour + " but got " + hr);
385
386    if (U_FAILURE(status))
387        errln((UnicodeString)"FAIL: " + (int32_t)status);
388
389    delete s;
390    delete fmt;
391    delete fullFmt;
392    delete PST;
393    delete defaultTZ;
394}
395
396// -------------------------------------
397
398UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
399
400UnicodeString&
401DateFormatTest::escape(UnicodeString& s)
402{
403    UnicodeString buf;
404    for (int32_t i=0; i<s.length(); ++i)
405    {
406        UChar c = s[(int32_t)i];
407        if (c <= (UChar)0x7F) buf += c;
408        else {
409            buf += (UChar)0x5c; buf += (UChar)0x55;
410            buf += toHexString((c & 0xF000) >> 12);
411            buf += toHexString((c & 0x0F00) >> 8);
412            buf += toHexString((c & 0x00F0) >> 4);
413            buf += toHexString(c & 0x000F);
414        }
415    }
416    return (s = buf);
417}
418
419// -------------------------------------
420
421/**
422 * This MUST be kept in sync with DateFormatSymbols.gPatternChars.
423 */
424static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXx";
425
426/**
427 * A list of the names of all the fields in DateFormat.
428 * This MUST be kept in sync with DateFormat.
429 */
430static const char* DATEFORMAT_FIELD_NAMES[] = {
431    "ERA_FIELD",
432    "YEAR_FIELD",
433    "MONTH_FIELD",
434    "DATE_FIELD",
435    "HOUR_OF_DAY1_FIELD",
436    "HOUR_OF_DAY0_FIELD",
437    "MINUTE_FIELD",
438    "SECOND_FIELD",
439    "MILLISECOND_FIELD",
440    "DAY_OF_WEEK_FIELD",
441    "DAY_OF_YEAR_FIELD",
442    "DAY_OF_WEEK_IN_MONTH_FIELD",
443    "WEEK_OF_YEAR_FIELD",
444    "WEEK_OF_MONTH_FIELD",
445    "AM_PM_FIELD",
446    "HOUR1_FIELD",
447    "HOUR0_FIELD",
448    "TIMEZONE_FIELD",
449    "YEAR_WOY_FIELD",
450    "DOW_LOCAL_FIELD",
451    "EXTENDED_YEAR_FIELD",
452    "JULIAN_DAY_FIELD",
453    "MILLISECONDS_IN_DAY_FIELD",
454    "TIMEZONE_RFC_FIELD",
455    "GENERIC_TIMEZONE_FIELD",
456    "STAND_ALONE_DAY_FIELD",
457    "STAND_ALONE_MONTH_FIELD",
458    "QUARTER_FIELD",
459    "STAND_ALONE_QUARTER_FIELD",
460    "TIMEZONE_SPECIAL_FIELD",
461    "YEAR_NAME_FIELD",
462    "TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD",
463    "TIMEZONE_ISO_FIELD",
464    "TIMEZONE_ISO_LOCAL_FIELD",
465};
466
467static const int32_t DATEFORMAT_FIELD_NAMES_LENGTH =
468    sizeof(DATEFORMAT_FIELD_NAMES) / sizeof(DATEFORMAT_FIELD_NAMES[0]);
469
470/**
471 * Verify that returned field position indices are correct.
472 */
473void DateFormatTest::TestFieldPosition() {
474    UErrorCode ec = U_ZERO_ERROR;
475    int32_t i, j, exp;
476    UnicodeString buf;
477
478    // Verify data
479    DateFormatSymbols rootSyms(Locale(""), ec);
480    if (U_FAILURE(ec)) {
481        dataerrln("Unable to create DateFormatSymbols - %s", u_errorName(ec));
482        return;
483    }
484
485    // local pattern chars data is not longer loaded
486    // from icu locale bundle
487    assertEquals("patternChars", PATTERN_CHARS, rootSyms.getLocalPatternChars(buf));
488    assertEquals("patternChars", PATTERN_CHARS, DateFormatSymbols::getPatternUChars());
489    assertTrue("DATEFORMAT_FIELD_NAMES", DATEFORMAT_FIELD_NAMES_LENGTH == UDAT_FIELD_COUNT);
490    assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS));
491
492    // Create test formatters
493    const int32_t COUNT = 4;
494    DateFormat* dateFormats[COUNT];
495    dateFormats[0] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getUS());
496    dateFormats[1] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getFrance());
497    // Make the pattern "G y M d..."
498    buf.remove().append(PATTERN_CHARS);
499    for (j=buf.length()-1; j>=0; --j) buf.insert(j, (UChar)32/*' '*/);
500    dateFormats[2] = new SimpleDateFormat(buf, Locale::getUS(), ec);
501    // Make the pattern "GGGG yyyy MMMM dddd..."
502    for (j=buf.length()-1; j>=0; j-=2) {
503        for (i=0; i<3; ++i) {
504            buf.insert(j, buf.charAt(j));
505        }
506    }
507    dateFormats[3] = new SimpleDateFormat(buf, Locale::getUS(), ec);
508    if(U_FAILURE(ec)){
509        errln(UnicodeString("Could not create SimpleDateFormat object for locale en_US. Error: " )+ UnicodeString(u_errorName(ec)));
510        return;
511    }
512    UDate aug13 = 871508052513.0;
513
514    // Expected output field values for above DateFormats on aug13
515    // Fields are given in order of DateFormat field number
516    const char* EXPECTED[] = {
517        "", "1997", "August", "13", "", "", "34", "12", "", "Wednesday",
518        "", "", "", "", "PM", "2", "", "Pacific Daylight Time", "", "",
519        "", "", "", "", "", "", "", "", "", "",
520        "", "", "", "",
521
522        "", "1997", "ao\\u00FBt", "13", "", "14", "34", "12", "", "mercredi",
523        "", "", "", "", "", "", "", "heure avanc\\u00e9e du Pacifique", "", "",
524        "", "", "", "", "",  "", "", "", "", "",
525        "", "", "", "",
526
527        "AD", "1997", "8", "13", "14", "14", "34", "12", "5", "Wed",
528        "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4",
529        "1997", "2450674", "52452513", "-0700", "PT",  "4", "8", "3", "3", "uslax",
530        "1997", "GMT-7", "-07", "-07",
531
532        "Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130", "Wednesday",
533        "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "Wednesday",
534        "1997", "2450674", "52452513", "GMT-07:00", "Pacific Time",  "Wednesday", "August", "3rd quarter", "3rd quarter", "Los Angeles Time",
535        "1997", "GMT-07:00", "-0700", "-0700",
536    };
537
538    const int32_t EXPECTED_LENGTH = sizeof(EXPECTED)/sizeof(EXPECTED[0]);
539
540    assertTrue("data size", EXPECTED_LENGTH == COUNT * UDAT_FIELD_COUNT);
541
542    TimeZone* PT = TimeZone::createTimeZone("America/Los_Angeles");
543    for (j = 0, exp = 0; j < COUNT; ++j) {
544        //  String str;
545        DateFormat* df = dateFormats[j];
546        df->setTimeZone(*PT);
547        SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
548        if (sdtfmt != NULL) {
549            logln(" Pattern = " + sdtfmt->toPattern(buf.remove()));
550        } else {
551            logln(" Pattern = ? (not a SimpleDateFormat)");
552        }
553        logln((UnicodeString)"  Result = " + df->format(aug13, buf.remove()));
554
555        int32_t expBase = exp; // save for later
556        for (i = 0; i < UDAT_FIELD_COUNT; ++i, ++exp) {
557            FieldPosition pos(i);
558            buf.remove();
559            df->format(aug13, buf, pos);
560            UnicodeString field;
561            buf.extractBetween(pos.getBeginIndex(), pos.getEndIndex(), field);
562            assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
563                         ctou(EXPECTED[exp]), field);
564        }
565
566        // test FieldPositionIterator API
567        logln("FieldPositionIterator");
568        {
569          UErrorCode status = U_ZERO_ERROR;
570          FieldPositionIterator posIter;
571          FieldPosition fp;
572
573          buf.remove();
574          df->format(aug13, buf, &posIter, status);
575          while (posIter.next(fp)) {
576            int32_t i = fp.getField();
577            UnicodeString field;
578            buf.extractBetween(fp.getBeginIndex(), fp.getEndIndex(), field);
579            assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
580                         ctou(EXPECTED[expBase + i]), field);
581          }
582
583        }
584    }
585
586
587    // test null posIter
588    buf.remove();
589    UErrorCode status = U_ZERO_ERROR;
590    dateFormats[0]->format(aug13, buf, NULL, status);
591    // if we didn't crash, we succeeded.
592
593    for (i=0; i<COUNT; ++i) {
594        delete dateFormats[i];
595    }
596    delete PT;
597}
598
599// -------------------------------------
600
601/**
602 * General parse/format tests.  Add test cases as needed.
603 */
604void DateFormatTest::TestGeneral() {
605    const char* DATA[] = {
606        "yyyy MM dd HH:mm:ss.SSS",
607
608        // Milliseconds are left-justified, since they format as fractions of a second
609        "y/M/d H:mm:ss.S", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5", "2004 03 10 16:36:31.500",
610        "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.56", "2004 03 10 16:36:31.560",
611        "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567",
612        "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5670",
613    };
614    expect(DATA, ARRAY_SIZE(DATA), Locale("en", "", ""));
615}
616
617// -------------------------------------
618
619/**
620 * Verify that strings which contain incomplete specifications are parsed
621 * correctly.  In some instances, this means not being parsed at all, and
622 * returning an appropriate error.
623 */
624void
625DateFormatTest::TestPartialParse994()
626{
627    UErrorCode status = U_ZERO_ERROR;
628    SimpleDateFormat* f = new SimpleDateFormat(status);
629    if (U_FAILURE(status)) {
630        dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
631        delete f;
632        return;
633    }
634    UDate null = 0;
635    tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", date(97, 1 - 1, 17, 10, 11, 42));
636    tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null);
637    tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null);
638    tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null);
639    tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null);
640    if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
641    delete f;
642}
643
644// -------------------------------------
645
646void
647DateFormatTest::tryPat994(SimpleDateFormat* format, const char* pat, const char* str, UDate expected)
648{
649    UErrorCode status = U_ZERO_ERROR;
650    UDate null = 0;
651    logln(UnicodeString("Pattern \"") + pat + "\"   String \"" + str + "\"");
652    //try {
653        format->applyPattern(pat);
654        UDate date = format->parse(str, status);
655        if (U_FAILURE(status) || date == null)
656        {
657            logln((UnicodeString)"ParseException: " + (int32_t)status);
658            if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
659        }
660        else
661        {
662            UnicodeString f;
663            ((DateFormat*)format)->format(date, f);
664            logln(UnicodeString(" parse(") + str + ") -> " + dateToString(date));
665            logln((UnicodeString)" format -> " + f);
666            if (expected == null ||
667                !(date == expected)) errln((UnicodeString)"FAIL: Expected null");//" + expected);
668            if (!(f == str)) errln(UnicodeString("FAIL: Expected ") + str);
669        }
670    //}
671    //catch(ParseException e) {
672    //    logln((UnicodeString)"ParseException: " + e.getMessage());
673    //    if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
674    //}
675    //catch(Exception e) {
676    //    errln((UnicodeString)"*** Exception:");
677    //    e.printStackTrace();
678    //}
679}
680
681// -------------------------------------
682
683/**
684 * Verify the behavior of patterns in which digits for different fields run together
685 * without intervening separators.
686 */
687void
688DateFormatTest::TestRunTogetherPattern985()
689{
690    UErrorCode status = U_ZERO_ERROR;
691    UnicodeString format("yyyyMMddHHmmssSSS");
692    UnicodeString now, then;
693    //UBool flag;
694    SimpleDateFormat *formatter = new SimpleDateFormat(format, status);
695    if (U_FAILURE(status)) {
696        dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
697        delete formatter;
698        return;
699    }
700    UDate date1 = Calendar::getNow();
701    ((DateFormat*)formatter)->format(date1, now);
702    logln(now);
703    ParsePosition pos(0);
704    UDate date2 = formatter->parse(now, pos);
705    if (date2 == 0) then = UnicodeString("Parse stopped at ") + pos.getIndex();
706    else ((DateFormat*)formatter)->format(date2, then);
707    logln(then);
708    if (!(date2 == date1)) errln((UnicodeString)"FAIL");
709    delete formatter;
710    if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
711}
712
713// -------------------------------------
714
715/**
716 * Verify the behavior of patterns in which digits for different fields run together
717 * without intervening separators.
718 */
719void
720DateFormatTest::TestRunTogetherPattern917()
721{
722    UErrorCode status = U_ZERO_ERROR;
723    SimpleDateFormat* fmt;
724    UnicodeString myDate;
725    fmt = new SimpleDateFormat((UnicodeString)"yyyy/MM/dd", status);
726    if (U_FAILURE(status)) {
727        dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
728        delete fmt;
729        return;
730    }
731    myDate = "1997/02/03";
732    testIt917(fmt, myDate, date(97, 2 - 1, 3));
733    delete fmt;
734    fmt = new SimpleDateFormat((UnicodeString)"yyyyMMdd", status);
735    myDate = "19970304";
736    testIt917(fmt, myDate, date(97, 3 - 1, 4));
737    delete fmt;
738    if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
739}
740
741// -------------------------------------
742
743void
744DateFormatTest::testIt917(SimpleDateFormat* fmt, UnicodeString& str, UDate expected)
745{
746    UErrorCode status = U_ZERO_ERROR;
747    UnicodeString pattern;
748    logln((UnicodeString)"pattern=" + fmt->toPattern(pattern) + "   string=" + str);
749    Formattable o;
750    //try {
751        ((Format*)fmt)->parseObject(str, o, status);
752    //}
753    if (U_FAILURE(status)) return;
754    //catch(ParseException e) {
755    //    e.printStackTrace();
756    //    return;
757    //}
758    logln((UnicodeString)"Parsed object: " + dateToString(o.getDate()));
759    if (!(o.getDate() == expected)) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
760    UnicodeString formatted; ((Format*)fmt)->format(o, formatted, status);
761    logln((UnicodeString)"Formatted string: " + formatted);
762    if (!(formatted == str)) errln((UnicodeString)"FAIL: Expected " + str);
763    if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
764}
765
766// -------------------------------------
767
768/**
769 * Verify the handling of Czech June and July, which have the unique attribute that
770 * one is a proper prefix substring of the other.
771 */
772void
773DateFormatTest::TestCzechMonths459()
774{
775    UErrorCode status = U_ZERO_ERROR;
776    DateFormat* fmt = DateFormat::createDateInstance(DateFormat::FULL, Locale("cs", "", ""));
777    if (fmt == NULL){
778        dataerrln("Error calling DateFormat::createDateInstance()");
779        return;
780    }
781
782    UnicodeString pattern;
783    logln((UnicodeString)"Pattern " + ((SimpleDateFormat*) fmt)->toPattern(pattern));
784    UDate june = date(97, UCAL_JUNE, 15);
785    UDate july = date(97, UCAL_JULY, 15);
786    UnicodeString juneStr; fmt->format(june, juneStr);
787    UnicodeString julyStr; fmt->format(july, julyStr);
788    //try {
789        logln((UnicodeString)"format(June 15 1997) = " + juneStr);
790        UDate d = fmt->parse(juneStr, status);
791        UnicodeString s; fmt->format(d, s);
792        int32_t month,yr,day,hr,min,sec; dateToFields(d,yr,month,day,hr,min,sec);
793        logln((UnicodeString)"  -> parse -> " + s + " (month = " + month + ")");
794        if (month != UCAL_JUNE) errln((UnicodeString)"FAIL: Month should be June");
795        logln((UnicodeString)"format(July 15 1997) = " + julyStr);
796        d = fmt->parse(julyStr, status);
797        fmt->format(d, s);
798        dateToFields(d,yr,month,day,hr,min,sec);
799        logln((UnicodeString)"  -> parse -> " + s + " (month = " + month + ")");
800        if (month != UCAL_JULY) errln((UnicodeString)"FAIL: Month should be July");
801    //}
802    //catch(ParseException e) {
803    if (U_FAILURE(status))
804        errln((UnicodeString)"Exception: " + (int32_t)status);
805    //}
806    delete fmt;
807}
808
809// -------------------------------------
810
811/**
812 * Test the handling of 'D' in patterns.
813 */
814void
815DateFormatTest::TestLetterDPattern212()
816{
817    UErrorCode status = U_ZERO_ERROR;
818    UnicodeString dateString("1995-040.05:01:29");
819    UnicodeString bigD("yyyy-DDD.hh:mm:ss");
820    UnicodeString littleD("yyyy-ddd.hh:mm:ss");
821    UDate expLittleD = date(95, 0, 1, 5, 1, 29);
822    UDate expBigD = expLittleD + 39 * 24 * 3600000.0;
823    expLittleD = expBigD; // Expect the same, with default lenient parsing
824    logln((UnicodeString)"dateString= " + dateString);
825    SimpleDateFormat *formatter = new SimpleDateFormat(bigD, status);
826    if (U_FAILURE(status)) {
827        dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
828        delete formatter;
829        return;
830    }
831    ParsePosition pos(0);
832    UDate myDate = formatter->parse(dateString, pos);
833    logln((UnicodeString)"Using " + bigD + " -> " + myDate);
834    if (myDate != expBigD) errln((UnicodeString)"FAIL: bigD - Expected " + dateToString(expBigD));
835    delete formatter;
836    formatter = new SimpleDateFormat(littleD, status);
837    ASSERT_OK(status);
838    pos = ParsePosition(0);
839    myDate = formatter->parse(dateString, pos);
840    logln((UnicodeString)"Using " + littleD + " -> " + dateToString(myDate));
841    if (myDate != expLittleD) errln((UnicodeString)"FAIL: littleD - Expected " + dateToString(expLittleD));
842    delete formatter;
843    if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
844}
845
846// -------------------------------------
847
848/**
849 * Test the day of year pattern.
850 */
851void
852DateFormatTest::TestDayOfYearPattern195()
853{
854    UErrorCode status = U_ZERO_ERROR;
855    UDate today = Calendar::getNow();
856    int32_t year,month,day,hour,min,sec; dateToFields(today,year,month,day,hour,min,sec);
857    UDate expected = date(year, month, day);
858    logln((UnicodeString)"Test Date: " + dateToString(today));
859    SimpleDateFormat* sdf = (SimpleDateFormat*)DateFormat::createDateInstance();
860    if (sdf == NULL){
861        dataerrln("Error calling DateFormat::createDateInstance()");
862        return;
863    }
864    tryPattern(*sdf, today, 0, expected);
865    tryPattern(*sdf, today, "G yyyy DDD", expected);
866    delete sdf;
867    if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
868}
869
870// -------------------------------------
871
872void
873DateFormatTest::tryPattern(SimpleDateFormat& sdf, UDate d, const char* pattern, UDate expected)
874{
875    UErrorCode status = U_ZERO_ERROR;
876    if (pattern != 0) sdf.applyPattern(pattern);
877    UnicodeString thePat;
878    logln((UnicodeString)"pattern: " + sdf.toPattern(thePat));
879    UnicodeString formatResult; (*(DateFormat*)&sdf).format(d, formatResult);
880    logln((UnicodeString)" format -> " + formatResult);
881    // try {
882        UDate d2 = sdf.parse(formatResult, status);
883        logln((UnicodeString)" parse(" + formatResult + ") -> " + dateToString(d2));
884        if (d2 != expected) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
885        UnicodeString format2; (*(DateFormat*)&sdf).format(d2, format2);
886        logln((UnicodeString)" format -> " + format2);
887        if (!(formatResult == format2)) errln((UnicodeString)"FAIL: Round trip drift");
888    //}
889    //catch(Exception e) {
890    if (U_FAILURE(status))
891        errln((UnicodeString)"Error: " + (int32_t)status);
892    //}
893}
894
895// -------------------------------------
896
897/**
898 * Test the handling of single quotes in patterns.
899 */
900void
901DateFormatTest::TestQuotePattern161()
902{
903    UErrorCode status = U_ZERO_ERROR;
904    SimpleDateFormat* formatter = new SimpleDateFormat((UnicodeString)"MM/dd/yyyy 'at' hh:mm:ss a zzz", status);
905    if (U_FAILURE(status)) {
906        dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
907        delete formatter;
908        return;
909    }
910    UDate currentTime_1 = date(97, UCAL_AUGUST, 13, 10, 42, 28);
911    UnicodeString dateString; ((DateFormat*)formatter)->format(currentTime_1, dateString);
912    UnicodeString exp("08/13/1997 at 10:42:28 AM ");
913    logln((UnicodeString)"format(" + dateToString(currentTime_1) + ") = " + dateString);
914    if (0 != dateString.compareBetween(0, exp.length(), exp, 0, exp.length())) errln((UnicodeString)"FAIL: Expected " + exp);
915    delete formatter;
916    if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
917}
918
919// -------------------------------------
920
921/**
922 * Verify the correct behavior when handling invalid input strings.
923 */
924void
925DateFormatTest::TestBadInput135()
926{
927    UErrorCode status = U_ZERO_ERROR;
928    DateFormat::EStyle looks[] = {
929        DateFormat::SHORT, DateFormat::MEDIUM, DateFormat::LONG, DateFormat::FULL
930    };
931    int32_t looks_length = (int32_t)(sizeof(looks) / sizeof(looks[0]));
932    const char* strings[] = {
933        "Mar 15", "Mar 15 1997", "asdf", "3/1/97 1:23:", "3/1/00 1:23:45 AM"
934    };
935    int32_t strings_length = (int32_t)(sizeof(strings) / sizeof(strings[0]));
936    DateFormat *full = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::LONG);
937    if(full==NULL) {
938      dataerrln("could not create date time instance");
939      return;
940    }
941    UnicodeString expected("March 1, 2000 at 1:23:45 AM ");
942    for (int32_t i = 0; i < strings_length;++i) {
943        const char* text = strings[i];
944        for (int32_t j = 0; j < looks_length;++j) {
945            DateFormat::EStyle dateLook = looks[j];
946            for (int32_t k = 0; k < looks_length;++k) {
947                DateFormat::EStyle timeLook = looks[k];
948                DateFormat *df = DateFormat::createDateTimeInstance(dateLook, timeLook);
949                if (df == NULL){
950                    dataerrln("Error calling DateFormat::createDateTimeInstance()");
951                    continue;
952                }
953                UnicodeString prefix = UnicodeString(text) + ", " + dateLook + "/" + timeLook + ": ";
954                //try {
955                    UDate when = df->parse(text, status);
956                    if (when == 0 && U_SUCCESS(status)) {
957                        errln(prefix + "SHOULD NOT HAPPEN: parse returned 0.");
958                        continue;
959                    }
960                    if (U_SUCCESS(status))
961                    {
962                        UnicodeString format;
963                        UnicodeString pattern;
964                        SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
965                        if (sdtfmt != NULL) {
966                            sdtfmt->toPattern(pattern);
967                        }
968                        full->format(when, format);
969                        logln(prefix + "OK: " + format);
970                        if (0!=format.compareBetween(0, expected.length(), expected, 0, expected.length()))
971                            errln((UnicodeString)"FAIL: Parse \"" + text + "\", pattern \"" + pattern + "\", expected " + expected + " got " + format);
972                    }
973                //}
974                //catch(ParseException e) {
975                    else
976                        status = U_ZERO_ERROR;
977                //}
978                //catch(StringIndexOutOfBoundsException e) {
979                //    errln(prefix + "SHOULD NOT HAPPEN: " + (int)status);
980                //}
981                delete df;
982            }
983        }
984    }
985    delete full;
986    if (U_FAILURE(status))
987        errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
988}
989
990static const char* const parseFormats[] = {
991    "MMMM d, yyyy",
992    "MMMM d yyyy",
993    "M/d/yy",
994    "d MMMM, yyyy",
995    "d MMMM yyyy",
996    "d MMMM",
997    "MMMM d",
998    "yyyy",
999    "h:mm a MMMM d, yyyy"
1000};
1001
1002#if 0
1003// strict inputStrings
1004static const char* const inputStrings[] = {
1005    "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1006    "April 1, 1997", "April 1, 1997", 0, 0, 0, 0, 0, "April 1", 0, 0,
1007    "Jan 1, 1970", "January 1, 1970", 0, 0, 0, 0, 0, "January 1", 0, 0,
1008    "Jan 1 2037", 0, "January 1 2037", 0, 0, 0, 0, "January 1", 0, 0,
1009    "1/1/70", 0, 0, "1/1/70", 0, 0, 0, 0, "0001", 0,
1010    "5 May 1997", 0, 0, 0, 0, "5 May 1997", "5 May", 0, "0005", 0,
1011    "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1012    "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1013    "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1014    "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1015    "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1016};
1017#else
1018// lenient inputStrings
1019static const char* const inputStrings[] = {
1020    "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1021    "April 1, 1997", "April 1, 1997", "April 1 1997", "4/1/97", 0, 0, 0, "April 1", 0, 0,
1022    "Jan 1, 1970", "January 1, 1970", "January 1 1970", "1/1/70", 0, 0, 0, "January 1", 0, 0,
1023    "Jan 1 2037", "January 1, 2037", "January 1 2037", "1/1/37", 0, 0, 0, "January 1", 0, 0,
1024    "1/1/70", "January 1, 0070", "January 1 0070", "1/1/70", "1 January, 0070", "1 January 0070", "1 January", "January 1", "0001", 0,
1025    "5 May 1997", 0, 0, 0, "5 May, 1997", "5 May 1997", "5 May", 0, "0005", 0,
1026    "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1027    "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1028    "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1029    "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1030    "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1031};
1032#endif
1033
1034// -------------------------------------
1035
1036/**
1037 * Verify the correct behavior when parsing an array of inputs against an
1038 * array of patterns, with known results.  The results are encoded after
1039 * the input strings in each row.
1040 */
1041void
1042DateFormatTest::TestBadInput135a()
1043{
1044  UErrorCode status = U_ZERO_ERROR;
1045  SimpleDateFormat* dateParse = new SimpleDateFormat(status);
1046  if(U_FAILURE(status)) {
1047    dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1048    delete dateParse;
1049    return;
1050  }
1051  const char* s;
1052  UDate date;
1053  const uint32_t PF_LENGTH = (int32_t)(sizeof(parseFormats)/sizeof(parseFormats[0]));
1054  const uint32_t INPUT_LENGTH = (int32_t)(sizeof(inputStrings)/sizeof(inputStrings[0]));
1055
1056  dateParse->applyPattern("d MMMM, yyyy");
1057  dateParse->adoptTimeZone(TimeZone::createDefault());
1058  s = "not parseable";
1059  UnicodeString thePat;
1060  logln(UnicodeString("Trying to parse \"") + s + "\" with " + dateParse->toPattern(thePat));
1061  //try {
1062  date = dateParse->parse(s, status);
1063  if (U_SUCCESS(status))
1064    errln((UnicodeString)"FAIL: Expected exception during parse");
1065  //}
1066  //catch(Exception ex) {
1067  else
1068    logln((UnicodeString)"Exception during parse: " + (int32_t)status);
1069  status = U_ZERO_ERROR;
1070  //}
1071  for (uint32_t i = 0; i < INPUT_LENGTH; i += (PF_LENGTH + 1)) {
1072    ParsePosition parsePosition(0);
1073    UnicodeString s( inputStrings[i]);
1074    for (uint32_t index = 0; index < PF_LENGTH;++index) {
1075      const char* expected = inputStrings[i + 1 + index];
1076      dateParse->applyPattern(parseFormats[index]);
1077      dateParse->adoptTimeZone(TimeZone::createDefault());
1078      //try {
1079      parsePosition.setIndex(0);
1080      date = dateParse->parse(s, parsePosition);
1081      if (parsePosition.getIndex() != 0) {
1082        UnicodeString s1, s2;
1083        s.extract(0, parsePosition.getIndex(), s1);
1084        s.extract(parsePosition.getIndex(), s.length(), s2);
1085        if (date == 0) {
1086          errln((UnicodeString)"ERROR: null result fmt=\"" +
1087                     parseFormats[index] +
1088                     "\" pos=" + parsePosition.getIndex() + " " +
1089                     s1 + "|" + s2);
1090        }
1091        else {
1092          UnicodeString result;
1093          ((DateFormat*)dateParse)->format(date, result);
1094          logln((UnicodeString)"Parsed \"" + s + "\" using \"" + dateParse->toPattern(thePat) + "\" to: " + result);
1095          if (expected == 0)
1096            errln((UnicodeString)"FAIL: Expected parse failure, got " + result);
1097          else if (!(result == expected))
1098            errln(UnicodeString("FAIL: Parse \"") + s + UnicodeString("\", expected ") + expected + UnicodeString(", got ") + result);
1099        }
1100      }
1101      else if (expected != 0) {
1102        errln(UnicodeString("FAIL: Expected ") + expected + " from \"" +
1103                     s + "\" with \"" + dateParse->toPattern(thePat) + "\"");
1104      }
1105      //}
1106      //catch(Exception ex) {
1107      if (U_FAILURE(status))
1108        errln((UnicodeString)"An exception was thrown during parse: " + (int32_t)status);
1109      //}
1110    }
1111  }
1112  delete dateParse;
1113  if (U_FAILURE(status))
1114    errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1115}
1116
1117// -------------------------------------
1118
1119/**
1120 * Test the parsing of two-digit years.
1121 */
1122void
1123DateFormatTest::TestTwoDigitYear()
1124{
1125    UErrorCode ec = U_ZERO_ERROR;
1126    SimpleDateFormat fmt("dd/MM/yy", Locale::getUK(), ec);
1127    if (U_FAILURE(ec)) {
1128        dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1129        return;
1130    }
1131    parse2DigitYear(fmt, "5/6/17", date(117, UCAL_JUNE, 5));
1132    parse2DigitYear(fmt, "4/6/34", date(34, UCAL_JUNE, 4));
1133}
1134
1135// -------------------------------------
1136
1137void
1138DateFormatTest::parse2DigitYear(DateFormat& fmt, const char* str, UDate expected)
1139{
1140    UErrorCode status = U_ZERO_ERROR;
1141    //try {
1142        UDate d = fmt.parse(str, status);
1143        UnicodeString thePat;
1144        logln(UnicodeString("Parsing \"") + str + "\" with " + ((SimpleDateFormat*)&fmt)->toPattern(thePat) +
1145            "  => " + dateToString(d));
1146        if (d != expected) errln((UnicodeString)"FAIL: Expected " + expected);
1147    //}
1148    //catch(ParseException e) {
1149        if (U_FAILURE(status))
1150        errln((UnicodeString)"FAIL: Got exception");
1151    //}
1152}
1153
1154// -------------------------------------
1155
1156/**
1157 * Test the formatting of time zones.
1158 */
1159void
1160DateFormatTest::TestDateFormatZone061()
1161{
1162    UErrorCode status = U_ZERO_ERROR;
1163    UDate date;
1164    DateFormat *formatter;
1165    date= 859248000000.0;
1166    logln((UnicodeString)"Date 1997/3/25 00:00 GMT: " + date);
1167    formatter = new SimpleDateFormat((UnicodeString)"dd-MMM-yyyyy HH:mm", Locale::getUK(), status);
1168    if(U_FAILURE(status)) {
1169      dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1170      delete formatter;
1171      return;
1172    }
1173    formatter->adoptTimeZone(TimeZone::createTimeZone("GMT"));
1174    UnicodeString temp; formatter->format(date, temp);
1175    logln((UnicodeString)"Formatted in GMT to: " + temp);
1176    //try {
1177        UDate tempDate = formatter->parse(temp, status);
1178        logln((UnicodeString)"Parsed to: " + dateToString(tempDate));
1179        if (tempDate != date) errln((UnicodeString)"FAIL: Expected " + dateToString(date));
1180    //}
1181    //catch(Throwable t) {
1182    if (U_FAILURE(status))
1183        errln((UnicodeString)"Date Formatter throws: " + (int32_t)status);
1184    //}
1185    delete formatter;
1186}
1187
1188// -------------------------------------
1189
1190/**
1191 * Test the formatting of time zones.
1192 */
1193void
1194DateFormatTest::TestDateFormatZone146()
1195{
1196    TimeZone *saveDefault = TimeZone::createDefault();
1197
1198        //try {
1199    TimeZone *thedefault = TimeZone::createTimeZone("GMT");
1200    TimeZone::setDefault(*thedefault);
1201            // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
1202
1203            // check to be sure... its GMT all right
1204        TimeZone *testdefault = TimeZone::createDefault();
1205        UnicodeString testtimezone;
1206        testdefault->getID(testtimezone);
1207        if (testtimezone == "GMT")
1208            logln("Test timezone = " + testtimezone);
1209        else
1210            dataerrln("Test timezone should be GMT, not " + testtimezone);
1211
1212        UErrorCode status = U_ZERO_ERROR;
1213        // now try to use the default GMT time zone
1214        GregorianCalendar *greenwichcalendar =
1215            new GregorianCalendar(1997, 3, 4, 23, 0, status);
1216        if (U_FAILURE(status)) {
1217            dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
1218        } else {
1219            //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
1220            //greenwichcalendar.set(1997, 3, 4, 23, 0);
1221            // try anything to set hour to 23:00 !!!
1222            greenwichcalendar->set(UCAL_HOUR_OF_DAY, 23);
1223            // get time
1224            UDate greenwichdate = greenwichcalendar->getTime(status);
1225            // format every way
1226            UnicodeString DATA [] = {
1227                UnicodeString("simple format:  "), UnicodeString("04/04/97 23:00 GMT"),
1228                    UnicodeString("MM/dd/yy HH:mm z"),
1229                UnicodeString("full format:    "), UnicodeString("Friday, April 4, 1997 11:00:00 o'clock PM GMT"),
1230                    UnicodeString("EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z"),
1231                UnicodeString("long format:    "), UnicodeString("April 4, 1997 11:00:00 PM GMT"),
1232                    UnicodeString("MMMM d, yyyy h:mm:ss a z"),
1233                UnicodeString("default format: "), UnicodeString("04-Apr-97 11:00:00 PM"),
1234                    UnicodeString("dd-MMM-yy h:mm:ss a"),
1235                UnicodeString("short format:   "), UnicodeString("4/4/97 11:00 PM"),
1236                    UnicodeString("M/d/yy h:mm a")
1237            };
1238            int32_t DATA_length = (int32_t)(sizeof(DATA) / sizeof(DATA[0]));
1239
1240            for (int32_t i=0; i<DATA_length; i+=3) {
1241                DateFormat *fmt = new SimpleDateFormat(DATA[i+2], Locale::getEnglish(), status);
1242                if (U_FAILURE(status)) {
1243                    dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
1244                    break;
1245                }
1246                fmt->setCalendar(*greenwichcalendar);
1247                UnicodeString result;
1248                result = fmt->format(greenwichdate, result);
1249                logln(DATA[i] + result);
1250                if (result != DATA[i+1])
1251                    errln("FAIL: Expected " + DATA[i+1] + ", got " + result);
1252                delete fmt;
1253            }
1254        }
1255    //}
1256    //finally {
1257        TimeZone::adoptDefault(saveDefault);
1258    //}
1259        delete testdefault;
1260        delete greenwichcalendar;
1261        delete thedefault;
1262
1263
1264}
1265
1266// -------------------------------------
1267
1268/**
1269 * Test the formatting of dates in different locales.
1270 */
1271void
1272DateFormatTest::TestLocaleDateFormat() // Bug 495
1273{
1274    UDate testDate = date(97, UCAL_SEPTEMBER, 15);
1275    DateFormat *dfFrench = DateFormat::createDateTimeInstance(DateFormat::FULL,
1276        DateFormat::FULL, Locale::getFrench());
1277    DateFormat *dfUS = DateFormat::createDateTimeInstance(DateFormat::FULL,
1278        DateFormat::FULL, Locale::getUS());
1279    UnicodeString expectedFRENCH ( "lundi 15 septembre 1997 00:00:00 heure avanc\\u00E9e du Pacifique", -1, US_INV );
1280    expectedFRENCH = expectedFRENCH.unescape();
1281    UnicodeString expectedUS ( "Monday, September 15, 1997 at 12:00:00 AM Pacific Daylight Time" );
1282    logln((UnicodeString)"Date set to : " + dateToString(testDate));
1283    UnicodeString out;
1284    if (dfUS == NULL || dfFrench == NULL){
1285        dataerrln("Error calling DateFormat::createDateTimeInstance)");
1286        delete dfUS;
1287        delete dfFrench;
1288        return;
1289    }
1290
1291    dfFrench->format(testDate, out);
1292    logln((UnicodeString)"Date Formated with French Locale " + out);
1293    if (!(out == expectedFRENCH))
1294        errln((UnicodeString)"FAIL: Expected " + expectedFRENCH);
1295    out.truncate(0);
1296    dfUS->format(testDate, out);
1297    logln((UnicodeString)"Date Formated with US Locale " + out);
1298    if (!(out == expectedUS))
1299        errln((UnicodeString)"FAIL: Expected " + expectedUS);
1300    delete dfUS;
1301    delete dfFrench;
1302}
1303
1304/**
1305 * Test DateFormat(Calendar) API
1306 */
1307void DateFormatTest::TestDateFormatCalendar() {
1308    DateFormat *date=0, *time=0, *full=0;
1309    Calendar *cal=0;
1310    UnicodeString str;
1311    ParsePosition pos;
1312    UDate when;
1313    UErrorCode ec = U_ZERO_ERROR;
1314
1315    /* Create a formatter for date fields. */
1316    date = DateFormat::createDateInstance(DateFormat::kShort, Locale::getUS());
1317    if (date == NULL) {
1318        dataerrln("FAIL: createDateInstance failed");
1319        goto FAIL;
1320    }
1321
1322    /* Create a formatter for time fields. */
1323    time = DateFormat::createTimeInstance(DateFormat::kShort, Locale::getUS());
1324    if (time == NULL) {
1325        errln("FAIL: createTimeInstance failed");
1326        goto FAIL;
1327    }
1328
1329    /* Create a full format for output */
1330    full = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull,
1331                                              Locale::getUS());
1332    if (full == NULL) {
1333        errln("FAIL: createInstance failed");
1334        goto FAIL;
1335    }
1336
1337    /* Create a calendar */
1338    cal = Calendar::createInstance(Locale::getUS(), ec);
1339    if (cal == NULL || U_FAILURE(ec)) {
1340        errln((UnicodeString)"FAIL: Calendar::createInstance failed with " +
1341              u_errorName(ec));
1342        goto FAIL;
1343    }
1344
1345    /* Parse the date */
1346    cal->clear();
1347    str = UnicodeString("4/5/2001", "");
1348    pos.setIndex(0);
1349    date->parse(str, *cal, pos);
1350    if (pos.getIndex() != str.length()) {
1351        errln((UnicodeString)"FAIL: DateFormat::parse(4/5/2001) failed at " +
1352              pos.getIndex());
1353        goto FAIL;
1354    }
1355
1356    /* Parse the time */
1357    str = UnicodeString("5:45 PM", "");
1358    pos.setIndex(0);
1359    time->parse(str, *cal, pos);
1360    if (pos.getIndex() != str.length()) {
1361        errln((UnicodeString)"FAIL: DateFormat::parse(17:45) failed at " +
1362              pos.getIndex());
1363        goto FAIL;
1364    }
1365
1366    /* Check result */
1367    when = cal->getTime(ec);
1368    if (U_FAILURE(ec)) {
1369        errln((UnicodeString)"FAIL: cal->getTime() failed with " + u_errorName(ec));
1370        goto FAIL;
1371    }
1372    str.truncate(0);
1373    full->format(when, str);
1374    // Thursday, April 5, 2001 5:45:00 PM PDT 986517900000
1375    if (when == 986517900000.0) {
1376        logln("Ok: Parsed result: " + str);
1377    } else {
1378        errln("FAIL: Parsed result: " + str + ", exp 4/5/2001 5:45 PM");
1379    }
1380
1381 FAIL:
1382    delete date;
1383    delete time;
1384    delete full;
1385    delete cal;
1386}
1387
1388/**
1389 * Test DateFormat's parsing of space characters.  See jitterbug 1916.
1390 */
1391void DateFormatTest::TestSpaceParsing() {
1392    const char* DATA[] = {
1393        "yyyy MM dd HH:mm:ss",
1394
1395        // pattern, input, expected parse or NULL if expect parse failure
1396        "MMMM d yy", " 04 05 06",  "2006 04 05 00:00:00",
1397        NULL,        "04 05 06",   "2006 04 05 00:00:00",
1398
1399        "MM d yy",   " 04 05 06",    "2006 04 05 00:00:00",
1400        NULL,        "04 05 06",     "2006 04 05 00:00:00",
1401        NULL,        "04/05/06",     "2006 04 05 00:00:00",
1402        NULL,        "04-05-06",     "2006 04 05 00:00:00",
1403        NULL,        "04.05.06",     "2006 04 05 00:00:00",
1404        NULL,        "04 / 05 / 06", "2006 04 05 00:00:00",
1405        NULL,        "Apr / 05/ 06", "2006 04 05 00:00:00",
1406        NULL,        "Apr-05-06",    "2006 04 05 00:00:00",
1407        NULL,        "Apr 05, 2006", "2006 04 05 00:00:00",
1408
1409        "MMMM d yy", " Apr 05 06", "2006 04 05 00:00:00",
1410        NULL,        "Apr 05 06",  "2006 04 05 00:00:00",
1411        NULL,        "Apr05 06",   "2006 04 05 00:00:00",
1412
1413        "hh:mm:ss a", "12:34:56 PM", "1970 01 01 12:34:56",
1414        NULL,         "12:34:56PM",  "1970 01 01 12:34:56",
1415        NULL,         "12.34.56PM",  "1970 01 01 12:34:56",
1416        NULL,         "12-34-56 PM", "1970 01 01 12:34:56",
1417        NULL,         "12 : 34 : 56  PM", "1970 01 01 12:34:56",
1418
1419        "MM d yy 'at' hh:mm:ss a", "04/05/06 12:34:56 PM", "2006 04 05 12:34:56",
1420
1421        "MMMM dd yyyy hh:mm a", "September 27, 1964 21:56 PM", "1964 09 28 09:56:00",
1422        NULL,                   "November 4, 2008 0:13 AM",    "2008 11 04 00:13:00",
1423
1424        "HH'h'mm'min'ss's'", "12h34min56s", "1970 01 01 12:34:56",
1425        NULL,                "12h34mi56s",  "1970 01 01 12:34:56",
1426        NULL,                "12h34m56s",   "1970 01 01 12:34:56",
1427        NULL,                "12:34:56",    "1970 01 01 12:34:56"
1428    };
1429    const int32_t DATA_len = sizeof(DATA)/sizeof(DATA[0]);
1430
1431    expectParse(DATA, DATA_len, Locale("en"));
1432}
1433
1434/**
1435 * Test handling of "HHmmss" pattern.
1436 */
1437void DateFormatTest::TestExactCountFormat() {
1438    const char* DATA[] = {
1439        "yyyy MM dd HH:mm:ss",
1440
1441        // pattern, input, expected parse or NULL if expect parse failure
1442        "HHmmss", "123456", "1970 01 01 12:34:56",
1443        NULL,     "12345",  "1970 01 01 01:23:45",
1444        NULL,     "1234",   NULL,
1445        NULL,     "00-05",  NULL,
1446        NULL,     "12-34",  NULL,
1447        NULL,     "00+05",  NULL,
1448        "ahhmm",  "PM730",  "1970 01 01 19:30:00",
1449    };
1450    const int32_t DATA_len = sizeof(DATA)/sizeof(DATA[0]);
1451
1452    expectParse(DATA, DATA_len, Locale("en"));
1453}
1454
1455/**
1456 * Test handling of white space.
1457 */
1458void DateFormatTest::TestWhiteSpaceParsing() {
1459    const char* DATA[] = {
1460        "yyyy MM dd",
1461
1462        // pattern, input, expected parse or null if expect parse failure
1463
1464        // Pattern space run should parse input text space run
1465        "MM   d yy",   " 04 01 03",    "2003 04 01",
1466        NULL,          " 04  01   03 ", "2003 04 01",
1467    };
1468    const int32_t DATA_len = sizeof(DATA)/sizeof(DATA[0]);
1469
1470    expectParse(DATA, DATA_len, Locale("en"));
1471}
1472
1473
1474void DateFormatTest::TestInvalidPattern() {
1475    UErrorCode ec = U_ZERO_ERROR;
1476    SimpleDateFormat f(UnicodeString("Yesterday"), ec);
1477    if (U_FAILURE(ec)) {
1478        dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1479        return;
1480    }
1481    UnicodeString out;
1482    FieldPosition pos;
1483    f.format((UDate)0, out, pos);
1484    logln(out);
1485    // The bug is that the call to format() will crash.  By not
1486    // crashing, the test passes.
1487}
1488
1489void DateFormatTest::TestGreekMay() {
1490    UErrorCode ec = U_ZERO_ERROR;
1491    UDate date = -9896080848000.0;
1492    SimpleDateFormat fmt("EEEE, dd MMMM yyyy h:mm:ss a", Locale("el", "", ""), ec);
1493    if (U_FAILURE(ec)) {
1494        dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1495        return;
1496    }
1497    UnicodeString str;
1498    fmt.format(date, str);
1499    ParsePosition pos(0);
1500    UDate d2 = fmt.parse(str, pos);
1501    if (date != d2) {
1502        errln("FAIL: unable to parse strings where case-folding changes length");
1503    }
1504}
1505
1506void DateFormatTest::TestStandAloneMonths()
1507{
1508    const char *EN_DATA[] = {
1509        "yyyy MM dd HH:mm:ss",
1510
1511        "yyyy LLLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 March 10 16:36:31", "2004 03 10 16:36:31",
1512        "yyyy LLL dd H:mm:ss",  "fp", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31",   "2004 03 10 16:36:31",
1513        "yyyy LLLL dd H:mm:ss", "F",  "2004 03 10 16:36:31", "2004 March 10 16:36:31",
1514        "yyyy LLL dd H:mm:ss",  "pf", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31",
1515
1516        "LLLL", "fp", "1970 01 01 0:00:00", "January",   "1970 01 01 0:00:00",
1517        "LLLL", "fp", "1970 02 01 0:00:00", "February",  "1970 02 01 0:00:00",
1518        "LLLL", "fp", "1970 03 01 0:00:00", "March",     "1970 03 01 0:00:00",
1519        "LLLL", "fp", "1970 04 01 0:00:00", "April",     "1970 04 01 0:00:00",
1520        "LLLL", "fp", "1970 05 01 0:00:00", "May",       "1970 05 01 0:00:00",
1521        "LLLL", "fp", "1970 06 01 0:00:00", "June",      "1970 06 01 0:00:00",
1522        "LLLL", "fp", "1970 07 01 0:00:00", "July",      "1970 07 01 0:00:00",
1523        "LLLL", "fp", "1970 08 01 0:00:00", "August",    "1970 08 01 0:00:00",
1524        "LLLL", "fp", "1970 09 01 0:00:00", "September", "1970 09 01 0:00:00",
1525        "LLLL", "fp", "1970 10 01 0:00:00", "October",   "1970 10 01 0:00:00",
1526        "LLLL", "fp", "1970 11 01 0:00:00", "November",  "1970 11 01 0:00:00",
1527        "LLLL", "fp", "1970 12 01 0:00:00", "December",  "1970 12 01 0:00:00",
1528
1529        "LLL", "fp", "1970 01 01 0:00:00", "Jan", "1970 01 01 0:00:00",
1530        "LLL", "fp", "1970 02 01 0:00:00", "Feb", "1970 02 01 0:00:00",
1531        "LLL", "fp", "1970 03 01 0:00:00", "Mar", "1970 03 01 0:00:00",
1532        "LLL", "fp", "1970 04 01 0:00:00", "Apr", "1970 04 01 0:00:00",
1533        "LLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1534        "LLL", "fp", "1970 06 01 0:00:00", "Jun", "1970 06 01 0:00:00",
1535        "LLL", "fp", "1970 07 01 0:00:00", "Jul", "1970 07 01 0:00:00",
1536        "LLL", "fp", "1970 08 01 0:00:00", "Aug", "1970 08 01 0:00:00",
1537        "LLL", "fp", "1970 09 01 0:00:00", "Sep", "1970 09 01 0:00:00",
1538        "LLL", "fp", "1970 10 01 0:00:00", "Oct", "1970 10 01 0:00:00",
1539        "LLL", "fp", "1970 11 01 0:00:00", "Nov", "1970 11 01 0:00:00",
1540        "LLL", "fp", "1970 12 01 0:00:00", "Dec", "1970 12 01 0:00:00",
1541    };
1542
1543    const char *CS_DATA[] = {
1544        "yyyy MM dd HH:mm:ss",
1545
1546        "yyyy LLLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 duben 10 16:36:31", "2004 04 10 16:36:31",
1547        "yyyy MMMM dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31",
1548        "yyyy LLL dd H:mm:ss",  "fp", "2004 04 10 16:36:31", "2004 dub 10 16:36:31",   "2004 04 10 16:36:31",
1549        "yyyy LLLL dd H:mm:ss", "F",  "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1550        "yyyy MMMM dd H:mm:ss", "F",  "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1551        "yyyy LLLL dd H:mm:ss", "pf", "2004 duben 10 16:36:31", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1552        "yyyy MMMM dd H:mm:ss", "pf", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1553
1554        "LLLL", "fp", "1970 01 01 0:00:00", "leden",               "1970 01 01 0:00:00",
1555        "LLLL", "fp", "1970 02 01 0:00:00", "\\u00FAnor",           "1970 02 01 0:00:00",
1556        "LLLL", "fp", "1970 03 01 0:00:00", "b\\u0159ezen",         "1970 03 01 0:00:00",
1557        "LLLL", "fp", "1970 04 01 0:00:00", "duben",               "1970 04 01 0:00:00",
1558        "LLLL", "fp", "1970 05 01 0:00:00", "kv\\u011Bten",         "1970 05 01 0:00:00",
1559        "LLLL", "fp", "1970 06 01 0:00:00", "\\u010Derven",         "1970 06 01 0:00:00",
1560        "LLLL", "fp", "1970 07 01 0:00:00", "\\u010Dervenec",       "1970 07 01 0:00:00",
1561        "LLLL", "fp", "1970 08 01 0:00:00", "srpen",               "1970 08 01 0:00:00",
1562        "LLLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159\\u00ED", "1970 09 01 0:00:00",
1563        "LLLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDjen",     "1970 10 01 0:00:00",
1564        "LLLL", "fp", "1970 11 01 0:00:00", "listopad",            "1970 11 01 0:00:00",
1565        "LLLL", "fp", "1970 12 01 0:00:00", "prosinec",            "1970 12 01 0:00:00",
1566
1567        "LLL", "fp", "1970 01 01 0:00:00", "led",  "1970 01 01 0:00:00",
1568        "LLL", "fp", "1970 02 01 0:00:00", "\\u00FAno",  "1970 02 01 0:00:00",
1569        "LLL", "fp", "1970 03 01 0:00:00", "b\\u0159e",  "1970 03 01 0:00:00",
1570        "LLL", "fp", "1970 04 01 0:00:00", "dub",  "1970 04 01 0:00:00",
1571        "LLL", "fp", "1970 05 01 0:00:00", "kv\\u011B",  "1970 05 01 0:00:00",
1572        "LLL", "fp", "1970 06 01 0:00:00", "\\u010Dvn",  "1970 06 01 0:00:00",
1573        "LLL", "fp", "1970 07 01 0:00:00", "\\u010Dvc",  "1970 07 01 0:00:00",
1574        "LLL", "fp", "1970 08 01 0:00:00", "srp",  "1970 08 01 0:00:00",
1575        "LLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159",  "1970 09 01 0:00:00",
1576        "LLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDj", "1970 10 01 0:00:00",
1577        "LLL", "fp", "1970 11 01 0:00:00", "lis", "1970 11 01 0:00:00",
1578        "LLL", "fp", "1970 12 01 0:00:00", "pro", "1970 12 01 0:00:00",
1579    };
1580
1581    expect(EN_DATA, ARRAY_SIZE(EN_DATA), Locale("en", "", ""));
1582    expect(CS_DATA, ARRAY_SIZE(CS_DATA), Locale("cs", "", ""));
1583}
1584
1585void DateFormatTest::TestStandAloneDays()
1586{
1587    const char *EN_DATA[] = {
1588        "yyyy MM dd HH:mm:ss",
1589
1590        "cccc", "fp", "1970 01 04 0:00:00", "Sunday",    "1970 01 04 0:00:00",
1591        "cccc", "fp", "1970 01 05 0:00:00", "Monday",    "1970 01 05 0:00:00",
1592        "cccc", "fp", "1970 01 06 0:00:00", "Tuesday",   "1970 01 06 0:00:00",
1593        "cccc", "fp", "1970 01 07 0:00:00", "Wednesday", "1970 01 07 0:00:00",
1594        "cccc", "fp", "1970 01 01 0:00:00", "Thursday",  "1970 01 01 0:00:00",
1595        "cccc", "fp", "1970 01 02 0:00:00", "Friday",    "1970 01 02 0:00:00",
1596        "cccc", "fp", "1970 01 03 0:00:00", "Saturday",  "1970 01 03 0:00:00",
1597
1598        "ccc", "fp", "1970 01 04 0:00:00", "Sun", "1970 01 04 0:00:00",
1599        "ccc", "fp", "1970 01 05 0:00:00", "Mon", "1970 01 05 0:00:00",
1600        "ccc", "fp", "1970 01 06 0:00:00", "Tue", "1970 01 06 0:00:00",
1601        "ccc", "fp", "1970 01 07 0:00:00", "Wed", "1970 01 07 0:00:00",
1602        "ccc", "fp", "1970 01 01 0:00:00", "Thu", "1970 01 01 0:00:00",
1603        "ccc", "fp", "1970 01 02 0:00:00", "Fri", "1970 01 02 0:00:00",
1604        "ccc", "fp", "1970 01 03 0:00:00", "Sat", "1970 01 03 0:00:00",
1605    };
1606
1607    const char *CS_DATA[] = {
1608        "yyyy MM dd HH:mm:ss",
1609
1610        "cccc", "fp", "1970 01 04 0:00:00", "ned\\u011Ble",       "1970 01 04 0:00:00",
1611        "cccc", "fp", "1970 01 05 0:00:00", "pond\\u011Bl\\u00ED", "1970 01 05 0:00:00",
1612        "cccc", "fp", "1970 01 06 0:00:00", "\\u00FAter\\u00FD",   "1970 01 06 0:00:00",
1613        "cccc", "fp", "1970 01 07 0:00:00", "st\\u0159eda",       "1970 01 07 0:00:00",
1614        "cccc", "fp", "1970 01 01 0:00:00", "\\u010Dtvrtek",      "1970 01 01 0:00:00",
1615        "cccc", "fp", "1970 01 02 0:00:00", "p\\u00E1tek",        "1970 01 02 0:00:00",
1616        "cccc", "fp", "1970 01 03 0:00:00", "sobota",            "1970 01 03 0:00:00",
1617
1618        "ccc", "fp", "1970 01 04 0:00:00", "ne",      "1970 01 04 0:00:00",
1619        "ccc", "fp", "1970 01 05 0:00:00", "po",      "1970 01 05 0:00:00",
1620        "ccc", "fp", "1970 01 06 0:00:00", "\\u00FAt", "1970 01 06 0:00:00",
1621        "ccc", "fp", "1970 01 07 0:00:00", "st",      "1970 01 07 0:00:00",
1622        "ccc", "fp", "1970 01 01 0:00:00", "\\u010Dt", "1970 01 01 0:00:00",
1623        "ccc", "fp", "1970 01 02 0:00:00", "p\\u00E1", "1970 01 02 0:00:00",
1624        "ccc", "fp", "1970 01 03 0:00:00", "so",      "1970 01 03 0:00:00",
1625    };
1626
1627    expect(EN_DATA, ARRAY_SIZE(EN_DATA), Locale("en", "", ""));
1628    expect(CS_DATA, ARRAY_SIZE(CS_DATA), Locale("cs", "", ""));
1629}
1630
1631void DateFormatTest::TestShortDays()
1632{
1633    const char *EN_DATA[] = {
1634        "yyyy MM dd HH:mm:ss",
1635
1636        "EEEEEE, MMM d y", "fp", "2013 01 13 0:00:00", "Su, Jan 13 2013", "2013 01 13 0:00:00",
1637        "EEEEEE, MMM d y", "fp", "2013 01 16 0:00:00", "We, Jan 16 2013", "2013 01 16 0:00:00",
1638        "EEEEEE d",        "fp", "1970 01 17 0:00:00", "Sa 17",           "1970 01 17 0:00:00",
1639        "cccccc d",        "fp", "1970 01 17 0:00:00", "Sa 17",           "1970 01 17 0:00:00",
1640        "cccccc",          "fp", "1970 01 03 0:00:00", "Sa",              "1970 01 03 0:00:00",
1641    };
1642    const char *SV_DATA[] = {
1643        "yyyy MM dd HH:mm:ss",
1644
1645        "EEEEEE d MMM y",  "fp", "2013 01 13 0:00:00", "s\\u00F6 13 jan 2013", "2013 01 13 0:00:00",
1646        "EEEEEE d MMM y",  "fp", "2013 01 16 0:00:00", "on 16 jan 2013",       "2013 01 16 0:00:00",
1647        "EEEEEE d",        "fp", "1970 01 17 0:00:00", "l\\u00F6 17",          "1970 01 17 0:00:00",
1648        "cccccc d",        "fp", "1970 01 17 0:00:00", "L\\u00F6 17",          "1970 01 17 0:00:00",
1649        "cccccc",          "fp", "1970 01 03 0:00:00", "L\\u00F6",             "1970 01 03 0:00:00",
1650    };
1651    expect(EN_DATA, ARRAY_SIZE(EN_DATA), Locale("en", "", ""));
1652    expect(SV_DATA, ARRAY_SIZE(SV_DATA), Locale("sv", "", ""));
1653}
1654
1655void DateFormatTest::TestNarrowNames()
1656{
1657    const char *EN_DATA[] = {
1658            "yyyy MM dd HH:mm:ss",
1659
1660            "yyyy MMMMM dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1661            "yyyy LLLLL dd H:mm:ss",  "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1662
1663            "MMMMM", "1970 01 01 0:00:00", "J",
1664            "MMMMM", "1970 02 01 0:00:00", "F",
1665            "MMMMM", "1970 03 01 0:00:00", "M",
1666            "MMMMM", "1970 04 01 0:00:00", "A",
1667            "MMMMM", "1970 05 01 0:00:00", "M",
1668            "MMMMM", "1970 06 01 0:00:00", "J",
1669            "MMMMM", "1970 07 01 0:00:00", "J",
1670            "MMMMM", "1970 08 01 0:00:00", "A",
1671            "MMMMM", "1970 09 01 0:00:00", "S",
1672            "MMMMM", "1970 10 01 0:00:00", "O",
1673            "MMMMM", "1970 11 01 0:00:00", "N",
1674            "MMMMM", "1970 12 01 0:00:00", "D",
1675
1676            "LLLLL", "1970 01 01 0:00:00", "J",
1677            "LLLLL", "1970 02 01 0:00:00", "F",
1678            "LLLLL", "1970 03 01 0:00:00", "M",
1679            "LLLLL", "1970 04 01 0:00:00", "A",
1680            "LLLLL", "1970 05 01 0:00:00", "M",
1681            "LLLLL", "1970 06 01 0:00:00", "J",
1682            "LLLLL", "1970 07 01 0:00:00", "J",
1683            "LLLLL", "1970 08 01 0:00:00", "A",
1684            "LLLLL", "1970 09 01 0:00:00", "S",
1685            "LLLLL", "1970 10 01 0:00:00", "O",
1686            "LLLLL", "1970 11 01 0:00:00", "N",
1687            "LLLLL", "1970 12 01 0:00:00", "D",
1688
1689            "EEEEE", "1970 01 04 0:00:00", "S",
1690            "EEEEE", "1970 01 05 0:00:00", "M",
1691            "EEEEE", "1970 01 06 0:00:00", "T",
1692            "EEEEE", "1970 01 07 0:00:00", "W",
1693            "EEEEE", "1970 01 01 0:00:00", "T",
1694            "EEEEE", "1970 01 02 0:00:00", "F",
1695            "EEEEE", "1970 01 03 0:00:00", "S",
1696
1697            "ccccc", "1970 01 04 0:00:00", "S",
1698            "ccccc", "1970 01 05 0:00:00", "M",
1699            "ccccc", "1970 01 06 0:00:00", "T",
1700            "ccccc", "1970 01 07 0:00:00", "W",
1701            "ccccc", "1970 01 01 0:00:00", "T",
1702            "ccccc", "1970 01 02 0:00:00", "F",
1703            "ccccc", "1970 01 03 0:00:00", "S",
1704        };
1705
1706        const char *CS_DATA[] = {
1707            "yyyy MM dd HH:mm:ss",
1708
1709            "yyyy LLLLL dd H:mm:ss", "2004 04 10 16:36:31", "2004 d 10 16:36:31",
1710            "yyyy MMMMM dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1711
1712            "MMMMM", "1970 01 01 0:00:00", "1",
1713            "MMMMM", "1970 02 01 0:00:00", "2",
1714            "MMMMM", "1970 03 01 0:00:00", "3",
1715            "MMMMM", "1970 04 01 0:00:00", "4",
1716            "MMMMM", "1970 05 01 0:00:00", "5",
1717            "MMMMM", "1970 06 01 0:00:00", "6",
1718            "MMMMM", "1970 07 01 0:00:00", "7",
1719            "MMMMM", "1970 08 01 0:00:00", "8",
1720            "MMMMM", "1970 09 01 0:00:00", "9",
1721            "MMMMM", "1970 10 01 0:00:00", "10",
1722            "MMMMM", "1970 11 01 0:00:00", "11",
1723            "MMMMM", "1970 12 01 0:00:00", "12",
1724
1725            "LLLLL", "1970 01 01 0:00:00", "l",
1726            "LLLLL", "1970 02 01 0:00:00", "\\u00FA",
1727            "LLLLL", "1970 03 01 0:00:00", "b",
1728            "LLLLL", "1970 04 01 0:00:00", "d",
1729            "LLLLL", "1970 05 01 0:00:00", "k",
1730            "LLLLL", "1970 06 01 0:00:00", "\\u010D",
1731            "LLLLL", "1970 07 01 0:00:00", "\\u010D",
1732            "LLLLL", "1970 08 01 0:00:00", "s",
1733            "LLLLL", "1970 09 01 0:00:00", "z",
1734            "LLLLL", "1970 10 01 0:00:00", "\\u0159",
1735            "LLLLL", "1970 11 01 0:00:00", "l",
1736            "LLLLL", "1970 12 01 0:00:00", "p",
1737
1738            "EEEEE", "1970 01 04 0:00:00", "N",
1739            "EEEEE", "1970 01 05 0:00:00", "P",
1740            "EEEEE", "1970 01 06 0:00:00", "\\u00DA",
1741            "EEEEE", "1970 01 07 0:00:00", "S",
1742            "EEEEE", "1970 01 01 0:00:00", "\\u010C",
1743            "EEEEE", "1970 01 02 0:00:00", "P",
1744            "EEEEE", "1970 01 03 0:00:00", "S",
1745
1746            "ccccc", "1970 01 04 0:00:00", "N",
1747            "ccccc", "1970 01 05 0:00:00", "P",
1748            "ccccc", "1970 01 06 0:00:00", "\\u00DA",
1749            "ccccc", "1970 01 07 0:00:00", "S",
1750            "ccccc", "1970 01 01 0:00:00", "\\u010C",
1751            "ccccc", "1970 01 02 0:00:00", "P",
1752            "ccccc", "1970 01 03 0:00:00", "S",
1753        };
1754
1755      expectFormat(EN_DATA, ARRAY_SIZE(EN_DATA), Locale("en", "", ""));
1756      expectFormat(CS_DATA, ARRAY_SIZE(CS_DATA), Locale("cs", "", ""));
1757}
1758
1759void DateFormatTest::TestEras()
1760{
1761    const char *EN_DATA[] = {
1762        "yyyy MM dd",
1763
1764        "MMMM dd yyyy G",    "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
1765        "MMMM dd yyyy GG",   "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
1766        "MMMM dd yyyy GGG",  "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
1767        "MMMM dd yyyy GGGG", "fp", "1951 07 17", "July 17 1951 Anno Domini", "1951 07 17",
1768
1769        "MMMM dd yyyy G",    "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
1770        "MMMM dd yyyy GG",   "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
1771        "MMMM dd yyyy GGG",  "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
1772        "MMMM dd yyyy GGGG", "fp", "-438 07 17", "July 17 0439 Before Christ", "-438 07 17",
1773    };
1774
1775    expect(EN_DATA, ARRAY_SIZE(EN_DATA), Locale("en", "", ""));
1776}
1777
1778void DateFormatTest::TestQuarters()
1779{
1780    const char *EN_DATA[] = {
1781        "yyyy MM dd",
1782
1783        "Q",    "fp", "1970 01 01", "1",           "1970 01 01",
1784        "QQ",   "fp", "1970 04 01", "02",          "1970 04 01",
1785        "QQQ",  "fp", "1970 07 01", "Q3",          "1970 07 01",
1786        "QQQQ", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1787
1788        "q",    "fp", "1970 01 01", "1",           "1970 01 01",
1789        "qq",   "fp", "1970 04 01", "02",          "1970 04 01",
1790        "qqq",  "fp", "1970 07 01", "Q3",          "1970 07 01",
1791        "qqqq", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1792    };
1793
1794    expect(EN_DATA, ARRAY_SIZE(EN_DATA), Locale("en", "", ""));
1795}
1796
1797/**
1798 * Test parsing.  Input is an array that starts with the following
1799 * header:
1800 *
1801 * [0]   = pattern string to parse [i+2] with
1802 *
1803 * followed by test cases, each of which is 3 array elements:
1804 *
1805 * [i]   = pattern, or NULL to reuse prior pattern
1806 * [i+1] = input string
1807 * [i+2] = expected parse result (parsed with pattern [0])
1808 *
1809 * If expect parse failure, then [i+2] should be NULL.
1810 */
1811void DateFormatTest::expectParse(const char** data, int32_t data_length,
1812                                 const Locale& loc) {
1813    const UDate FAIL = (UDate) -1;
1814    const UnicodeString FAIL_STR("parse failure");
1815    int32_t i = 0;
1816
1817    UErrorCode ec = U_ZERO_ERROR;
1818    SimpleDateFormat fmt("", loc, ec);
1819    SimpleDateFormat ref(data[i++], loc, ec);
1820    SimpleDateFormat gotfmt("G yyyy MM dd HH:mm:ss z", loc, ec);
1821    if (U_FAILURE(ec)) {
1822        dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1823        return;
1824    }
1825
1826    const char* currentPat = NULL;
1827    while (i<data_length) {
1828        const char* pattern  = data[i++];
1829        const char* input    = data[i++];
1830        const char* expected = data[i++];
1831
1832        ec = U_ZERO_ERROR;
1833        if (pattern != NULL) {
1834            fmt.applyPattern(pattern);
1835            currentPat = pattern;
1836        }
1837        UDate got = fmt.parse(input, ec);
1838        UnicodeString gotstr(FAIL_STR);
1839        if (U_FAILURE(ec)) {
1840            got = FAIL;
1841        } else {
1842            gotstr.remove();
1843            gotfmt.format(got, gotstr);
1844        }
1845
1846        UErrorCode ec2 = U_ZERO_ERROR;
1847        UDate exp = FAIL;
1848        UnicodeString expstr(FAIL_STR);
1849        if (expected != NULL) {
1850            expstr = expected;
1851            exp = ref.parse(expstr, ec2);
1852            if (U_FAILURE(ec2)) {
1853                // This only happens if expected is in wrong format --
1854                // should never happen once test is debugged.
1855                errln("FAIL: Internal test error");
1856                return;
1857            }
1858        }
1859
1860        if (got == exp) {
1861            logln((UnicodeString)"Ok: " + input + " x " +
1862                  currentPat + " => " + gotstr);
1863        } else {
1864            errln((UnicodeString)"FAIL: " + input + " x " +
1865                  currentPat + " => " + gotstr + ", expected " +
1866                  expstr);
1867        }
1868    }
1869}
1870
1871/**
1872 * Test formatting and parsing.  Input is an array that starts
1873 * with the following header:
1874 *
1875 * [0]   = pattern string to parse [i+2] with
1876 *
1877 * followed by test cases, each of which is 3 array elements:
1878 *
1879 * [i]   = pattern, or null to reuse prior pattern
1880 * [i+1] = control string, either "fp", "pf", or "F".
1881 * [i+2..] = data strings
1882 *
1883 * The number of data strings depends on the control string.
1884 * Examples:
1885 * 1. "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.56", "2004 03 10 16:36:31.560",
1886 * 'f': Format date [i+2] (as parsed using pattern [0]) and expect string [i+3].
1887 * 'p': Parse string [i+3] and expect date [i+4].
1888 *
1889 * 2. "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567"
1890 * 'F': Format date [i+2] and expect string [i+3],
1891 *      then parse string [i+3] and expect date [i+2].
1892 *
1893 * 3. "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5670",
1894 * 'p': Parse string [i+2] and expect date [i+3].
1895 * 'f': Format date [i+3] and expect string [i+4].
1896 */
1897void DateFormatTest::expect(const char** data, int32_t data_length,
1898                            const Locale& loc) {
1899    int32_t i = 0;
1900    UErrorCode ec = U_ZERO_ERROR;
1901    UnicodeString str, str2;
1902    SimpleDateFormat fmt("", loc, ec);
1903    SimpleDateFormat ref(data[i++], loc, ec);
1904    SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
1905    if (U_FAILURE(ec)) {
1906        dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1907        return;
1908    }
1909
1910    UnicodeString currentPat;
1911    while (i<data_length) {
1912        const char* pattern  = data[i++];
1913        if (pattern != NULL) {
1914            fmt.applyPattern(pattern);
1915            currentPat = pattern;
1916        }
1917
1918        const char* control = data[i++];
1919
1920        if (uprv_strcmp(control, "fp") == 0) {
1921            // 'f'
1922            const char* datestr = data[i++];
1923            const char* string = data[i++];
1924            UDate date = ref.parse(ctou(datestr), ec);
1925            if (!assertSuccess("parse", ec)) return;
1926            assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
1927                         ctou(string),
1928                         fmt.format(date, str.remove()));
1929            // 'p'
1930            datestr = data[i++];
1931            date = ref.parse(ctou(datestr), ec);
1932            if (!assertSuccess("parse", ec)) return;
1933            UDate parsedate = fmt.parse(ctou(string), ec);
1934            if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
1935                assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
1936                             univ.format(date, str.remove()),
1937                             univ.format(parsedate, str2.remove()));
1938            }
1939        }
1940
1941        else if (uprv_strcmp(control, "pf") == 0) {
1942            // 'p'
1943            const char* string = data[i++];
1944            const char* datestr = data[i++];
1945            UDate date = ref.parse(ctou(datestr), ec);
1946            if (!assertSuccess("parse", ec)) return;
1947            UDate parsedate = fmt.parse(ctou(string), ec);
1948            if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
1949                assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
1950                             univ.format(date, str.remove()),
1951                             univ.format(parsedate, str2.remove()));
1952            }
1953            // 'f'
1954            string = data[i++];
1955            assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
1956                         ctou(string),
1957                         fmt.format(date, str.remove()));
1958        }
1959
1960        else if (uprv_strcmp(control, "F") == 0) {
1961            const char* datestr  = data[i++];
1962            const char* string   = data[i++];
1963            UDate date = ref.parse(ctou(datestr), ec);
1964            if (!assertSuccess("parse", ec)) return;
1965            assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
1966                         ctou(string),
1967                         fmt.format(date, str.remove()));
1968
1969            UDate parsedate = fmt.parse(string, ec);
1970            if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
1971                assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
1972                             univ.format(date, str.remove()),
1973                             univ.format(parsedate, str2.remove()));
1974            }
1975        }
1976
1977        else {
1978            errln((UnicodeString)"FAIL: Invalid control string " + control);
1979            return;
1980        }
1981    }
1982}
1983
1984/**
1985 * Test formatting.  Input is an array that starts
1986 * with the following header:
1987 *
1988 * [0]   = pattern string to parse [i+2] with
1989 *
1990 * followed by test cases, each of which is 3 array elements:
1991 *
1992 * [i]   = pattern, or null to reuse prior pattern
1993 * [i+1] = data string a
1994 * [i+2] = data string b
1995 *
1996 * Examples:
1997 * Format date [i+1] and expect string [i+2].
1998 *
1999 * "y/M/d H:mm:ss.SSSS", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567"
2000 */
2001void DateFormatTest::expectFormat(const char** data, int32_t data_length,
2002                            const Locale& loc) {
2003    int32_t i = 0;
2004    UErrorCode ec = U_ZERO_ERROR;
2005    UnicodeString str, str2;
2006    SimpleDateFormat fmt("", loc, ec);
2007    SimpleDateFormat ref(data[i++], loc, ec);
2008    SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2009    if (U_FAILURE(ec)) {
2010        dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2011        return;
2012    }
2013
2014    UnicodeString currentPat;
2015
2016    while (i<data_length) {
2017        const char* pattern  = data[i++];
2018        if (pattern != NULL) {
2019            fmt.applyPattern(pattern);
2020            currentPat = pattern;
2021        }
2022
2023        const char* datestr = data[i++];
2024        const char* string = data[i++];
2025        UDate date = ref.parse(ctou(datestr), ec);
2026        if (!assertSuccess("parse", ec)) return;
2027        assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2028                        ctou(string),
2029                        fmt.format(date, str.remove()));
2030    }
2031}
2032
2033void DateFormatTest::TestGenericTime() {
2034  const Locale en("en");
2035  // Note: We no longer parse strings in different styles.
2036/*
2037  const char* ZDATA[] = {
2038        "yyyy MM dd HH:mm zzz",
2039        // round trip
2040        "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2041        "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2042        "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2043        "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2044        // non-generic timezone string influences dst offset even if wrong for date/time
2045        "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
2046        "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 Pacific Time",
2047        "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
2048        "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 Pacific Time",
2049        // generic timezone generates dst offset appropriate for local time
2050        "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2051        "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2052        "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2053        "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2054        // daylight savings time transition edge cases.
2055        // time to parse does not really exist, PT interpreted as earlier time
2056        "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2057        "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2058        "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
2059        "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2060        "y/M/d H:mm v", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2061        "y/M/d H:mm v", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT",
2062        "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2063        // time to parse is ambiguous, PT interpreted as later time
2064        "y/M/d H:mm zzz", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PST",
2065        "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30  01:30 PST", "2005/10/30 1:30 PT",
2066        "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2067
2068        "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2069        "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2070        "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
2071        "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2072        "y/M/d H:mm v", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2073        "y/M/d H:mm v", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PT",
2074        "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2075  };
2076*/
2077  const char* ZDATA[] = {
2078        "yyyy MM dd HH:mm zzz",
2079        // round trip
2080        "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2081        "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2082        "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2083        "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2084        // non-generic timezone string influences dst offset even if wrong for date/time
2085        "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
2086        "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
2087        // generic timezone generates dst offset appropriate for local time
2088        "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PST", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2089        "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 Pacific Time", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2090        "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2091        "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 Pacific Time", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2092        // daylight savings time transition edge cases.
2093        // time to parse does not really exist, PT interpreted as earlier time
2094        "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2095        "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
2096        "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2097        "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2098        // time to parse is ambiguous, PT interpreted as later time
2099        "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30  01:30 PST", "2005/10/30 1:30 PT",
2100        "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2101
2102        "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2103        "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
2104        "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2105        "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2106  };
2107
2108  const int32_t ZDATA_length = sizeof(ZDATA)/ sizeof(ZDATA[0]);
2109  expect(ZDATA, ZDATA_length, en);
2110
2111  UErrorCode status = U_ZERO_ERROR;
2112
2113  logln("cross format/parse tests");    // Note: We no longer support cross format/parse
2114  UnicodeString basepat("yy/MM/dd H:mm ");
2115  SimpleDateFormat formats[] = {
2116    SimpleDateFormat(basepat + "vvv", en, status),
2117    SimpleDateFormat(basepat + "vvvv", en, status),
2118    SimpleDateFormat(basepat + "zzz", en, status),
2119    SimpleDateFormat(basepat + "zzzz", en, status)
2120  };
2121  if (U_FAILURE(status)) {
2122    dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(status));
2123    return;
2124  }
2125  const int32_t formats_length = sizeof(formats)/sizeof(formats[0]);
2126
2127  UnicodeString test;
2128  SimpleDateFormat univ("yyyy MM dd HH:mm zzz", en, status);
2129  ASSERT_OK(status);
2130  const UnicodeString times[] = {
2131    "2004 01 02 03:04 PST",
2132    "2004 07 08 09:10 PDT"
2133  };
2134  int32_t times_length = sizeof(times)/sizeof(times[0]);
2135  for (int i = 0; i < times_length; ++i) {
2136    UDate d = univ.parse(times[i], status);
2137    logln(UnicodeString("\ntime: ") + d);
2138    for (int j = 0; j < formats_length; ++j) {
2139      test.remove();
2140      formats[j].format(d, test);
2141      logln("\ntest: '" + test + "'");
2142      for (int k = 0; k < formats_length; ++k) {
2143        UDate t = formats[k].parse(test, status);
2144        if (U_SUCCESS(status)) {
2145          if (d != t) {
2146            errln((UnicodeString)"FAIL: format " + k +
2147                  " incorrectly parsed output of format " + j +
2148                  " (" + test + "), returned " +
2149                  dateToString(t) + " instead of " + dateToString(d));
2150          } else {
2151            logln((UnicodeString)"OK: format " + k + " parsed ok");
2152          }
2153        } else if (status == U_PARSE_ERROR) {
2154          errln((UnicodeString)"FAIL: format " + k +
2155                " could not parse output of format " + j +
2156                " (" + test + ")");
2157        }
2158      }
2159    }
2160  }
2161}
2162
2163void DateFormatTest::TestGenericTimeZoneOrder() {
2164  // generic times should parse the same no matter what the placement of the time zone string
2165
2166  // Note: We no longer support cross style format/parse
2167
2168  //const char* XDATA[] = {
2169  //  "yyyy MM dd HH:mm zzz",
2170  //  // standard time, explicit daylight/standard
2171  //  "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2172  //  "y/M/d zzz H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
2173  //  "zzz y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
2174
2175  //  // standard time, generic
2176  //  "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2177  //  "y/M/d vvvv H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
2178  //  "vvvv y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
2179
2180  //  // dahylight time, explicit daylight/standard
2181  //  "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2182  //  "y/M/d zzz H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
2183  //  "zzz y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
2184
2185  //  // daylight time, generic
2186  //  "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2187  //  "y/M/d vvvv H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 Pacific Time 1:00",
2188  //  "vvvv y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "Pacific Time 2004/7/1 1:00",
2189  //};
2190  const char* XDATA[] = {
2191    "yyyy MM dd HH:mm zzz",
2192    // standard time, explicit daylight/standard
2193    "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PST", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2194    "y/M/d zzz H:mm", "pf", "2004/1/1 PST 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
2195    "zzz y/M/d H:mm", "pf", "PST 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
2196
2197    // standard time, generic
2198    "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 Pacific Time", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2199    "y/M/d vvvv H:mm", "pf", "2004/1/1 Pacific Time 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
2200    "vvvv y/M/d H:mm", "pf", "Pacific Time 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
2201
2202    // dahylight time, explicit daylight/standard
2203    "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2204    "y/M/d zzz H:mm", "pf", "2004/7/1 PDT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
2205    "zzz y/M/d H:mm", "pf", "PDT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
2206
2207    // daylight time, generic
2208    "y/M/d H:mm v", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PT",
2209    "y/M/d v H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PT 1:00",
2210    "v y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PT 2004/7/1 1:00",
2211  };
2212  const int32_t XDATA_length = sizeof(XDATA)/sizeof(XDATA[0]);
2213  Locale en("en");
2214  expect(XDATA, XDATA_length, en);
2215}
2216
2217void DateFormatTest::TestZTimeZoneParsing(void) {
2218    UErrorCode status = U_ZERO_ERROR;
2219    const Locale en("en");
2220    UnicodeString test;
2221    //SimpleDateFormat univ("yyyy-MM-dd'T'HH:mm Z", en, status);
2222    SimpleDateFormat univ("HH:mm Z", en, status);
2223    if (failure(status, "construct SimpleDateFormat", TRUE)) return;
2224    const TimeZone *t = TimeZone::getGMT();
2225    univ.setTimeZone(*t);
2226
2227    univ.setLenient(false);
2228    ParsePosition pp(0);
2229    struct {
2230        UnicodeString input;
2231        UnicodeString expected_result;
2232    } tests[] = {
2233        { "11:00 -0200", "13:00 +0000" },
2234        { "11:00 +0200", "09:00 +0000" },
2235        { "11:00 +0400", "07:00 +0000" },
2236        { "11:00 +0530", "05:30 +0000" }
2237    };
2238
2239    UnicodeString result;
2240    int32_t tests_length = sizeof(tests)/sizeof(tests[0]);
2241    for (int i = 0; i < tests_length; ++i) {
2242        pp.setIndex(0);
2243        UDate d = univ.parse(tests[i].input, pp);
2244        if(pp.getIndex() != tests[i].input.length()){
2245            errln("Test %i: setZoneString() did not succeed. Consumed: %i instead of %i",
2246                  i, pp.getIndex(), tests[i].input.length());
2247            return;
2248        }
2249        result.remove();
2250        univ.format(d, result);
2251        if(result != tests[i].expected_result) {
2252            errln("Expected " + tests[i].expected_result
2253                  + " got " + result);
2254            return;
2255        }
2256        logln("SUCCESS: Parsed " + tests[i].input
2257              + " got " + result
2258              + " expected " + tests[i].expected_result);
2259    }
2260}
2261
2262void DateFormatTest::TestHost(void)
2263{
2264#if U_PLATFORM_HAS_WIN32_API
2265    Win32DateTimeTest::testLocales(this);
2266#endif
2267}
2268
2269// Relative Date Tests
2270
2271void DateFormatTest::TestRelative(int daysdelta,
2272                                  const Locale& loc,
2273                                  const char *expectChars) {
2274    char banner[25];
2275    sprintf(banner, "%d", daysdelta);
2276    UnicodeString bannerStr(banner, "");
2277
2278    UErrorCode status = U_ZERO_ERROR;
2279
2280    FieldPosition pos(0);
2281    UnicodeString test;
2282    Locale en("en");
2283    DateFormat *fullrelative = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2284
2285    if (fullrelative == NULL) {
2286        dataerrln("DateFormat::createDateInstance(DateFormat::kFullRelative, %s) returned NULL", loc.getName());
2287        return;
2288    }
2289
2290    DateFormat *full         = DateFormat::createDateInstance(DateFormat::kFull        , loc);
2291
2292    if (full == NULL) {
2293        errln("DateFormat::createDateInstance(DateFormat::kFull, %s) returned NULL", loc.getName());
2294        return;
2295    }
2296
2297    DateFormat *en_full =         DateFormat::createDateInstance(DateFormat::kFull,         en);
2298
2299    if (en_full == NULL) {
2300        errln("DateFormat::createDateInstance(DateFormat::kFull, en) returned NULL");
2301        return;
2302    }
2303
2304    DateFormat *en_fulltime =         DateFormat::createDateTimeInstance(DateFormat::kFull,DateFormat::kFull,en);
2305
2306    if (en_fulltime == NULL) {
2307        errln("DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, en) returned NULL");
2308        return;
2309    }
2310
2311    UnicodeString result;
2312    UnicodeString normalResult;
2313    UnicodeString expect;
2314    UnicodeString parseResult;
2315
2316    Calendar *c = Calendar::createInstance(status);
2317
2318    // Today = Today
2319    c->setTime(Calendar::getNow(), status);
2320    if(daysdelta != 0) {
2321        c->add(Calendar::DATE,daysdelta,status);
2322    }
2323    ASSERT_OK(status);
2324
2325    // calculate the expected string
2326    if(expectChars != NULL) {
2327        expect = expectChars;
2328    } else {
2329        full->format(*c, expect, pos); // expected = normal full
2330    }
2331
2332    fullrelative   ->format(*c, result, pos);
2333    en_full        ->format(*c, normalResult, pos);
2334
2335    if(result != expect) {
2336        errln("FAIL: Relative Format ["+bannerStr+"] of "+normalResult+" failed, expected "+expect+" but got " + result);
2337    } else {
2338        logln("PASS: Relative Format ["+bannerStr+"] of "+normalResult+" got " + result);
2339    }
2340
2341
2342    //verify
2343    UDate d = fullrelative->parse(result, status);
2344    ASSERT_OK(status);
2345
2346    UnicodeString parseFormat; // parse rel->format full
2347    en_full->format(d, parseFormat, status);
2348
2349    UnicodeString origFormat;
2350    en_full->format(*c, origFormat, pos);
2351
2352    if(parseFormat!=origFormat) {
2353        errln("FAIL: Relative Parse ["+bannerStr+"] of "+result+" failed, expected "+parseFormat+" but got "+origFormat);
2354    } else {
2355        logln("PASS: Relative Parse ["+bannerStr+"] of "+result+" passed, got "+parseFormat);
2356    }
2357
2358    delete full;
2359    delete fullrelative;
2360    delete en_fulltime;
2361    delete en_full;
2362    delete c;
2363}
2364
2365
2366void DateFormatTest::TestRelative(void)
2367{
2368    Locale en("en");
2369    TestRelative( 0, en, "today");
2370    TestRelative(-1, en, "yesterday");
2371    TestRelative( 1, en, "tomorrow");
2372    TestRelative( 2, en, NULL);
2373    TestRelative( -2, en, NULL);
2374    TestRelative( 3, en, NULL);
2375    TestRelative( -3, en, NULL);
2376    TestRelative( 300, en, NULL);
2377    TestRelative( -300, en, NULL);
2378}
2379
2380void DateFormatTest::TestRelativeClone(void)
2381{
2382    /*
2383    Verify that a cloned formatter gives the same results
2384    and is useable after the original has been deleted.
2385    */
2386    UErrorCode status = U_ZERO_ERROR;
2387    Locale loc("en");
2388    UDate now = Calendar::getNow();
2389    DateFormat *full = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2390    if (full == NULL) {
2391        dataerrln("FAIL: Can't create Relative date instance");
2392        return;
2393    }
2394    UnicodeString result1;
2395    full->format(now, result1, status);
2396    Format *fullClone = full->clone();
2397    delete full;
2398    full = NULL;
2399
2400    UnicodeString result2;
2401    fullClone->format(now, result2, status);
2402    ASSERT_OK(status);
2403    if (result1 != result2) {
2404        errln("FAIL: Clone returned different result from non-clone.");
2405    }
2406    delete fullClone;
2407}
2408
2409void DateFormatTest::TestHostClone(void)
2410{
2411    /*
2412    Verify that a cloned formatter gives the same results
2413    and is useable after the original has been deleted.
2414    */
2415    // This is mainly important on Windows.
2416    UErrorCode status = U_ZERO_ERROR;
2417    Locale loc("en_US@compat=host");
2418    UDate now = Calendar::getNow();
2419    DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull, loc);
2420    if (full == NULL) {
2421        dataerrln("FAIL: Can't create Relative date instance");
2422        return;
2423    }
2424    UnicodeString result1;
2425    full->format(now, result1, status);
2426    Format *fullClone = full->clone();
2427    delete full;
2428    full = NULL;
2429
2430    UnicodeString result2;
2431    fullClone->format(now, result2, status);
2432    ASSERT_OK(status);
2433    if (result1 != result2) {
2434        errln("FAIL: Clone returned different result from non-clone.");
2435    }
2436    delete fullClone;
2437}
2438
2439void DateFormatTest::TestTimeZoneDisplayName()
2440{
2441    // This test data was ported from ICU4J.  Don't know why the 6th column in there because it's not being
2442    // used currently.
2443    const char *fallbackTests[][6]  = {
2444        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2445        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2446        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZZ", "-08:00", "-8:00" },
2447        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "PST", "America/Los_Angeles" },
2448        { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Pacific Standard Time", "America/Los_Angeles" },
2449        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2450        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2451        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "PDT", "America/Los_Angeles" },
2452        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Pacific Daylight Time", "America/Los_Angeles" },
2453        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "PT", "America/Los_Angeles" },
2454        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Pacific Time", "America/Los_Angeles" },
2455        { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "Los Angeles Time", "America/Los_Angeles" },
2456        { "en_GB", "America/Los_Angeles", "2004-01-15T12:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2457        { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "Z", "-0700", "-7:00" },
2458        { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2459        { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2460        { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2461        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2462        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2463        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2464        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2465        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "v", "MST", "America/Phoenix" },
2466        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "vvvv", "Mountain Standard Time", "America/Phoenix" },
2467        { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "VVVV", "Phoenix Time", "America/Phoenix" },
2468
2469        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2470        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2471        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2472        { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2473        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2474        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2475        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2476        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2477        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2478        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2479        { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2480
2481        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2482        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2483        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2484        { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2485        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2486        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2487        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2488        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2489        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2490        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2491        { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2492
2493        { "en", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2494        { "en", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2495        { "en", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2496        { "en", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Cuba Standard Time", "-5:00" },
2497        { "en", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2498        { "en", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2499        { "en", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2500        { "en", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Cuba Daylight Time", "-4:00" },
2501        { "en", "America/Havana", "2004-07-15T00:00:00Z", "v", "Cuba Time", "America/Havana" },
2502        { "en", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Cuba Time", "America/Havana" },
2503        { "en", "America/Havana", "2004-07-15T00:00:00Z", "VVVV", "Cuba Time", "America/Havana" },
2504
2505        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2506        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2507        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2508        { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2509        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2510        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2511        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2512        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2513        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2514        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2515        { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2516
2517        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2518        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2519        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2520        { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2521        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2522        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2523        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2524        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2525        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2526        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2527        { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2528
2529        { "en", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2530        { "en", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2531        { "en", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2532        { "en", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Greenwich Mean Time", "+0:00" },
2533        { "en", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2534        { "en", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2535        { "en", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "Europe/London" },
2536        { "en", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "British Summer Time", "Europe/London" },
2537    // icu en.txt has exemplar city for this time zone
2538        { "en", "Europe/London", "2004-07-15T00:00:00Z", "v", "United Kingdom Time", "Europe/London" },
2539        { "en", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "United Kingdom Time", "Europe/London" },
2540        { "en", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "United Kingdom Time", "Europe/London" },
2541
2542        { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2543        { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2544        { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2545        { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2546        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2547        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2548        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2549        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2550        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2551        { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2552
2553        // JB#5150
2554        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2555        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2556        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2557        { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2558        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2559        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2560        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2561        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2562        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "India Time", "Asia/Calcutta" },
2563        { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "India Standard Time", "Asia/Calcutta" },
2564
2565        // Proper CLDR primary zone support #9733
2566        { "en", "Asia/Shanghai", "2013-01-01T00:00:00Z", "VVVV", "China Time", "Asia/Shanghai" },
2567        { "en", "Asia/Harbin", "2013-01-01T00:00:00Z", "VVVV", "Harbin Time", "Asia/Harbin" },
2568
2569        // ==========
2570
2571        { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2572        { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2573        { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2574        { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Normalzeit", "-8:00" },
2575        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2576        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2577        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2578        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Sommerzeit", "-7:00" },
2579        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles Zeit", "America/Los_Angeles" },
2580        { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Nordamerikanische Westk\\u00fcstenzeit", "America/Los_Angeles" },
2581
2582        { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2583        { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2584        { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2585        { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2586        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2587        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2588        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2589        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2590        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2591        { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2592
2593        { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2594        { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2595        { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2596        { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2597        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2598        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2599        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2600        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2601        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2602        { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2603
2604        { "de", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2605        { "de", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2606        { "de", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2607        { "de", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Kubanische Normalzeit", "-5:00" },
2608        { "de", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2609        { "de", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2610        { "de", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2611        { "de", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Kubanische Sommerzeit", "-4:00" },
2612        { "de", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2613        { "de", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2614        // added to test proper fallback of country name
2615        { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2616        { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2617
2618        { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2619        { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2620        { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2621        { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2622        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2623        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2624        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2625        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2626        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2627        { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2628
2629        { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2630        { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2631        { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2632        { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2633        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2634        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2635        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2636        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2637        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2638        { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2639
2640        { "de", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2641        { "de", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2642        { "de", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2643        { "de", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Mittlere Greenwich-Zeit", "+0:00" },
2644        { "de", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2645        { "de", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2646        { "de", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2647        { "de", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "Britische Sommerzeit", "+1:00" },
2648        { "de", "Europe/London", "2004-07-15T00:00:00Z", "v", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2649        { "de", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2650
2651        { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2652        { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2653        { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2654        { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2655        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2656        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2657        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2658        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2659        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2660        { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2661
2662        // JB#5150
2663        { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2664        { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2665        { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2666        { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2667        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2668        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2669        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2670        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2671        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "Indien Zeit", "Asia/Calcutta" },
2672        { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "Indische Zeit", "Asia/Calcutta" },
2673
2674        // ==========
2675
2676        { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2677        { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2678        { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2679        { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u6807\\u51c6\\u65f6\\u95f4", "America/Los_Angeles" },
2680        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2681        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2682        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
2683        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u590f\\u4ee4\\u65f6\\u95f4", "America/Los_Angeles" },
2684    // icu zh.txt has exemplar city for this time zone
2685        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4", "America/Los_Angeles" },
2686        { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u65f6\\u95f4", "America/Los_Angeles" },
2687
2688        { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2689        { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2690        { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2691        { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2692        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2693        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2694        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2695        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2696        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2697        { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2698
2699        { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2700        { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2701        { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2702        { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2703        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2704        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2705        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2706        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2707        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2708        { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2709
2710        { "zh", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2711        { "zh", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2712        { "zh", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2713        { "zh", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u6807\\u51c6\\u65f6\\u95f4", "-5:00" },
2714        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2715        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2716        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2717        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u590f\\u4ee4\\u65f6\\u95f4", "-4:00" },
2718        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2719        { "zh", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2720
2721        { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2722        { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2723        { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2724        { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2725        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2726        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2727        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2728        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2729    // icu zh.txt does not have info for this time zone
2730        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2731        { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2732
2733        { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2734        { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2735        { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2736        { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2737        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2738        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2739        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2740        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2741        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2742        { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2743
2744        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2745        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2746        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2747        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2748        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2749        { "zh", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u683C\\u6797\\u5C3C\\u6CBB\\u6807\\u51C6\\u65F6\\u95F4", "+0:00" },
2750        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2751        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2752        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2753        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u4ee4\\u65f6\\u95f4", "+1:00" },
2754        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2755        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2756        { "zh", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2757
2758        { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2759        { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2760        { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2761        { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2762        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2763        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2764        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2765        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2766        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2767        { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2768
2769        // JB#5150
2770        { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2771        { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2772        { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2773        { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2774        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2775        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2776        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2777        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2778        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2779        { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2780
2781        // Proper CLDR primary zone support #9733
2782        { "zh", "Asia/Shanghai", "2013-01-01T00:00:00Z", "VVVV", "\\u4e2d\\u56fd\\u65f6\\u95f4", "Asia/Shanghai" },
2783        { "zh", "Asia/Harbin", "2013-01-01T00:00:00Z", "VVVV", "\\u54c8\\u5c14\\u6ee8\\u65f6\\u95f4", "Asia/Harbin" },
2784
2785        // ==========
2786
2787        { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2788        { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2789        { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2790        { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-8:00" },
2791        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2792        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2793        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2794        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "-7:00" },
2795        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v",  "\\u0932\\u0949\\u0938 \\u090f\\u0902\\u091c\\u093f\\u0932\\u094d\\u0938 \\u0938\\u092e\\u092f", "America/Los_Angeles" },
2796        { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u0938\\u092e\\u092f", "America/Los_Angeles" },
2797
2798        { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2799        { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2800        { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2801        { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2802        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2803        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2804        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2805        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2806        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u092C\\u094D\\u092F\\u0942\\u0928\\u0938 \\u0906\\u092F\\u0930\\u0938 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2807        { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2808
2809        { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2810        { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2811        { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2812        { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2813        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2814        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2815        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2816        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2817        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u092C\\u094D\\u092F\\u0942\\u0928\\u0938 \\u0906\\u092F\\u0930\\u0938 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2818        { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2819
2820        { "hi", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2821        { "hi", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2822        { "hi", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2823        { "hi", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-5:00" },
2824        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2825        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2826        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2827        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "-4:00" },
2828        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092E\\u092F", "America/Havana" },
2829        { "hi", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092e\\u092f", "America/Havana" },
2830
2831        { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2832        { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2833        { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2834        { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "+11:00" },
2835        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2836        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2837        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2838        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "+10:00" },
2839        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
2840        { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0911\\u0938\\u094d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e \\u0938\\u092e\\u092f", "Australia/Sydney" },
2841
2842        { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2843        { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2844        { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2845        { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "+11:00" },
2846        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2847        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2848        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2849        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "+10:00" },
2850        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
2851        { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0911\\u0938\\u094d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e \\u0938\\u092e\\u092f", "Australia/Sydney" },
2852
2853        { "hi", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2854        { "hi", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2855        { "hi", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2856        { "hi", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u0917\\u094d\\u0930\\u0940\\u0928\\u0935\\u093f\\u091a \\u092e\\u0940\\u0928 \\u091f\\u093e\\u0907\\u092e", "+0:00" },
2857        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2858        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2859        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2860        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u092c\\u094d\\u0930\\u093f\\u091f\\u093f\\u0936 \\u0917\\u094d\\u0930\\u0940\\u0937\\u094d\\u092e\\u0915\\u093e\\u0932\\u0940\\u0928 \\u0938\\u092e\\u092f", "+1:00" },
2861        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u092f\\u0942\\u0928\\u093e\\u0907\\u091f\\u0947\\u0921 \\u0915\\u093f\\u0902\\u0917\\u0921\\u092e \\u0938\\u092e\\u092f", "Europe/London" },
2862        { "hi", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u092f\\u0942\\u0928\\u093e\\u0907\\u091f\\u0947\\u0921 \\u0915\\u093f\\u0902\\u0917\\u0921\\u092e \\u0938\\u092e\\u092f", "Europe/London" },
2863
2864        { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2865        { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2866        { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2867        { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2868        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2869        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2870        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2871        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2872        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2873        { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2874
2875        { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2876        { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2877        { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "IST", "+5:30" },
2878        { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u0938\\u092E\\u092F", "+5:30" },
2879        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2880        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2881        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "IST", "+05:30" },
2882        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u0938\\u092E\\u092F", "+5:30" },
2883        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IST", "Asia/Calcutta" },
2884        { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u0938\\u092E\\u092F", "Asia/Calcutta" },
2885
2886        // ==========
2887
2888        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2889        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-08:00", "-8:00" },
2890        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-8", "America/Los_Angeles" },
2891        { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
2892        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2893        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-07:00", "-7:00" },
2894        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-7", "America/Los_Angeles" },
2895        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
2896    // icu bg.txt has exemplar city for this time zone
2897        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
2898        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
2899        { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
2900
2901        { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2902        { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
2903        { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
2904        { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
2905        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2906        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
2907        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
2908        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
2909        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
2910        { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Buenos_Aires" },
2911
2912        { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2913        { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
2914        { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
2915        { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
2916        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2917        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
2918        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
2919        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
2920    // icu bg.txt does not have info for this time zone
2921        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
2922        { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Buenos_Aires" },
2923
2924        { "bg", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2925        { "bg", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-05:00", "-5:00" },
2926        { "bg", "America/Havana", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-5", "-5:00" },
2927        { "bg", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-5:00" },
2928        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2929        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-04:00", "-4:00" },
2930        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-4", "-4:00" },
2931        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-4:00" },
2932        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u041a\\u0443\\u0431\\u0430", "America/Havana" },
2933        { "bg", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043C\\u0435", "America/Havana" },
2934
2935        { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2936        { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
2937        { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
2938        { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u043B\\u044F\\u0442\\u043D\\u043E \\u0447\\u0430\\u0441\\u043E\\u0432\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+11:00" },
2939        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2940        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
2941        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
2942        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+10:00" },
2943        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
2944        { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "Australia/Sydney" },
2945
2946        { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2947        { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
2948        { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
2949        { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u043B\\u044F\\u0442\\u043D\\u043E \\u0447\\u0430\\u0441\\u043E\\u0432\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+11:00" },
2950        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2951        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
2952        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
2953        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+10:00" },
2954        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
2955        { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "Australia/Sydney" },
2956
2957        { "bg", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2958        { "bg", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
2959        { "bg", "Europe/London", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
2960        { "bg", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u0421\\u0440\\u0435\\u0434\\u043d\\u043e \\u0433\\u0440\\u0438\\u043d\\u0443\\u0438\\u0447\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+0:00" },
2961        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2962        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+01:00", "+1:00" },
2963        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+1", "+1:00" },
2964        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u0411\\u0440\\u0438\\u0442\\u0430\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+1:00" },
2965        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u0412\\u0435\\u043b\\u0438\\u043a\\u043e\\u0431\\u0440\\u0438\\u0442\\u0430\\u043d\\u0438\\u044f", "Europe/London" },
2966        { "bg", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u0412\\u0435\\u043b\\u0438\\u043a\\u043e\\u0431\\u0440\\u0438\\u0442\\u0430\\u043d\\u0438\\u044f", "Europe/London" },
2967
2968        { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2969        { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
2970        { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
2971        { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
2972        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2973        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
2974        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
2975        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
2976        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
2977        { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
2978
2979        // JB#5150
2980        { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2981        { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
2982        { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+5:30" },
2983        { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u043d\\u0434\\u0438\\u0439\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
2984        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2985        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
2986        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+05:30" },
2987        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u043d\\u0434\\u0438\\u0439\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
2988        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u0418\\u043D\\u0434\\u0438\\u044F", "Asia/Calcutta" },
2989        { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u043d\\u0434\\u0438\\u0439\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "Asia/Calcutta" },
2990    // ==========
2991
2992        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2993        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2994        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2995        { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u6a19\\u6e96\\u6642", "America/Los_Angeles" },
2996        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-700" },
2997        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2998        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
2999        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u590f\\u6642\\u9593", "America/Los_Angeles" },
3000    // icu ja.txt has exemplar city for this time zone
3001        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3002        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30E1\\u30EA\\u30AB\\u592A\\u5e73\\u6D0B\\u6642\\u9593", "America/Los_Angeles" },
3003        { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3004
3005        { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3006        { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3007        { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3008        { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3009        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3010        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3011        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3012        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3013    // icu ja.txt does not have info for this time zone
3014        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3015        { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3016
3017        { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3018        { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3019        { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3020        { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3021        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3022        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3023        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3024        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3025        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3026        { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3027
3028        { "ja", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3029        { "ja", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3030        { "ja", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3031        { "ja", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u6A19\\u6E96\\u6642", "-5:00" },
3032        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3033        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3034        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3035        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u590F\\u6642\\u9593", "-4:00" },
3036        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3037        { "ja", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3038
3039        { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3040        { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3041        { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3042        { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3043        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3044        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3045        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3046        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3047    // icu ja.txt does not have info for this time zone
3048        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3049        { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3050
3051        { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3052        { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3053        { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3054        { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3055        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3056        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3057        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3058        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3059        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3060        { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3061
3062        { "ja", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3063        { "ja", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3064        { "ja", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3065        { "ja", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u30B0\\u30EA\\u30CB\\u30C3\\u30B8\\u6A19\\u6E96\\u6642", "+0:00" },
3066        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3067        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3068        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3069        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u6642\\u9593", "+1:00" },
3070        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3071        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3072        { "ja", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3073
3074        { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3075        { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3076        { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3077        { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3078        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3079        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3080        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3081        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3082        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3083        { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3084
3085        // JB#5150
3086        { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3087        { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3088        { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3089        { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6642\\u9593", "+5:30" },
3090        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3091        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3092        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3093        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6642\\u9593", "+5:30" },
3094        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u30A4\\u30F3\\u30C9\\u6642\\u9593", "Asia/Calcutta" },
3095        { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u30A4\\u30F3\\u30C9\\u6642\\u9593", "Asia/Calcutta" },
3096
3097    // ==========
3098
3099        { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3100        { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3101        { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
3102        { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "GMT-08:00", "-8:00" },
3103        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3104        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3105        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
3106        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "GMT-07:00", "-7:00" },
3107        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles", "America/Los_Angeles" },
3108        { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Los Angeles", "America/Los_Angeles" },
3109
3110        { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3111        { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3112        { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3113        { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3114        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3115        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3116        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3117        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3118        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3119        { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3120
3121        { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3122        { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3123        { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3124        { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3125        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3126        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3127        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3128        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3129        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3130        { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3131
3132        { "ti", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3133        { "ti", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3134        { "ti", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3135        { "ti", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "GMT-05:00", "-5:00" },
3136        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3137        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3138        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3139        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "GMT-04:00", "-4:00" },
3140        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "v", "CU", "America/Havana" },
3141        { "ti", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "CU", "America/Havana" },
3142
3143        { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3144        { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3145        { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3146        { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3147        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3148        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3149        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3150        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3151        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3152        { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3153
3154        { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3155        { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3156        { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3157        { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3158        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3159        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3160        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3161        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3162        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3163        { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3164
3165        { "ti", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3166        { "ti", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3167        { "ti", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3168        { "ti", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "GMT", "+0:00" },
3169        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3170        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3171        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3172        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "GMT+01:00", "+1:00" },
3173        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "v", "GB", "Europe/London" },
3174        { "ti", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "GB", "Europe/London" },
3175
3176        { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3177        { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3178        { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3179        { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3180        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3181        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3182        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3183        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3184        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3185        { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3186
3187        // JB#5150
3188        { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3189        { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3190        { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3191        { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3192        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3193        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3194        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3195        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3196        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IN", "Alna/Calcutta" },
3197        { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "IN", "Asia/Calcutta" },
3198
3199        // Ticket#8589 Partial location name to use country name if the zone is the golden
3200        // zone for the time zone's country.
3201        { "en_MX", "America/Chicago", "1995-07-15T00:00:00Z", "vvvv", "Central Time (United States)", "America/Chicago"},
3202
3203        // Tests proper handling of time zones that should have empty sets when inherited from the parent.
3204        // For example, en_GB understands CET as Central European Time, but en_HK, which inherits from en_GB
3205        // does not
3206        { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3207        { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3208        { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "CET", "+1:00"},
3209        { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "CEST", "+2:00"},
3210        { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3211        { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3212        { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "GMT+1", "+1:00"},
3213        { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "GMT+2", "+2:00"},
3214
3215        { NULL, NULL, NULL, NULL, NULL, NULL },
3216    };
3217
3218    UErrorCode status = U_ZERO_ERROR;
3219    Calendar *cal = GregorianCalendar::createInstance(status);
3220    if (failure(status, "GregorianCalendar::createInstance", TRUE)) return;
3221    SimpleDateFormat testfmt(UnicodeString("yyyy-MM-dd'T'HH:mm:ss'Z'"), status);
3222    if (failure(status, "SimpleDateFormat constructor", TRUE)) return;
3223    testfmt.setTimeZone(*TimeZone::getGMT());
3224
3225    for (int i = 0; fallbackTests[i][0]; i++) {
3226        const char **testLine = fallbackTests[i];
3227        UnicodeString info[5];
3228        for ( int j = 0 ; j < 5 ; j++ ) {
3229            info[j] = UnicodeString(testLine[j], -1, US_INV);
3230        }
3231        info[4] = info[4].unescape();
3232        logln("%s;%s;%s;%s", testLine[0], testLine[1], testLine[2], testLine[3]);
3233
3234        TimeZone *tz = TimeZone::createTimeZone(info[1]);
3235
3236        UDate d = testfmt.parse(testLine[2], status);
3237        cal->setTime(d, status);
3238        if (U_FAILURE(status)) {
3239            errln(UnicodeString("Failed to set date: ") + testLine[2]);
3240        }
3241
3242        SimpleDateFormat fmt(info[3], Locale(testLine[0]),status);
3243        ASSERT_OK(status);
3244        cal->adoptTimeZone(tz);
3245        UnicodeString result;
3246        FieldPosition pos(0);
3247        fmt.format(*cal,result,pos);
3248        if (result != info[4]) {
3249            errln(info[0] + ";" + info[1] + ";" + info[2] + ";" + info[3] + " expected: '" +
3250                  info[4] + "' but got: '" + result + "'");
3251        }
3252    }
3253    delete cal;
3254}
3255
3256void DateFormatTest::TestRoundtripWithCalendar(void) {
3257    UErrorCode status = U_ZERO_ERROR;
3258
3259    TimeZone *tz = TimeZone::createTimeZone("Europe/Paris");
3260    TimeZone *gmt = TimeZone::createTimeZone("Etc/GMT");
3261
3262    Calendar *calendars[] = {
3263        Calendar::createInstance(*tz, Locale("und@calendar=gregorian"), status),
3264        Calendar::createInstance(*tz, Locale("und@calendar=buddhist"), status),
3265//        Calendar::createInstance(*tz, Locale("und@calendar=hebrew"), status),
3266        Calendar::createInstance(*tz, Locale("und@calendar=islamic"), status),
3267        Calendar::createInstance(*tz, Locale("und@calendar=japanese"), status),
3268        NULL
3269    };
3270    if (U_FAILURE(status)) {
3271        dataerrln("Failed to initialize calendars: %s", u_errorName(status));
3272        for (int i = 0; calendars[i] != NULL; i++) {
3273            delete calendars[i];
3274        }
3275        return;
3276    }
3277
3278    //FIXME The formatters commented out below are currently failing because of
3279    // the calendar calculation problem reported by #6691
3280
3281    // The order of test formatters must match the order of calendars above.
3282    DateFormat *formatters[] = {
3283        DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("en_US")), //calendar=gregorian
3284        DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("th_TH")), //calendar=buddhist
3285//        DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("he_IL@calendar=hebrew")),
3286        DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ar_EG@calendar=islamic")),
3287//        DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ja_JP@calendar=japanese")),
3288        NULL
3289    };
3290
3291    UDate d = Calendar::getNow();
3292    UnicodeString buf;
3293    FieldPosition fpos;
3294    ParsePosition ppos;
3295
3296    for (int i = 0; formatters[i] != NULL; i++) {
3297        buf.remove();
3298        fpos.setBeginIndex(0);
3299        fpos.setEndIndex(0);
3300        calendars[i]->setTime(d, status);
3301
3302        // Normal case output - the given calendar matches the calendar
3303        // used by the formatter
3304        formatters[i]->format(*calendars[i], buf, fpos);
3305        UnicodeString refStr(buf);
3306
3307        for (int j = 0; calendars[j] != NULL; j++) {
3308            if (j == i) {
3309                continue;
3310            }
3311            buf.remove();
3312            fpos.setBeginIndex(0);
3313            fpos.setEndIndex(0);
3314            calendars[j]->setTime(d, status);
3315
3316            // Even the different calendar type is specified,
3317            // we should get the same result.
3318            formatters[i]->format(*calendars[j], buf, fpos);
3319            if (refStr != buf) {
3320                errln((UnicodeString)"FAIL: Different format result with a different calendar for the same time -"
3321                        + "\n Reference calendar type=" + calendars[i]->getType()
3322                        + "\n Another calendar type=" + calendars[j]->getType()
3323                        + "\n Expected result=" + refStr
3324                        + "\n Actual result=" + buf);
3325            }
3326        }
3327
3328        calendars[i]->setTimeZone(*gmt);
3329        calendars[i]->clear();
3330        ppos.setErrorIndex(-1);
3331        ppos.setIndex(0);
3332
3333        // Normal case parse result - the given calendar matches the calendar
3334        // used by the formatter
3335        formatters[i]->parse(refStr, *calendars[i], ppos);
3336
3337        for (int j = 0; calendars[j] != NULL; j++) {
3338            if (j == i) {
3339                continue;
3340            }
3341            calendars[j]->setTimeZone(*gmt);
3342            calendars[j]->clear();
3343            ppos.setErrorIndex(-1);
3344            ppos.setIndex(0);
3345
3346            // Even the different calendar type is specified,
3347            // we should get the same time and time zone.
3348            formatters[i]->parse(refStr, *calendars[j], ppos);
3349            if (calendars[i]->getTime(status) != calendars[j]->getTime(status)
3350                || calendars[i]->getTimeZone() != calendars[j]->getTimeZone()) {
3351                UnicodeString tzid;
3352                errln((UnicodeString)"FAIL: Different parse result with a different calendar for the same string -"
3353                        + "\n Reference calendar type=" + calendars[i]->getType()
3354                        + "\n Another calendar type=" + calendars[j]->getType()
3355                        + "\n Date string=" + refStr
3356                        + "\n Expected time=" + calendars[i]->getTime(status)
3357                        + "\n Expected time zone=" + calendars[i]->getTimeZone().getID(tzid)
3358                        + "\n Actual time=" + calendars[j]->getTime(status)
3359                        + "\n Actual time zone=" + calendars[j]->getTimeZone().getID(tzid));
3360            }
3361        }
3362        if (U_FAILURE(status)) {
3363            errln((UnicodeString)"FAIL: " + u_errorName(status));
3364            break;
3365        }
3366    }
3367
3368    delete tz;
3369    delete gmt;
3370    for (int i = 0; calendars[i] != NULL; i++) {
3371        delete calendars[i];
3372    }
3373    for (int i = 0; formatters[i] != NULL; i++) {
3374        delete formatters[i];
3375    }
3376}
3377
3378/*
3379void DateFormatTest::TestRelativeError(void)
3380{
3381    UErrorCode status;
3382    Locale en("en");
3383
3384    DateFormat *en_reltime_reldate =         DateFormat::createDateTimeInstance(DateFormat::kFullRelative,DateFormat::kFullRelative,en);
3385    if(en_reltime_reldate == NULL) {
3386        logln("PASS: rel date/rel time failed");
3387    } else {
3388        errln("FAIL: rel date/rel time created, should have failed.");
3389        delete en_reltime_reldate;
3390    }
3391}
3392
3393void DateFormatTest::TestRelativeOther(void)
3394{
3395    logln("Nothing in this test. When we get more data from CLDR, put in some tests of -2, +2, etc. ");
3396}
3397*/
3398
3399void DateFormatTest::Test6338(void)
3400{
3401    UErrorCode status = U_ZERO_ERROR;
3402
3403    SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("ar"), status);
3404    if (failure(status, "new SimpleDateFormat", TRUE)) return;
3405
3406    UDate dt1 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3407    UnicodeString str1;
3408    str1 = fmt1->format(dt1, str1);
3409    logln(str1);
3410
3411    UDate dt11 = fmt1->parse(str1, status);
3412    failure(status, "fmt->parse");
3413
3414    UnicodeString str11;
3415    str11 = fmt1->format(dt11, str11);
3416    logln(str11);
3417
3418    if (str1 != str11) {
3419        errln((UnicodeString)"FAIL: Different dates str1:" + str1
3420            + " str2:" + str11);
3421    }
3422    delete fmt1;
3423
3424    /////////////////
3425
3426    status = U_ZERO_ERROR;
3427    SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("y M d"), Locale("ar"), status);
3428    failure(status, "new SimpleDateFormat");
3429
3430    UDate dt2 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3431    UnicodeString str2;
3432    str2 = fmt2->format(dt2, str2);
3433    logln(str2);
3434
3435    UDate dt22 = fmt2->parse(str2, status);
3436    failure(status, "fmt->parse");
3437
3438    UnicodeString str22;
3439    str22 = fmt2->format(dt22, str22);
3440    logln(str22);
3441
3442    if (str2 != str22) {
3443        errln((UnicodeString)"FAIL: Different dates str1:" + str2
3444            + " str2:" + str22);
3445    }
3446    delete fmt2;
3447
3448    /////////////////
3449
3450    status = U_ZERO_ERROR;
3451    SimpleDateFormat *fmt3 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("en-us"), status);
3452    failure(status, "new SimpleDateFormat");
3453
3454    UDate dt3 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3455    UnicodeString str3;
3456    str3 = fmt3->format(dt3, str3);
3457    logln(str3);
3458
3459    UDate dt33 = fmt3->parse(str3, status);
3460    failure(status, "fmt->parse");
3461
3462    UnicodeString str33;
3463    str33 = fmt3->format(dt33, str33);
3464    logln(str33);
3465
3466    if (str3 != str33) {
3467        errln((UnicodeString)"FAIL: Different dates str1:" + str3
3468            + " str2:" + str33);
3469    }
3470    delete fmt3;
3471
3472    /////////////////
3473
3474    status = U_ZERO_ERROR;
3475    SimpleDateFormat *fmt4 = new SimpleDateFormat(UnicodeString("y M  d"), Locale("en-us"), status);
3476    failure(status, "new SimpleDateFormat");
3477
3478    UDate dt4 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3479    UnicodeString str4;
3480    str4 = fmt4->format(dt4, str4);
3481    logln(str4);
3482
3483    UDate dt44 = fmt4->parse(str4, status);
3484    failure(status, "fmt->parse");
3485
3486    UnicodeString str44;
3487    str44 = fmt4->format(dt44, str44);
3488    logln(str44);
3489
3490    if (str4 != str44) {
3491        errln((UnicodeString)"FAIL: Different dates str1:" + str4
3492            + " str2:" + str44);
3493    }
3494    delete fmt4;
3495
3496}
3497
3498void DateFormatTest::Test6726(void)
3499{
3500    // status
3501//    UErrorCode status = U_ZERO_ERROR;
3502
3503    // fmtf, fmtl, fmtm, fmts;
3504    UnicodeString strf, strl, strm, strs;
3505    UDate dt = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3506
3507    Locale loc("ja");
3508    DateFormat* fmtf = DateFormat::createDateTimeInstance(DateFormat::FULL, DateFormat::FULL, loc);
3509    DateFormat* fmtl = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::FULL, loc);
3510    DateFormat* fmtm = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, loc);
3511    DateFormat* fmts = DateFormat::createDateTimeInstance(DateFormat::SHORT, DateFormat::FULL, loc);
3512    if (fmtf == NULL || fmtl == NULL || fmtm == NULL || fmts == NULL) {
3513        dataerrln("Unable to create DateFormat. got NULL.");
3514        /* It may not be true that if one is NULL all is NULL.  Just to be safe. */
3515        delete fmtf;
3516        delete fmtl;
3517        delete fmtm;
3518        delete fmts;
3519
3520        return;
3521    }
3522    strf = fmtf->format(dt, strf);
3523    strl = fmtl->format(dt, strl);
3524    strm = fmtm->format(dt, strm);
3525    strs = fmts->format(dt, strs);
3526
3527
3528    logln("strm.charAt(10)=%04X wanted 0x20\n", strm.charAt(10));
3529    if (strm.charAt(10) != UChar(0x0020)) {
3530      errln((UnicodeString)"FAIL: Improper formatted date: " + strm );
3531    }
3532    logln("strs.charAt(10)=%04X wanted 0x20\n", strs.charAt(8));
3533    if (strs.charAt(10)  != UChar(0x0020)) {
3534        errln((UnicodeString)"FAIL: Improper formatted date: " + strs);
3535    }
3536
3537    delete fmtf;
3538    delete fmtl;
3539    delete fmtm;
3540    delete fmts;
3541
3542    return;
3543}
3544
3545/**
3546 * Test DateFormat's parsing of default GMT variants.  See ticket#6135
3547 */
3548void DateFormatTest::TestGMTParsing() {
3549    const char* DATA[] = {
3550        "HH:mm:ss Z",
3551
3552        // pattern, input, expected output (in quotes)
3553        "HH:mm:ss Z",       "10:20:30 GMT+03:00",   "10:20:30 +0300",
3554        "HH:mm:ss Z",       "10:20:30 UT-02:00",    "10:20:30 -0200",
3555        "HH:mm:ss Z",       "10:20:30 GMT",         "10:20:30 +0000",
3556        "HH:mm:ss vvvv",    "10:20:30 UT+10:00",    "10:20:30 +1000",
3557        "HH:mm:ss zzzz",    "10:20:30 UTC",         "10:20:30 +0000",   // standalone "UTC"
3558        "ZZZZ HH:mm:ss",    "UT 10:20:30",          "10:20:30 +0000",
3559        "z HH:mm:ss",       "UT+0130 10:20:30",     "10:20:30 +0130",
3560        "z HH:mm:ss",       "UTC+0130 10:20:30",    "10:20:30 +0130",
3561        // Note: GMT-1100 no longer works because of the introduction of the short
3562        // localized GMT support. Previous implementation support this level of
3563        // leniency (no separator char in localized GMT format), but the new
3564        // implementation handles GMT-11 as the legitimate short localized GMT format
3565        // and stop at there. Otherwise, roundtrip would be broken.
3566        //"HH mm Z ss",       "10 20 GMT-1100 30",    "10:20:30 -1100",
3567        "HH mm Z ss",       "10 20 GMT-11 30",    "10:20:30 -1100",
3568        "HH:mm:ssZZZZZ",    "14:25:45Z",            "14:25:45 +0000",
3569        "HH:mm:ssZZZZZ",    "15:00:00-08:00",       "15:00:00 -0800",
3570    };
3571    const int32_t DATA_len = sizeof(DATA)/sizeof(DATA[0]);
3572    expectParse(DATA, DATA_len, Locale("en"));
3573}
3574
3575// Test case for localized GMT format parsing
3576// with no delimitters in offset format (Chinese locale)
3577void DateFormatTest::Test6880() {
3578    UErrorCode status = U_ZERO_ERROR;
3579    UDate d1, d2, dp1, dp2, dexp1, dexp2;
3580    UnicodeString s1, s2;
3581
3582    TimeZone *tz = TimeZone::createTimeZone("Asia/Shanghai");
3583    GregorianCalendar gcal(*tz, status);
3584    if (failure(status, "construct GregorianCalendar", TRUE)) return;
3585
3586    gcal.clear();
3587    gcal.set(1910, UCAL_JULY, 1, 12, 00);   // offset 8:05:57
3588    d1 = gcal.getTime(status);
3589
3590    gcal.clear();
3591    gcal.set(1950, UCAL_JULY, 1, 12, 00);   // offset 8:00
3592    d2 = gcal.getTime(status);
3593
3594    gcal.clear();
3595    gcal.set(1970, UCAL_JANUARY, 1, 12, 00);
3596    dexp2 = gcal.getTime(status);
3597    dexp1 = dexp2 - (5*60 + 57)*1000;   // subtract 5m57s
3598
3599    if (U_FAILURE(status)) {
3600        errln("FAIL: Gregorian calendar error");
3601    }
3602
3603    DateFormat *fmt = DateFormat::createTimeInstance(DateFormat::kFull, Locale("zh"));
3604    if (fmt == NULL) {
3605        dataerrln("Unable to create DateFormat. Got NULL.");
3606        return;
3607    }
3608    fmt->adoptTimeZone(tz);
3609
3610    fmt->format(d1, s1);
3611    fmt->format(d2, s2);
3612
3613    dp1 = fmt->parse(s1, status);
3614    dp2 = fmt->parse(s2, status);
3615
3616    if (U_FAILURE(status)) {
3617        errln("FAIL: Parse failure");
3618    }
3619
3620    if (dp1 != dexp1) {
3621        errln("FAIL: Failed to parse " + s1 + " parsed: " + dp1 + " expected: " + dexp1);
3622    }
3623    if (dp2 != dexp2) {
3624        errln("FAIL: Failed to parse " + s2 + " parsed: " + dp2 + " expected: " + dexp2);
3625    }
3626
3627    delete fmt;
3628}
3629
3630typedef struct {
3631    const char * localeStr;
3632    UBool        lenient;
3633    UBool        expectFail;
3634    UnicodeString datePattern;
3635    UnicodeString dateString;
3636} NumAsStringItem;
3637
3638void DateFormatTest::TestNumberAsStringParsing()
3639{
3640    const NumAsStringItem items[] = {
3641        // loc lenient fail?  datePattern                                         dateString
3642        { "",   FALSE, TRUE,  UnicodeString("y MMMM d HH:mm:ss"),                 UnicodeString("2009 7 14 08:43:57") },
3643        { "",   TRUE,  FALSE, UnicodeString("y MMMM d HH:mm:ss"),                 UnicodeString("2009 7 14 08:43:57") },
3644        { "en", FALSE, FALSE, UnicodeString("MMM d, y"),                          UnicodeString("Jul 14, 2009") },
3645        { "en", TRUE,  FALSE, UnicodeString("MMM d, y"),                          UnicodeString("Jul 14, 2009") },
3646        { "en", FALSE, TRUE,  UnicodeString("MMM d, y"),                          UnicodeString("7 14, 2009") },
3647        { "en", TRUE,  FALSE, UnicodeString("MMM d, y"),                          UnicodeString("7 14, 2009") },
3648        { "ja", FALSE, FALSE, UnicodeString("yyyy/MM/dd"),                        UnicodeString("2009/07/14")         },
3649        { "ja", TRUE,  FALSE, UnicodeString("yyyy/MM/dd"),                        UnicodeString("2009/07/14")         },
3650      //{ "ja", FALSE, FALSE, UnicodeString("yyyy/MMMMM/d"),                      UnicodeString("2009/7/14")          }, // #8860 covers test failure
3651        { "ja", TRUE,  FALSE, UnicodeString("yyyy/MMMMM/d"),                      UnicodeString("2009/7/14")          },
3652        { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"),   CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   },
3653        { "ja", TRUE,  FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"),   CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   },
3654        { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"),        CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   },
3655        { "ja", TRUE,  FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"),        CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   }, // #8820 fixes test failure
3656        { "ko", FALSE, FALSE, UnicodeString("yyyy. M. d."),                       UnicodeString("2009. 7. 14.")       },
3657        { "ko", TRUE,  FALSE, UnicodeString("yyyy. M. d."),                       UnicodeString("2009. 7. 14.")       },
3658        { "ko", FALSE, FALSE, UnicodeString("yyyy. MMMMM d."),                    CharsToUnicodeString("2009. 7\\uC6D4 14.")             },
3659        { "ko", TRUE,  FALSE, UnicodeString("yyyy. MMMMM d."),                    CharsToUnicodeString("2009. 7\\uC6D4 14.")             }, // #8820 fixes test failure
3660        { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3661        { "ko", TRUE,  FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3662        { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"),      CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3663        { "ko", TRUE,  FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"),      CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") }, // #8820 fixes test failure
3664        { NULL, FALSE, FALSE, UnicodeString(""),                                  UnicodeString("")                   }
3665    };
3666    const NumAsStringItem * itemPtr;
3667    for (itemPtr = items; itemPtr->localeStr != NULL; itemPtr++ ) {
3668        Locale locale = Locale::createFromName(itemPtr->localeStr);
3669        UErrorCode status = U_ZERO_ERROR;
3670        SimpleDateFormat *formatter = new SimpleDateFormat(itemPtr->datePattern, locale, status);
3671        if (formatter == NULL || U_FAILURE(status)) {
3672            dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3673            return;
3674        }
3675
3676        formatter->setLenient(itemPtr->lenient);
3677        formatter->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->lenient, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->lenient, status);
3678        UDate date1 = formatter->parse(itemPtr->dateString, status);
3679        if (U_FAILURE(status)) {
3680            if (!itemPtr->expectFail) {
3681                errln("FAIL, err when expected success: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3682                        ": using pattern \"" + itemPtr->datePattern + "\", could not parse \"" + itemPtr->dateString + "\"; err: " + u_errorName(status) );
3683            }
3684        } else if (itemPtr->expectFail) {
3685                errln("FAIL, expected err but got none: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3686                        ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\"." );
3687        } else if (!itemPtr->lenient) {
3688            UnicodeString formatted;
3689            formatter->format(date1, formatted);
3690            if (formatted != itemPtr->dateString) {
3691                errln("FAIL, mismatch formatting parsed date: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3692                        ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\", formatted result \"" + formatted + "\".");
3693            }
3694        }
3695
3696        delete formatter;
3697    }
3698}
3699
3700void DateFormatTest::TestISOEra() {
3701
3702    const char* data[] = {
3703    // input, output
3704    "BC 4004-10-23T07:00:00Z", "BC 4004-10-23T07:00:00Z",
3705    "AD 4004-10-23T07:00:00Z", "AD 4004-10-23T07:00:00Z",
3706    "-4004-10-23T07:00:00Z"  , "BC 4005-10-23T07:00:00Z",
3707    "4004-10-23T07:00:00Z"   , "AD 4004-10-23T07:00:00Z",
3708    };
3709
3710    int32_t numData = 8;
3711
3712    UErrorCode status = U_ZERO_ERROR;
3713
3714    // create formatter
3715    SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("GGG yyyy-MM-dd'T'HH:mm:ss'Z"), status);
3716    failure(status, "new SimpleDateFormat", TRUE);
3717    if (status == U_MISSING_RESOURCE_ERROR) {
3718        if (fmt1 != NULL) {
3719            delete fmt1;
3720        }
3721        return;
3722    }
3723    for(int i=0; i < numData; i+=2) {
3724        // create input string
3725        UnicodeString in = data[i];
3726
3727        // parse string to date
3728        UDate dt1 = fmt1->parse(in, status);
3729        failure(status, "fmt->parse", TRUE);
3730
3731        // format date back to string
3732        UnicodeString out;
3733        out = fmt1->format(dt1, out);
3734        logln(out);
3735
3736        // check that roundtrip worked as expected
3737        UnicodeString expected = data[i+1];
3738        if (out != expected) {
3739            dataerrln((UnicodeString)"FAIL: " + in + " -> " + out + " expected -> " + expected);
3740        }
3741    }
3742
3743    delete fmt1;
3744}
3745void DateFormatTest::TestFormalChineseDate() {
3746
3747    UErrorCode status = U_ZERO_ERROR;
3748    UnicodeString pattern ("y\\u5e74M\\u6708d\\u65e5", -1, US_INV );
3749    pattern = pattern.unescape();
3750    UnicodeString override ("y=hanidec;M=hans;d=hans", -1, US_INV );
3751
3752    // create formatter
3753    SimpleDateFormat *sdf = new SimpleDateFormat(pattern,override,Locale::getChina(),status);
3754    failure(status, "new SimpleDateFormat with override", TRUE);
3755
3756    UDate thedate = date(2009-1900, UCAL_JULY, 28);
3757    FieldPosition pos(0);
3758    UnicodeString result;
3759    sdf->format(thedate,result,pos);
3760
3761    UnicodeString expected = "\\u4e8c\\u3007\\u3007\\u4e5d\\u5e74\\u4e03\\u6708\\u4e8c\\u5341\\u516b\\u65e5";
3762    expected = expected.unescape();
3763    if (result != expected) {
3764        dataerrln((UnicodeString)"FAIL: -> " + result + " expected -> " + expected);
3765    }
3766
3767    UDate parsedate = sdf->parse(expected,status);
3768    if ( parsedate != thedate ) {
3769        UnicodeString pat1 ("yyyy-MM-dd'T'HH:mm:ss'Z'", -1, US_INV );
3770        SimpleDateFormat *usf = new SimpleDateFormat(pat1,Locale::getEnglish(),status);
3771        UnicodeString parsedres,expres;
3772        usf->format(parsedate,parsedres,pos);
3773        usf->format(thedate,expres,pos);
3774        dataerrln((UnicodeString)"FAIL: parsed -> " + parsedres + " expected -> " + expres);
3775        delete usf;
3776    }
3777    delete sdf;
3778}
3779
3780// Test case for #8675
3781// Incorrect parse offset with stand alone GMT string on 2nd or later iteration.
3782void DateFormatTest::TestStandAloneGMTParse() {
3783    UErrorCode status = U_ZERO_ERROR;
3784    SimpleDateFormat *sdf = new SimpleDateFormat("ZZZZ", Locale(""), status);
3785
3786    if (U_SUCCESS(status)) {
3787
3788        UnicodeString inText("GMT$$$");
3789        for (int32_t i = 0; i < 10; i++) {
3790            ParsePosition pos(0);
3791            sdf->parse(inText, pos);
3792            if (pos.getIndex() != 3) {
3793                errln((UnicodeString)"FAIL: Incorrect output parse position: actual=" + pos.getIndex() + " expected=3");
3794            }
3795        }
3796
3797        delete sdf;
3798    } else {
3799        dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3800    }
3801}
3802
3803void DateFormatTest::TestParsePosition() {
3804    const char* TestData[][4] = {
3805        // {<pattern>, <lead>, <date string>, <trail>}
3806        {"yyyy-MM-dd HH:mm:ssZ", "", "2010-01-10 12:30:00+0500", ""},
3807        {"yyyy-MM-dd HH:mm:ss ZZZZ", "", "2010-01-10 12:30:00 GMT+05:00", ""},
3808        {"Z HH:mm:ss", "", "-0100 13:20:30", ""},
3809        {"y-M-d Z", "", "2011-8-25 -0400", " Foo"},
3810        {"y/M/d H:mm:ss z", "", "2011/7/1 12:34:00 PDT", ""},
3811        {"y/M/d H:mm:ss z", "+123", "2011/7/1 12:34:00 PDT", " PST"},
3812        {"vvvv a h:mm:ss", "", "Pacific Time AM 10:21:45", ""},
3813        {"HH:mm v M/d", "111", "14:15 PT 8/10", " 12345"},
3814        {"'time zone:' VVVV 'date:' yyyy-MM-dd", "xxxx", "time zone: Los Angeles Time date: 2010-02-25", "xxxx"},
3815        {"yG", "", "2012AD", ""},
3816        {"yG", "", "2012", "x"},
3817        {0, 0, 0, 0},
3818    };
3819
3820    for (int32_t i = 0; TestData[i][0]; i++) {
3821        UErrorCode status = U_ZERO_ERROR;
3822        SimpleDateFormat *sdf = new SimpleDateFormat(UnicodeString(TestData[i][0]), status);
3823        if (failure(status, "new SimpleDateFormat", TRUE)) return;
3824
3825        int32_t startPos, resPos;
3826
3827        // lead text
3828        UnicodeString input(TestData[i][1]);
3829        startPos = input.length();
3830
3831        // date string
3832        input += TestData[i][2];
3833        resPos = input.length();
3834
3835        // trail text
3836        input += TestData[i][3];
3837
3838        ParsePosition pos(startPos);
3839        //UDate d = sdf->parse(input, pos);
3840        (void)sdf->parse(input, pos);
3841
3842        if (pos.getIndex() != resPos) {
3843            errln(UnicodeString("FAIL: Parsing [") + input + "] with pattern [" + TestData[i][0] + "] returns position - "
3844                + pos.getIndex() + ", expected - " + resPos);
3845        }
3846
3847        delete sdf;
3848    }
3849}
3850
3851
3852typedef struct {
3853    int32_t era;
3854    int32_t year;
3855    int32_t month; // 1-based
3856    int32_t isLeapMonth;
3857    int32_t day;
3858} ChineseCalTestDate;
3859
3860#define NUM_TEST_DATES 3
3861
3862typedef struct {
3863    const char *   locale;
3864    int32_t        style; // <0 => custom
3865    UnicodeString  dateString[NUM_TEST_DATES];
3866} MonthPatternItem;
3867
3868void DateFormatTest::TestMonthPatterns()
3869{
3870    const ChineseCalTestDate dates[NUM_TEST_DATES] = {
3871        // era yr mo lp da
3872        {  78, 29, 4, 0, 2 }, // (in chinese era 78) gregorian 2012-4-22
3873        {  78, 29, 4, 1, 2 }, // (in chinese era 78) gregorian 2012-5-22
3874        {  78, 29, 5, 0, 2 }, // (in chinese era 78) gregorian 2012-6-20
3875    };
3876
3877    const MonthPatternItem items[] = {
3878        // locale                     date style;           expected formats for the 3 dates above
3879        { "root@calendar=chinese",    DateFormat::kLong,  { UnicodeString("ren-chen M04 2"),  UnicodeString("ren-chen M04bis 2"),  UnicodeString("ren-chen M05 2") } },
3880        { "root@calendar=chinese",    DateFormat::kShort, { UnicodeString("29-04-02"),      UnicodeString("29-04bis-02"),           UnicodeString("29-05-02") } },
3881        { "root@calendar=chinese",    -1,                 { UnicodeString("29-4-2"),        UnicodeString("29-4bis-2"),             UnicodeString("29-5-2") } },
3882        { "root@calendar=chinese",    -2,                 { UnicodeString("78x29-4-2"),     UnicodeString("78x29-4bis-2"),          UnicodeString("78x29-5-2") } },
3883        { "root@calendar=chinese",    -3,                 { UnicodeString("ren-chen-4-2"),  UnicodeString("ren-chen-4bis-2"),       UnicodeString("ren-chen-5-2") } },
3884        { "root@calendar=chinese",    -4,                 { UnicodeString("ren-chen M04 2"),  UnicodeString("ren-chen M04bis 2"),   UnicodeString("ren-chen M05 2") } },
3885        { "en@calendar=gregorian",    -3,                 { UnicodeString("2012-4-22"),     UnicodeString("2012-5-22"),             UnicodeString("2012-6-20") } },
3886        { "en@calendar=chinese",      DateFormat::kLong,  { UnicodeString("Month4 2, ren-chen"), UnicodeString("Month4bis 2, ren-chen"), UnicodeString("Month5 2, ren-chen") } },
3887        { "en@calendar=chinese",      DateFormat::kShort, { UnicodeString("4/2/29"),        UnicodeString("4bis/2/29"),             UnicodeString("5/2/29") } },
3888        { "zh@calendar=chinese",      DateFormat::kLong,  { CharsToUnicodeString("\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u4E8C\\u65E5"),
3889                                                            CharsToUnicodeString("\\u58EC\\u8FB0\\u5E74\\u95F0\\u56DB\\u6708\\u4E8C\\u65E5"),
3890                                                            CharsToUnicodeString("\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u4E8C\\u65E5") } },
3891        { "zh@calendar=chinese",      DateFormat::kShort, { CharsToUnicodeString("\\u58EC\\u8FB0-4-2"),
3892                                                            CharsToUnicodeString("\\u58EC\\u8FB0-\\u95F04-2"),
3893                                                            CharsToUnicodeString("\\u58EC\\u8FB0-5-2") } },
3894        { "zh@calendar=chinese",      -3,                 { CharsToUnicodeString("\\u58EC\\u8FB0-4-2"),
3895                                                            CharsToUnicodeString("\\u58EC\\u8FB0-\\u95F04-2"),
3896                                                            CharsToUnicodeString("\\u58EC\\u8FB0-5-2") } },
3897        { "zh@calendar=chinese",      -4,                 { CharsToUnicodeString("\\u58EC\\u8FB0 \\u56DB\\u6708 2"),
3898                                                            CharsToUnicodeString("\\u58EC\\u8FB0 \\u95F0\\u56DB\\u6708 2"),
3899                                                            CharsToUnicodeString("\\u58EC\\u8FB0 \\u4E94\\u6708 2") } },
3900        { "zh_Hant@calendar=chinese", DateFormat::kLong,  { CharsToUnicodeString("\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u4E8C\\u65E5"),
3901                                                            CharsToUnicodeString("\\u58EC\\u8FB0\\u5E74\\u958F\\u56DB\\u6708\\u4E8C\\u65E5"),
3902                                                            CharsToUnicodeString("\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u4E8C\\u65E5") } },
3903        { "zh_Hant@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("\\u58EC\\u8FB0/4/2"),
3904                                                            CharsToUnicodeString("\\u58EC\\u8FB0/\\u958F4/2"),
3905                                                            CharsToUnicodeString("\\u58EC\\u8FB0/5/2") } },
3906        { "fr@calendar=chinese",      DateFormat::kLong,  { CharsToUnicodeString("2 s\\u00ECyu\\u00E8 ren-chen"),
3907                                                            CharsToUnicodeString("2 s\\u00ECyu\\u00E8bis ren-chen"),
3908                                                            CharsToUnicodeString("2 w\\u01D4yu\\u00E8 ren-chen") } },
3909        { "fr@calendar=chinese",      DateFormat::kShort, { UnicodeString("2/4/29"),        UnicodeString("2/4bis/29"),             UnicodeString("2/5/29") } },
3910        { "en@calendar=dangi",        DateFormat::kLong,  { UnicodeString("Month3bis 2, 29"),  UnicodeString("Month4 2, 29"),       UnicodeString("Month5 1, 29") } },
3911        { "en@calendar=dangi",        DateFormat::kShort, { UnicodeString("3bis/2/29"),     UnicodeString("4/2/29"),                UnicodeString("5/1/29") } },
3912        { "en@calendar=dangi",        -2,                 { UnicodeString("78x29-3bis-2"),  UnicodeString("78x29-4-2"),             UnicodeString("78x29-5-1") } },
3913        { "ko@calendar=dangi",        DateFormat::kLong,  { CharsToUnicodeString("\\uC784\\uC9C4\\uB144 3bis\\uC6D4 2\\uC77C"),
3914                                                            CharsToUnicodeString("\\uC784\\uC9C4\\uB144 4\\uC6D4 2\\uC77C"),
3915                                                            CharsToUnicodeString("\\uC784\\uC9C4\\uB144 5\\uC6D4 1\\uC77C") } },
3916        { "ko@calendar=dangi",        DateFormat::kShort, { CharsToUnicodeString("29. 3bis. 2."),
3917                                                            CharsToUnicodeString("29. 4. 2."),
3918                                                            CharsToUnicodeString("29. 5. 1.") } },
3919        // terminator
3920        { NULL,                       0,                  { UnicodeString(""), UnicodeString(""), UnicodeString("") } }
3921    };
3922
3923    //.                               style: -1        -2            -3       -4
3924    const UnicodeString customPatterns[] = { "y-Ml-d", "G'x'y-Ml-d", "U-M-d", "U MMM d" }; // like old root pattern, using 'l'
3925
3926    UErrorCode status = U_ZERO_ERROR;
3927    Locale rootChineseCalLocale = Locale::createFromName("root@calendar=chinese");
3928    Calendar * rootChineseCalendar = Calendar::createInstance(rootChineseCalLocale, status);
3929    if (U_SUCCESS(status)) {
3930        const MonthPatternItem * itemPtr;
3931        for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
3932            Locale locale = Locale::createFromName(itemPtr->locale);
3933            DateFormat * dmft = (itemPtr->style >= 0)?
3934                    DateFormat::createDateInstance((DateFormat::EStyle)itemPtr->style, locale):
3935                    new SimpleDateFormat(customPatterns[-itemPtr->style - 1], locale, status);
3936            if ( dmft != NULL ) {
3937                if (U_SUCCESS(status)) {
3938                    const ChineseCalTestDate * datePtr = dates;
3939                    int32_t idate;
3940                    for (idate = 0; idate < NUM_TEST_DATES; idate++, datePtr++) {
3941                        rootChineseCalendar->clear();
3942                        rootChineseCalendar->set(UCAL_ERA, datePtr->era);
3943                        rootChineseCalendar->set(datePtr->year, datePtr->month-1, datePtr->day);
3944                        rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, datePtr->isLeapMonth);
3945                        UnicodeString result;
3946                        FieldPosition fpos(0);
3947                        dmft->format(*rootChineseCalendar, result, fpos);
3948                        if ( result.compare(itemPtr->dateString[idate]) != 0 ) {
3949                            errln( UnicodeString("FAIL: Chinese calendar format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
3950                                    ", expected \"" + itemPtr->dateString[idate] + "\", got \"" + result + "\"");
3951                        } else {
3952                            // formatted OK, try parse
3953                            ParsePosition ppos(0);
3954                            // ensure we are really parsing the fields we should be
3955                            rootChineseCalendar->set(UCAL_YEAR, 1);
3956                            rootChineseCalendar->set(UCAL_MONTH, 0);
3957                            rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, 0);
3958                            rootChineseCalendar->set(UCAL_DATE, 1);
3959                            //
3960                            dmft->parse(result, *rootChineseCalendar, ppos);
3961                            int32_t year = rootChineseCalendar->get(UCAL_YEAR, status);
3962                            int32_t month = rootChineseCalendar->get(UCAL_MONTH, status) + 1;
3963                            int32_t isLeapMonth = rootChineseCalendar->get(UCAL_IS_LEAP_MONTH, status);
3964                            int32_t day = rootChineseCalendar->get(UCAL_DATE, status);
3965                            if ( ppos.getIndex() < result.length() || year != datePtr->year || month != datePtr->month || isLeapMonth != datePtr->isLeapMonth || day != datePtr->day ) {
3966                                errln( UnicodeString("FAIL: Chinese calendar parse for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
3967                                    ", string \"" + result + "\", expected " + datePtr->year +"-"+datePtr->month+"("+datePtr->isLeapMonth+")-"+datePtr->day + ", got pos " +
3968                                    ppos.getIndex() + " " + year +"-"+month+"("+isLeapMonth+")-"+day);
3969                            }
3970                        }
3971                    }
3972                } else {
3973                    dataerrln("Error creating SimpleDateFormat for Chinese calendar- %s", u_errorName(status));
3974                }
3975                delete dmft;
3976            } else {
3977                dataerrln("FAIL: Unable to create DateFormat for Chinese calendar- %s", u_errorName(status));
3978            }
3979        }
3980        delete rootChineseCalendar;
3981    } else {
3982        errln(UnicodeString("FAIL: Unable to create Calendar for root@calendar=chinese"));
3983    }
3984}
3985
3986typedef struct {
3987    const char * locale;
3988    UnicodeString pattern;
3989    UDisplayContext capitalizationContext;
3990    UnicodeString expectedFormat;
3991} TestContextItem;
3992
3993void DateFormatTest::TestContext()
3994{
3995    const UDate july022008 = 1215000001979.0;
3996    const TestContextItem items[] = {
3997        //locale              pattern    capitalizationContext                              expected formatted date
3998        { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_NONE,                      UnicodeString("juillet 2008") },
3999#if !UCONFIG_NO_BREAK_ITERATION
4000        { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    UnicodeString("juillet 2008") },
4001        { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, UnicodeString("Juillet 2008") },
4002        { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU,       UnicodeString("juillet 2008") },
4003        { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE,            UnicodeString("Juillet 2008") },
4004#endif
4005        { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_NONE,                      CharsToUnicodeString("\\u010Dervenec 2008") },
4006#if !UCONFIG_NO_BREAK_ITERATION
4007        { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    CharsToUnicodeString("\\u010Dervenec 2008") },
4008        { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, CharsToUnicodeString("\\u010Cervenec 2008") },
4009        { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU,       CharsToUnicodeString("\\u010Cervenec 2008") },
4010        { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE,            CharsToUnicodeString("\\u010Dervenec 2008") },
4011#endif
4012        // terminator
4013        { NULL, UnicodeString(""),       (UDisplayContext)0, UnicodeString("") }
4014    };
4015    UErrorCode status = U_ZERO_ERROR;
4016    Calendar* cal = Calendar::createInstance(status);
4017    if (U_FAILURE(status)) {
4018        dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4019    } else {
4020        cal->setTime(july022008, status);
4021        const TestContextItem * itemPtr;
4022        for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4023           Locale locale = Locale::createFromName(itemPtr->locale);
4024           status = U_ZERO_ERROR;
4025           SimpleDateFormat * sdmft = new SimpleDateFormat(itemPtr->pattern, locale, status);
4026           if (U_FAILURE(status)) {
4027                dataerrln(UnicodeString("FAIL: Unable to create SimpleDateFormat for specified pattern with locale ") + UnicodeString(itemPtr->locale));
4028           } else {
4029               sdmft->setContext(itemPtr->capitalizationContext, status);
4030               UnicodeString result;
4031               FieldPosition pos(0);
4032               sdmft->format(*cal, result, pos);
4033               if (result.compare(itemPtr->expectedFormat) != 0) {
4034                   errln(UnicodeString("FAIL: format for locale ") + UnicodeString(itemPtr->locale) +
4035                           ", status " + (int)status +
4036                           ", capitalizationContext " + (int)itemPtr->capitalizationContext +
4037                           ", expected " + itemPtr->expectedFormat + ", got " + result);
4038               }
4039           }
4040           if (sdmft) {
4041               delete sdmft;
4042           }
4043        }
4044    }
4045    if (cal) {
4046        delete cal;
4047    }
4048}
4049
4050// test item for a particular locale + calendar and date format
4051typedef struct {
4052    int32_t year;
4053    int32_t month;
4054    int32_t day;
4055    int32_t hour;
4056    int32_t minute;
4057    UnicodeString formattedDate;
4058} CalAndFmtTestItem;
4059
4060// test item giving locale + calendar, date format, and CalAndFmtTestItems
4061typedef struct {
4062    const char * locale; // with calendar
4063    DateFormat::EStyle style;
4064    const CalAndFmtTestItem *caftItems;
4065} TestNonGregoItem;
4066
4067void DateFormatTest::TestNonGregoFmtParse()
4068{
4069    // test items for he@calendar=hebrew, long date format
4070    const CalAndFmtTestItem cafti_he_hebrew_long[] = {
4071        { 4999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05D3\\u05F3\\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4072        { 5100,  0,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05E7\\u05F3") },
4073        { 5774,  5,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05D0\\u05D3\\u05E8 \\u05D0\\u05F3 \\u05EA\\u05E9\\u05E2\\u05F4\\u05D3") },
4074        { 5999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4075        { 6100,  0,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05D5\\u05F3\\u05E7\\u05F3") },
4076        {    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4077    };
4078    // overal test items
4079    const TestNonGregoItem items[] = {
4080        { "he@calendar=hebrew", DateFormat::kLong, cafti_he_hebrew_long },
4081        { NULL, DateFormat::kNone, NULL } // terminator
4082    };
4083    const TestNonGregoItem * itemPtr;
4084    for (itemPtr = items; itemPtr->locale != NULL; itemPtr++) {
4085        Locale locale = Locale::createFromName(itemPtr->locale);
4086        DateFormat * dfmt = DateFormat::createDateInstance(itemPtr->style, locale);
4087        if (dfmt == NULL) {
4088            dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->locale);
4089        } else {
4090            Calendar * cal = (dfmt->getCalendar())->clone();
4091            if (cal == NULL) {
4092                dataerrln("(DateFormat::getCalendar)->clone() fails for locale %s", itemPtr->locale);
4093            } else {
4094                const CalAndFmtTestItem * caftItemPtr;
4095                for (caftItemPtr = itemPtr->caftItems; caftItemPtr->year != 0; caftItemPtr++) {
4096                    cal->clear();
4097                    cal->set(UCAL_YEAR,   caftItemPtr->year);
4098                    cal->set(UCAL_MONTH,  caftItemPtr->month);
4099                    cal->set(UCAL_DATE,   caftItemPtr->day);
4100                    cal->set(UCAL_HOUR_OF_DAY, caftItemPtr->hour);
4101                    cal->set(UCAL_MINUTE, caftItemPtr->minute);
4102                    UnicodeString result;
4103                    FieldPosition fpos(0);
4104                    dfmt->format(*cal, result, fpos);
4105                    if ( result.compare(caftItemPtr->formattedDate) != 0 ) {
4106                        errln( UnicodeString("FAIL: date format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4107                                ", expected \"" + caftItemPtr->formattedDate + "\", got \"" + result + "\"");
4108                    } else {
4109                        // formatted OK, try parse
4110                        ParsePosition ppos(0);
4111                        dfmt->parse(result, *cal, ppos);
4112                        UErrorCode status = U_ZERO_ERROR;
4113                        int32_t year = cal->get(UCAL_YEAR, status);
4114                        int32_t month = cal->get(UCAL_MONTH, status);
4115                        int32_t day = cal->get(UCAL_DATE, status);
4116                        if ( U_FAILURE(status) || ppos.getIndex() < result.length() || year != caftItemPtr->year || month != caftItemPtr->month || day != caftItemPtr->day ) {
4117                            errln( UnicodeString("FAIL: date parse for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4118                                ", string \"" + result + "\", expected " + caftItemPtr->year +"-"+caftItemPtr->month+"-"+caftItemPtr->day + ", got pos " +
4119                                ppos.getIndex() + " " + year +"-"+month+"-"+day + " status " + UnicodeString(u_errorName(status)) );
4120                        }
4121                    }
4122                }
4123                delete cal;
4124            }
4125            delete dfmt;
4126        }
4127    }
4128}
4129
4130static const UDate TEST_DATE = 1326585600000.;  // 2012-jan-15
4131
4132void DateFormatTest::TestDotAndAtLeniency() {
4133    // Test for date/time parsing regression with CLDR 22.1/ICU 50 pattern strings.
4134    // For details see http://bugs.icu-project.org/trac/ticket/9789
4135    static const char *locales[] = { "en", "fr" };
4136    for (int32_t i = 0; i < LENGTHOF(locales); ++i) {
4137        Locale locale(locales[i]);
4138
4139        for (DateFormat::EStyle dateStyle = DateFormat::FULL; dateStyle <= DateFormat::SHORT;
4140                  dateStyle = static_cast<DateFormat::EStyle>(dateStyle + 1)) {
4141            LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance(dateStyle, locale));
4142
4143            for (DateFormat::EStyle timeStyle = DateFormat::FULL; timeStyle <= DateFormat::SHORT;
4144                      timeStyle = static_cast<DateFormat::EStyle>(timeStyle + 1)) {
4145                LocalPointer<DateFormat> format(DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale));
4146                LocalPointer<DateFormat> timeFormat(DateFormat::createTimeInstance(timeStyle, locale));
4147                UnicodeString formattedString;
4148                if (format.isNull()) {
4149                    dataerrln("Unable to create DateFormat");
4150                    continue;
4151                }
4152                format->format(TEST_DATE, formattedString);
4153
4154                if (!showParse(*format, formattedString)) {
4155                    errln(UnicodeString("    with date-time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4156                }
4157
4158                UnicodeString ds, ts;
4159                formattedString = dateFormat->format(TEST_DATE, ds) + "  " + timeFormat->format(TEST_DATE, ts);
4160                if (!showParse(*format, formattedString)) {
4161                    errln(UnicodeString("    with date sp sp time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4162                }
4163                if (formattedString.indexOf("n ") >= 0) { // will add "." after the end of text ending in 'n', like Jan.
4164                    UnicodeString plusDot(formattedString);
4165                    plusDot.findAndReplace("n ", "n. ").append(".");
4166                    if (!showParse(*format, plusDot)) {
4167                        errln(UnicodeString("    with date plus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4168                    }
4169                }
4170                if (formattedString.indexOf(". ") >= 0) { // will subtract "." at the end of strings.
4171                    UnicodeString minusDot(formattedString);
4172                    minusDot.findAndReplace(". ", " ");
4173                    if (!showParse(*format, minusDot)) {
4174                        errln(UnicodeString("    with date minus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4175                    }
4176                }
4177            }
4178        }
4179    }
4180}
4181
4182UBool DateFormatTest::showParse(DateFormat &format, const UnicodeString &formattedString) {
4183    ParsePosition parsePosition;
4184    UDate parsed = format.parse(formattedString, parsePosition);
4185    UBool ok = TEST_DATE == parsed && parsePosition.getIndex() == formattedString.length();
4186    UnicodeString pattern;
4187    static_cast<SimpleDateFormat &>(format).toPattern(pattern);
4188    if (ok) {
4189        logln(pattern + "  parsed: " + formattedString);
4190    } else {
4191        errln(pattern + "  fails to parse: " + formattedString);
4192    }
4193    return ok;
4194}
4195
4196
4197typedef struct {
4198    const char * locale;
4199    UBool leniency;
4200    UnicodeString parseString;
4201    UnicodeString pattern;
4202    UnicodeString expectedResult;       // null indicates expected error
4203} TestDateFormatLeniencyItem;
4204
4205void DateFormatTest::TestDateFormatLeniency() {
4206    // For details see http://bugs.icu-project.org/trac/ticket/10261
4207
4208    const UDate july022008 = 1215000001979.0;
4209    const TestDateFormatLeniencyItem items[] = {
4210        //locale    leniency    parse String                    pattern                             expected result
4211        { "en",     true,       UnicodeString("2008-07 02"),    UnicodeString("yyyy-LLLL dd"),      UnicodeString("2008-July 02") },
4212        { "en",     false,      UnicodeString("2008-07 02"),    UnicodeString("yyyy-LLLL dd"),      UnicodeString("") },
4213        { "en",     true,       UnicodeString("2008-Jan 02"),   UnicodeString("yyyy-LLL. dd"),      UnicodeString("2008-Jan 02") },
4214        { "en",     false,      UnicodeString("2008-Jan 02"),   UnicodeString("yyyy-LLL. dd"),      UnicodeString("") },
4215        { "en",     true,       UnicodeString("2008-Jan--02"),  UnicodeString("yyyy-MMM' -- 'dd"),  UnicodeString("2008-Jan 02") },
4216        { "en",     false,      UnicodeString("2008-Jan--02"),  UnicodeString("yyyy-MMM' -- 'dd"),  UnicodeString("") },
4217        // terminator
4218        { NULL,     true,       UnicodeString(""),              UnicodeString(""),                  UnicodeString("") }
4219    };
4220    UErrorCode status = U_ZERO_ERROR;
4221    Calendar* cal = Calendar::createInstance(status);
4222    if (U_FAILURE(status)) {
4223        dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4224    } else {
4225        cal->setTime(july022008, status);
4226        const TestDateFormatLeniencyItem * itemPtr;
4227        for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4228
4229           Locale locale = Locale::createFromName(itemPtr->locale);
4230           status = U_ZERO_ERROR;
4231           ParsePosition pos(0);
4232           SimpleDateFormat * sdmft = new SimpleDateFormat(itemPtr->pattern, locale, status);
4233           if (U_FAILURE(status)) {
4234               dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4235               continue;
4236           }
4237           sdmft->setLenient(itemPtr->leniency);
4238           sdmft->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->leniency, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->leniency, status);
4239           /*UDate d = */sdmft->parse(itemPtr->parseString, pos);
4240
4241           delete sdmft;
4242           if(pos.getErrorIndex() > -1)
4243               if(itemPtr->expectedResult.length() != 0) {
4244                 errln("error: unexpected error - " + itemPtr->parseString + " - error index " + pos.getErrorIndex() + " - leniency " + itemPtr->leniency);
4245                 continue;
4246               } else {
4247                 continue;
4248               }
4249        }
4250    }
4251    delete cal;
4252
4253}
4254
4255#endif /* #if !UCONFIG_NO_FORMATTING */
4256
4257//eof
4258