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