Imported Upstream version 58.1
[platform/upstream/icu.git] / source / test / intltest / dtfmttst.cpp
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * COPYRIGHT:
5  * Copyright (c) 1997-2016, International Business Machines
6  * Corporation and others. All Rights Reserved.
7  ********************************************************************/
8
9 #include "unicode/utypes.h"
10
11 #if !UCONFIG_NO_FORMATTING
12
13 #include "dtfmttst.h"
14 #include "unicode/localpointer.h"
15 #include "unicode/timezone.h"
16 #include "unicode/gregocal.h"
17 #include "unicode/smpdtfmt.h"
18 #include "unicode/datefmt.h"
19 #include "unicode/dtptngen.h"
20 #include "unicode/simpletz.h"
21 #include "unicode/strenum.h"
22 #include "unicode/dtfmtsym.h"
23 #include "cmemory.h"
24 #include "cstring.h"
25 #include "caltest.h"  // for fieldName
26 #include <stdio.h> // for sprintf
27
28 #if U_PLATFORM_HAS_WIN32_API
29 #include "windttst.h"
30 #endif
31
32 #define ASSERT_OK(status)  if(U_FAILURE(status)) {errcheckln(status, #status " = %s @ %s:%d", u_errorName(status), __FILE__, __LINE__); return; }
33
34 // *****************************************************************************
35 // class DateFormatTest
36 // *****************************************************************************
37
38 void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
39 {
40     if(exec) {
41         logln("TestSuite DateFormatTest: ");
42     }
43     TESTCASE_AUTO_BEGIN;
44     TESTCASE_AUTO(TestPatterns);
45     TESTCASE_AUTO(TestEquals);
46     TESTCASE_AUTO(TestTwoDigitYearDSTParse);
47     TESTCASE_AUTO(TestFieldPosition);
48     TESTCASE_AUTO(TestPartialParse994);
49     TESTCASE_AUTO(TestRunTogetherPattern985);
50     TESTCASE_AUTO(TestRunTogetherPattern917);
51     TESTCASE_AUTO(TestCzechMonths459);
52     TESTCASE_AUTO(TestLetterDPattern212);
53     TESTCASE_AUTO(TestDayOfYearPattern195);
54     TESTCASE_AUTO(TestQuotePattern161);
55     TESTCASE_AUTO(TestBadInput135);
56     TESTCASE_AUTO(TestBadInput135a);
57     TESTCASE_AUTO(TestTwoDigitYear);
58     TESTCASE_AUTO(TestDateFormatZone061);
59     TESTCASE_AUTO(TestDateFormatZone146);
60     TESTCASE_AUTO(TestLocaleDateFormat);
61     TESTCASE_AUTO(TestFormattingLocaleTimeSeparator);
62     TESTCASE_AUTO(TestWallyWedel);
63     TESTCASE_AUTO(TestDateFormatCalendar);
64     TESTCASE_AUTO(TestSpaceParsing);
65     TESTCASE_AUTO(TestExactCountFormat);
66     TESTCASE_AUTO(TestWhiteSpaceParsing);
67     TESTCASE_AUTO(TestInvalidPattern);
68     TESTCASE_AUTO(TestGeneral);
69     TESTCASE_AUTO(TestGreekMay);
70     TESTCASE_AUTO(TestGenericTime);
71     TESTCASE_AUTO(TestGenericTimeZoneOrder);
72     TESTCASE_AUTO(TestHost);
73     TESTCASE_AUTO(TestEras);
74     TESTCASE_AUTO(TestNarrowNames);
75     TESTCASE_AUTO(TestShortDays);
76     TESTCASE_AUTO(TestStandAloneDays);
77     TESTCASE_AUTO(TestStandAloneMonths);
78     TESTCASE_AUTO(TestQuarters);
79     TESTCASE_AUTO(TestZTimeZoneParsing);
80     TESTCASE_AUTO(TestRelative);
81     TESTCASE_AUTO(TestRelativeClone);
82     TESTCASE_AUTO(TestHostClone);
83     TESTCASE_AUTO(TestHebrewClone);
84     TESTCASE_AUTO(TestDateFormatSymbolsClone);
85     TESTCASE_AUTO(TestTimeZoneDisplayName);
86     TESTCASE_AUTO(TestRoundtripWithCalendar);
87     TESTCASE_AUTO(Test6338);
88     TESTCASE_AUTO(Test6726);
89     TESTCASE_AUTO(TestGMTParsing);
90     TESTCASE_AUTO(Test6880);
91     TESTCASE_AUTO(TestISOEra);
92     TESTCASE_AUTO(TestFormalChineseDate);
93     TESTCASE_AUTO(TestNumberAsStringParsing);
94     TESTCASE_AUTO(TestStandAloneGMTParse);
95     TESTCASE_AUTO(TestParsePosition);
96     TESTCASE_AUTO(TestMonthPatterns);
97     TESTCASE_AUTO(TestContext);
98     TESTCASE_AUTO(TestNonGregoFmtParse);
99     TESTCASE_AUTO(TestFormatsWithNumberSystems);
100     /*
101     TESTCASE_AUTO(TestRelativeError);
102     TESTCASE_AUTO(TestRelativeOther);
103     */
104     TESTCASE_AUTO(TestDotAndAtLeniency);
105     TESTCASE_AUTO(TestDateFormatLeniency);
106     TESTCASE_AUTO(TestParseMultiPatternMatch);
107
108     TESTCASE_AUTO(TestParseLeniencyAPIs);
109     TESTCASE_AUTO(TestNumberFormatOverride);
110     TESTCASE_AUTO(TestCreateInstanceForSkeleton);
111     TESTCASE_AUTO(TestCreateInstanceForSkeletonDefault);
112     TESTCASE_AUTO(TestCreateInstanceForSkeletonWithCalendar);
113     TESTCASE_AUTO(TestDFSCreateForLocaleNonGregorianLocale);
114     TESTCASE_AUTO(TestDFSCreateForLocaleWithCalendarInLocale);
115     TESTCASE_AUTO(TestChangeCalendar);
116
117     TESTCASE_AUTO(TestPatternFromSkeleton);
118
119     TESTCASE_AUTO(TestAmPmMidnightNoon);
120     TESTCASE_AUTO(TestFlexibleDayPeriod);
121     TESTCASE_AUTO(TestDayPeriodWithLocales);
122     TESTCASE_AUTO(TestMinuteSecondFieldsInOddPlaces);
123     TESTCASE_AUTO(TestDayPeriodParsing);
124
125     TESTCASE_AUTO_END;
126 }
127
128 void DateFormatTest::TestPatterns() {
129     static const struct {
130         const char *actualPattern;
131         const char *expectedPattern;
132         const char *localeID;
133         const char *expectedLocalPattern;
134     } EXPECTED[] = {
135         {UDAT_YEAR, "y","en","y"},
136
137         {UDAT_QUARTER, "QQQQ", "en", "QQQQ"},
138         {UDAT_ABBR_QUARTER, "QQQ", "en", "QQQ"},
139         {UDAT_YEAR_QUARTER, "yQQQQ", "en", "QQQQ y"},
140         {UDAT_YEAR_ABBR_QUARTER, "yQQQ", "en", "QQQ y"},
141
142         {UDAT_NUM_MONTH, "M", "en", "L"},
143         {UDAT_ABBR_MONTH, "MMM", "en", "LLL"},
144         {UDAT_MONTH, "MMMM", "en", "LLLL"},
145         {UDAT_YEAR_NUM_MONTH, "yM","en","M/y"},
146         {UDAT_YEAR_ABBR_MONTH, "yMMM","en","MMM y"},
147         {UDAT_YEAR_MONTH, "yMMMM","en","MMMM y"},
148
149         {UDAT_DAY, "d","en","d"},
150         {UDAT_YEAR_NUM_MONTH_DAY, "yMd", "en", "M/d/y"},
151         {UDAT_YEAR_ABBR_MONTH_DAY, "yMMMd", "en", "MMM d, y"},
152         {UDAT_YEAR_MONTH_DAY, "yMMMMd", "en", "MMMM d, y"},
153         {UDAT_YEAR_NUM_MONTH_WEEKDAY_DAY, "yMEd", "en", "EEE, M/d/y"},
154         {UDAT_YEAR_ABBR_MONTH_WEEKDAY_DAY, "yMMMEd", "en", "EEE, MMM d, y"},
155         {UDAT_YEAR_MONTH_WEEKDAY_DAY, "yMMMMEEEEd", "en", "EEEE, MMMM d, y"},
156
157         {UDAT_NUM_MONTH_DAY, "Md","en","M/d"},
158         {UDAT_ABBR_MONTH_DAY, "MMMd","en","MMM d"},
159         {UDAT_MONTH_DAY, "MMMMd","en","MMMM d"},
160         {UDAT_NUM_MONTH_WEEKDAY_DAY, "MEd","en","EEE, M/d"},
161         {UDAT_ABBR_MONTH_WEEKDAY_DAY, "MMMEd","en","EEE, MMM d"},
162         {UDAT_MONTH_WEEKDAY_DAY, "MMMMEEEEd","en","EEEE, MMMM d"},
163
164         {UDAT_HOUR, "j", "en", "h a"}, // (fixed expected result per ticket 6872<-6626)
165         {UDAT_HOUR24, "H", "en", "HH"}, // (fixed expected result per ticket 6872<-6626
166
167         {UDAT_MINUTE, "m", "en", "m"},
168         {UDAT_HOUR_MINUTE, "jm","en","h:mm a"}, // (fixed expected result per ticket 6872<-7180)
169         {UDAT_HOUR24_MINUTE, "Hm", "en", "HH:mm"}, // (fixed expected result per ticket 6872<-6626)
170
171         {UDAT_SECOND, "s", "en", "s"},
172         {UDAT_HOUR_MINUTE_SECOND, "jms","en","h:mm:ss a"}, // (fixed expected result per ticket 6872<-7180)
173         {UDAT_HOUR24_MINUTE_SECOND, "Hms","en","HH:mm:ss"}, // (fixed expected result per ticket 6872<-6626)
174         {UDAT_MINUTE_SECOND, "ms", "en", "mm:ss"}, // (fixed expected result per ticket 6872<-6626)
175
176         {UDAT_LOCATION_TZ, "VVVV", "en", "VVVV"},
177         {UDAT_GENERIC_TZ, "vvvv", "en", "vvvv"},
178         {UDAT_ABBR_GENERIC_TZ, "v", "en", "v"},
179         {UDAT_SPECIFIC_TZ, "zzzz", "en", "zzzz"},
180         {UDAT_ABBR_SPECIFIC_TZ, "z", "en", "z"},
181         {UDAT_ABBR_UTC_TZ, "ZZZZ", "en", "ZZZZ"},
182
183         {UDAT_YEAR_NUM_MONTH_DAY UDAT_ABBR_UTC_TZ, "yMdZZZZ", "en", "M/d/y, ZZZZ"},
184         {UDAT_MONTH_DAY UDAT_LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d, VVVV"}
185     };
186
187     IcuTestErrorCode errorCode(*this, "TestPatterns()");
188     for (int32_t i = 0; i < UPRV_LENGTHOF(EXPECTED); i++) {
189         // Verify that patterns have the correct values
190         UnicodeString actualPattern(EXPECTED[i].actualPattern, -1, US_INV);
191         UnicodeString expectedPattern(EXPECTED[i].expectedPattern, -1, US_INV);
192         Locale locale(EXPECTED[i].localeID);
193         if (actualPattern != expectedPattern) {
194             errln("FAILURE! Expected pattern: " + expectedPattern +
195                     " but was: " + actualPattern);
196         }
197
198         // Verify that DataFormat instances produced contain the correct
199         // localized patterns
200         // TODO: use DateFormat::getInstanceForSkeleton(), ticket #9029
201         // Java test code:
202         // DateFormat date1 = DateFormat.getPatternInstance(actualPattern,
203         //         locale);
204         // DateFormat date2 = DateFormat.getPatternInstance(Calendar.getInstance(locale),
205         //         actualPattern, locale);
206         LocalPointer<DateTimePatternGenerator> generator(
207                 DateTimePatternGenerator::createInstance(locale, errorCode));
208         if(errorCode.logDataIfFailureAndReset("DateTimePatternGenerator::createInstance() failed for locale ID \"%s\"", EXPECTED[i].localeID)) {
209             continue;
210         }
211         UnicodeString pattern = generator->getBestPattern(actualPattern, errorCode);
212         SimpleDateFormat date1(pattern, locale, errorCode);
213         SimpleDateFormat date2(pattern, locale, errorCode);
214         date2.adoptCalendar(Calendar::createInstance(locale, errorCode));
215         if(errorCode.logIfFailureAndReset("DateFormat::getInstanceForSkeleton() failed")) {
216             errln("  for actualPattern \"%s\" & locale ID \"%s\"",
217                   EXPECTED[i].actualPattern, EXPECTED[i].localeID);
218             continue;
219         }
220
221         UnicodeString expectedLocalPattern(EXPECTED[i].expectedLocalPattern, -1, US_INV);
222         UnicodeString actualLocalPattern1;
223         UnicodeString actualLocalPattern2;
224         date1.toLocalizedPattern(actualLocalPattern1, errorCode);
225         date2.toLocalizedPattern(actualLocalPattern2, errorCode);
226         if (actualLocalPattern1 != expectedLocalPattern) {
227             errln("FAILURE! Expected local pattern: " + expectedLocalPattern
228                     + " but was: " + actualLocalPattern1);
229         }
230         if (actualLocalPattern2 != expectedLocalPattern) {
231             errln("FAILURE! Expected local pattern: " + expectedLocalPattern
232                     + " but was: " + actualLocalPattern2);
233         }
234     }
235 }
236
237 // Test written by Wally Wedel and emailed to me.
238 void DateFormatTest::TestWallyWedel()
239 {
240     UErrorCode status = U_ZERO_ERROR;
241     /*
242      * Instantiate a TimeZone so we can get the ids.
243      */
244     TimeZone *tz = new SimpleTimeZone(7,"");
245     /*
246      * Computational variables.
247      */
248     int32_t offset, hours, minutes, seconds;
249     /*
250      * Instantiate a SimpleDateFormat set up to produce a full time
251      zone name.
252      */
253     SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)"zzzz", status);
254     /*
255      * A String array for the time zone ids.
256      */
257     int32_t ids_length;
258     StringEnumeration* ids = TimeZone::createEnumeration();
259     if (ids == NULL) {
260         dataerrln("Unable to create TimeZone enumeration.");
261         if (sdf != NULL) {
262             delete sdf;
263         }
264         return;
265     }
266     ids_length = ids->count(status);
267     /*
268      * How many ids do we have?
269      */
270     logln("Time Zone IDs size: %d", ids_length);
271     /*
272      * Column headings (sort of)
273      */
274     logln("Ordinal ID offset(h:m) name");
275     /*
276      * Loop through the tzs.
277      */
278     UDate today = Calendar::getNow();
279     Calendar *cal = Calendar::createInstance(status);
280     for (int32_t i = 0; i < ids_length; i++) {
281         // logln(i + " " + ids[i]);
282         const UnicodeString* id = ids->snext(status);
283         TimeZone *ttz = TimeZone::createTimeZone(*id);
284         // offset = ttz.getRawOffset();
285         cal->setTimeZone(*ttz);
286         cal->setTime(today, status);
287         offset = cal->get(UCAL_ZONE_OFFSET, status) + cal->get(UCAL_DST_OFFSET, status);
288         // logln(i + " " + ids[i] + " offset " + offset);
289         const char* sign = "+";
290         if (offset < 0) {
291             sign = "-";
292             offset = -offset;
293         }
294         hours = offset/3600000;
295         minutes = (offset%3600000)/60000;
296         seconds = (offset%60000)/1000;
297         UnicodeString dstOffset = (UnicodeString)"" + sign + (hours < 10 ? "0" : "") +
298             (int32_t)hours + ":" + (minutes < 10 ? "0" : "") + (int32_t)minutes;
299         if (seconds != 0) {
300             dstOffset = dstOffset + ":" + (seconds < 10 ? "0" : "") + seconds;
301         }
302         /*
303          * Instantiate a date so we can display the time zone name.
304          */
305         sdf->setTimeZone(*ttz);
306         /*
307          * Format the output.
308          */
309         UnicodeString fmtOffset;
310         FieldPosition pos(FieldPosition::DONT_CARE);
311         sdf->format(today,fmtOffset, pos);
312         // UnicodeString fmtOffset = tzS.toString();
313         UnicodeString *fmtDstOffset = 0;
314         if (fmtOffset.startsWith("GMT") && fmtOffset.length() != 3)
315         {
316             //fmtDstOffset = fmtOffset->substring(3);
317             fmtDstOffset = new UnicodeString();
318             fmtOffset.extract(3, fmtOffset.length(), *fmtDstOffset);
319         }
320         /*
321          * Show our result.
322          */
323         UBool ok = fmtDstOffset == 0 || *fmtDstOffset == dstOffset;
324         if (ok)
325         {
326             logln(UnicodeString() + i + " " + *id + " " + dstOffset +
327                   " " + fmtOffset +
328                   (fmtDstOffset != 0 ? " ok" : " ?"));
329         }
330         else
331         {
332             errln(UnicodeString() + i + " " + *id + " " + dstOffset +
333                   " " + fmtOffset + " *** FAIL ***");
334         }
335         delete ttz;
336         delete fmtDstOffset;
337     }
338     delete cal;
339     //  delete ids;   // TODO:  BAD API
340     delete ids;
341     delete sdf;
342     delete tz;
343 }
344
345 // -------------------------------------
346
347 /**
348  * Test operator==
349  */
350 void
351 DateFormatTest::TestEquals()
352 {
353     DateFormat* fmtA = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
354     DateFormat* fmtB = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
355     if ( fmtA == NULL || fmtB == NULL){
356         dataerrln("Error calling DateFormat::createDateTimeInstance");
357         delete fmtA;
358         delete fmtB;
359         return;
360     }
361
362     if (!(*fmtA == *fmtB)) errln((UnicodeString)"FAIL");
363     delete fmtA;
364     delete fmtB;
365
366     TimeZone* test = TimeZone::createTimeZone("PDT");
367     delete test;
368 }
369
370 // -------------------------------------
371
372 /**
373  * Test the parsing of 2-digit years.
374  */
375 void
376 DateFormatTest::TestTwoDigitYearDSTParse(void)
377 {
378     UErrorCode status = U_ZERO_ERROR;
379     SimpleDateFormat* fullFmt = new SimpleDateFormat((UnicodeString)"EEE MMM dd HH:mm:ss.SSS zzz yyyy G", status);
380     SimpleDateFormat *fmt = new SimpleDateFormat((UnicodeString)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status);
381     //DateFormat* fmt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, Locale::ENGLISH);
382     UnicodeString* s = new UnicodeString("03-Apr-04 2:20:47 o'clock AM PST", "");
383     TimeZone* defaultTZ = TimeZone::createDefault();
384     TimeZone* PST = TimeZone::createTimeZone("PST");
385     int32_t defaultOffset = defaultTZ->getRawOffset();
386     int32_t PSTOffset = PST->getRawOffset();
387     int32_t hour = 2 + (defaultOffset - PSTOffset) / (60*60*1000);
388     // hour is the expected hour of day, in units of seconds
389     hour = ((hour < 0) ? hour + 24 : hour) * 60*60;
390
391     UnicodeString str;
392
393     if(U_FAILURE(status)) {
394         dataerrln("Could not set up test. exitting - %s", u_errorName(status));
395         return;
396     }
397
398     UDate d = fmt->parse(*s, status);
399     logln(*s + " P> " + ((DateFormat*)fullFmt)->format(d, str));
400     int32_t y, m, day, hr, min, sec;
401     dateToFields(d, y, m, day, hr, min, sec);
402     hour += defaultTZ->inDaylightTime(d, status) ? 1 : 0;
403     hr = hr*60*60;
404     if (hr != hour)
405         errln((UnicodeString)"FAIL: Should parse to hour " + hour + " but got " + hr);
406
407     if (U_FAILURE(status))
408         errln((UnicodeString)"FAIL: " + (int32_t)status);
409
410     delete s;
411     delete fmt;
412     delete fullFmt;
413     delete PST;
414     delete defaultTZ;
415 }
416
417 // -------------------------------------
418
419 UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
420
421 UnicodeString&
422 DateFormatTest::escape(UnicodeString& s)
423 {
424     UnicodeString buf;
425     for (int32_t i=0; i<s.length(); ++i)
426     {
427         UChar c = s[(int32_t)i];
428         if (c <= (UChar)0x7F) buf += c;
429         else {
430             buf += (UChar)0x5c; buf += (UChar)0x55;
431             buf += toHexString((c & 0xF000) >> 12);
432             buf += toHexString((c & 0x0F00) >> 8);
433             buf += toHexString((c & 0x00F0) >> 4);
434             buf += toHexString(c & 0x000F);
435         }
436     }
437     return (s = buf);
438 }
439
440 // -------------------------------------
441
442 /**
443  * This MUST be kept in sync with DateFormatSymbols.gPatternChars.
444  */
445 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
446 static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:";
447 #else
448 static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB";
449 #endif
450
451 /**
452  * A list of the names of all the fields in DateFormat.
453  * This MUST be kept in sync with DateFormat.
454  */
455 static const char* DATEFORMAT_FIELD_NAMES[] = {
456     "ERA_FIELD",
457     "YEAR_FIELD",
458     "MONTH_FIELD",
459     "DATE_FIELD",
460     "HOUR_OF_DAY1_FIELD",
461     "HOUR_OF_DAY0_FIELD",
462     "MINUTE_FIELD",
463     "SECOND_FIELD",
464     "MILLISECOND_FIELD",
465     "DAY_OF_WEEK_FIELD",
466     "DAY_OF_YEAR_FIELD",
467     "DAY_OF_WEEK_IN_MONTH_FIELD",
468     "WEEK_OF_YEAR_FIELD",
469     "WEEK_OF_MONTH_FIELD",
470     "AM_PM_FIELD",
471     "HOUR1_FIELD",
472     "HOUR0_FIELD",
473     "TIMEZONE_FIELD",
474     "YEAR_WOY_FIELD",
475     "DOW_LOCAL_FIELD",
476     "EXTENDED_YEAR_FIELD",
477     "JULIAN_DAY_FIELD",
478     "MILLISECONDS_IN_DAY_FIELD",
479     "TIMEZONE_RFC_FIELD",
480     "GENERIC_TIMEZONE_FIELD",
481     "STAND_ALONE_DAY_FIELD",
482     "STAND_ALONE_MONTH_FIELD",
483     "QUARTER_FIELD",
484     "STAND_ALONE_QUARTER_FIELD",
485     "TIMEZONE_SPECIAL_FIELD",
486     "YEAR_NAME_FIELD",
487     "TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD",
488     "TIMEZONE_ISO_FIELD",
489     "TIMEZONE_ISO_LOCAL_FIELD",
490     "RELATED_YEAR_FIELD",
491     "AM_PM_MIDNIGHT_NOON_FIELD",
492     "FLEXIBLE_DAY_PERIOD_FIELD",
493     "UDAT_TIME_SEPARATOR_FIELD",
494 };
495
496 static const int32_t DATEFORMAT_FIELD_NAMES_LENGTH =
497     UPRV_LENGTHOF(DATEFORMAT_FIELD_NAMES);
498
499 /**
500  * Verify that returned field position indices are correct.
501  */
502 void DateFormatTest::TestFieldPosition() {
503     UErrorCode ec = U_ZERO_ERROR;
504     int32_t i, j, exp;
505     UnicodeString buf;
506
507     // Verify data
508     DateFormatSymbols rootSyms(Locale(""), ec);
509     if (U_FAILURE(ec)) {
510         dataerrln("Unable to create DateFormatSymbols - %s", u_errorName(ec));
511         return;
512     }
513
514     // local pattern chars data is not longer loaded
515     // from icu locale bundle
516     assertEquals("patternChars", PATTERN_CHARS, rootSyms.getLocalPatternChars(buf));
517     assertEquals("patternChars", PATTERN_CHARS, DateFormatSymbols::getPatternUChars());
518     assertTrue("DATEFORMAT_FIELD_NAMES", DATEFORMAT_FIELD_NAMES_LENGTH == UDAT_FIELD_COUNT);
519 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
520     assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS));
521 #else
522     assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS) + 1); // +1 for missing TIME_SEPARATOR pattern char
523 #endif
524
525     // Create test formatters
526     const int32_t COUNT = 4;
527     DateFormat* dateFormats[COUNT];
528     dateFormats[0] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getUS());
529     dateFormats[1] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getFrance());
530     // Make the pattern "G y M d..."
531     buf.remove().append(PATTERN_CHARS);
532     for (j=buf.length()-1; j>=0; --j) buf.insert(j, (UChar)32/*' '*/);
533     dateFormats[2] = new SimpleDateFormat(buf, Locale::getUS(), ec);
534     // Make the pattern "GGGG yyyy MMMM dddd..."
535     for (j=buf.length()-1; j>=0; j-=2) {
536         for (i=0; i<3; ++i) {
537             buf.insert(j, buf.charAt(j));
538         }
539     }
540     dateFormats[3] = new SimpleDateFormat(buf, Locale::getUS(), ec);
541     if(U_FAILURE(ec)){
542         errln(UnicodeString("Could not create SimpleDateFormat object for locale en_US. Error: " )+ UnicodeString(u_errorName(ec)));
543         return;
544     }
545     UDate aug13 = 871508052513.0;
546
547     // Expected output field values for above DateFormats on aug13
548     // Fields are given in order of DateFormat field number
549     const char* EXPECTED[] = {
550         "", "1997", "August", "13", "", "", "34", "12", "", "Wednesday",
551         "", "", "", "", "PM", "2", "", "Pacific Daylight Time", "", "",
552         "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
553 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
554         ":",
555 #else
556         "",
557 #endif
558
559         "", "1997", "ao\\u00FBt", "13", "", "14", "34", "12", "", "mercredi",
560         "", "", "", "", "", "", "", "heure d\\u2019\\u00E9t\\u00E9 du Pacifique", "", "",
561         "", "", "", "", "",  "", "", "", "", "", "", "", "", "", "", "", "",
562 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
563         ":",
564 #else
565         "",
566 #endif
567
568         "AD", "1997", "8", "13", "14", "14", "34", "12", "5", "Wed",
569         "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4",
570         "1997", "2450674", "52452513", "-0700", "PT",  "4", "8", "3", "3", "uslax",
571         "1997", "GMT-7", "-07", "-07", "1997", "PM", "in the afternoon",
572 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
573         ":",
574 #else
575         "",
576 #endif
577
578         "Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130", "Wednesday",
579         "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "Wednesday",
580         "1997", "2450674", "52452513", "GMT-07:00", "Pacific Time",  "Wednesday", "August", "3rd quarter", "3rd quarter", "Los Angeles Time",
581         "1997", "GMT-07:00", "-0700", "-0700", "1997", "PM", "in the afternoon",
582 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
583         ":",
584 #else
585         "",
586 #endif
587     };
588
589     const int32_t EXPECTED_LENGTH = UPRV_LENGTHOF(EXPECTED);
590
591     assertTrue("data size", EXPECTED_LENGTH == COUNT * UDAT_FIELD_COUNT);
592
593     TimeZone* PT = TimeZone::createTimeZone("America/Los_Angeles");
594     for (j = 0, exp = 0; j < COUNT; ++j) {
595         //  String str;
596         DateFormat* df = dateFormats[j];
597         df->setTimeZone(*PT);
598         SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
599         if (sdtfmt != NULL) {
600             logln(" Pattern = " + sdtfmt->toPattern(buf.remove()));
601         } else {
602             logln(" Pattern = ? (not a SimpleDateFormat)");
603         }
604         logln((UnicodeString)"  Result = " + df->format(aug13, buf.remove()));
605
606         int32_t expBase = exp; // save for later
607         for (i = 0; i < UDAT_FIELD_COUNT; ++i, ++exp) {
608             FieldPosition pos(i);
609             buf.remove();
610             df->format(aug13, buf, pos);
611             UnicodeString field;
612             buf.extractBetween(pos.getBeginIndex(), pos.getEndIndex(), field);
613             assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
614                          ctou(EXPECTED[exp]), field);
615         }
616
617         // test FieldPositionIterator API
618         logln("FieldPositionIterator");
619         {
620           UErrorCode status = U_ZERO_ERROR;
621           FieldPositionIterator posIter;
622           FieldPosition fp;
623
624           buf.remove();
625           df->format(aug13, buf, &posIter, status);
626           while (posIter.next(fp)) {
627             int32_t i = fp.getField();
628             UnicodeString field;
629             buf.extractBetween(fp.getBeginIndex(), fp.getEndIndex(), field);
630             assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
631                          ctou(EXPECTED[expBase + i]), field);
632           }
633
634         }
635     }
636
637
638     // test null posIter
639     buf.remove();
640     UErrorCode status = U_ZERO_ERROR;
641     dateFormats[0]->format(aug13, buf, NULL, status);
642     // if we didn't crash, we succeeded.
643
644     for (i=0; i<COUNT; ++i) {
645         delete dateFormats[i];
646     }
647     delete PT;
648 }
649
650 // -------------------------------------
651
652 /**
653  * General parse/format tests.  Add test cases as needed.
654  */
655 void DateFormatTest::TestGeneral() {
656     const char* DATA[] = {
657         "yyyy MM dd HH:mm:ss.SSS",
658
659         // Milliseconds are left-justified, since they format as fractions of a second
660         "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",
661         "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",
662         "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567",
663         "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",
664     };
665     expect(DATA, UPRV_LENGTHOF(DATA), Locale("en", "", ""));
666 }
667
668 // -------------------------------------
669
670 /**
671  * Verify that strings which contain incomplete specifications are parsed
672  * correctly.  In some instances, this means not being parsed at all, and
673  * returning an appropriate error.
674  */
675 void
676 DateFormatTest::TestPartialParse994()
677 {
678     UErrorCode status = U_ZERO_ERROR;
679     SimpleDateFormat* f = new SimpleDateFormat(status);
680     if (U_FAILURE(status)) {
681         dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
682         delete f;
683         return;
684     }
685     UDate null = 0;
686     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", date(97, 1 - 1, 17, 10, 11, 42));
687     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null);
688     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null);
689     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null);
690     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null);
691     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
692     delete f;
693 }
694
695 // -------------------------------------
696
697 void
698 DateFormatTest::tryPat994(SimpleDateFormat* format, const char* pat, const char* str, UDate expected)
699 {
700     UErrorCode status = U_ZERO_ERROR;
701     UDate null = 0;
702     logln(UnicodeString("Pattern \"") + pat + "\"   String \"" + str + "\"");
703     //try {
704         format->applyPattern(pat);
705         UDate date = format->parse(str, status);
706         if (U_FAILURE(status) || date == null)
707         {
708             logln((UnicodeString)"ParseException: " + (int32_t)status);
709             if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
710         }
711         else
712         {
713             UnicodeString f;
714             ((DateFormat*)format)->format(date, f);
715             logln(UnicodeString(" parse(") + str + ") -> " + dateToString(date));
716             logln((UnicodeString)" format -> " + f);
717             if (expected == null ||
718                 !(date == expected)) errln((UnicodeString)"FAIL: Expected null");//" + expected);
719             if (!(f == str)) errln(UnicodeString("FAIL: Expected ") + str);
720         }
721     //}
722     //catch(ParseException e) {
723     //    logln((UnicodeString)"ParseException: " + e.getMessage());
724     //    if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
725     //}
726     //catch(Exception e) {
727     //    errln((UnicodeString)"*** Exception:");
728     //    e.printStackTrace();
729     //}
730 }
731
732 // -------------------------------------
733
734 /**
735  * Verify the behavior of patterns in which digits for different fields run together
736  * without intervening separators.
737  */
738 void
739 DateFormatTest::TestRunTogetherPattern985()
740 {
741     UErrorCode status = U_ZERO_ERROR;
742     UnicodeString format("yyyyMMddHHmmssSSS");
743     UnicodeString now, then;
744     //UBool flag;
745     SimpleDateFormat *formatter = new SimpleDateFormat(format, status);
746     if (U_FAILURE(status)) {
747         dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
748         delete formatter;
749         return;
750     }
751     UDate date1 = Calendar::getNow();
752     ((DateFormat*)formatter)->format(date1, now);
753     logln(now);
754     ParsePosition pos(0);
755     UDate date2 = formatter->parse(now, pos);
756     if (date2 == 0) then = UnicodeString("Parse stopped at ") + pos.getIndex();
757     else ((DateFormat*)formatter)->format(date2, then);
758     logln(then);
759     if (!(date2 == date1)) errln((UnicodeString)"FAIL");
760     delete formatter;
761     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
762 }
763
764 // -------------------------------------
765
766 /**
767  * Verify the behavior of patterns in which digits for different fields run together
768  * without intervening separators.
769  */
770 void
771 DateFormatTest::TestRunTogetherPattern917()
772 {
773     UErrorCode status = U_ZERO_ERROR;
774     SimpleDateFormat* fmt;
775     UnicodeString myDate;
776     fmt = new SimpleDateFormat((UnicodeString)"yyyy/MM/dd", status);
777     if (U_FAILURE(status)) {
778         dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
779         delete fmt;
780         return;
781     }
782     myDate = "1997/02/03";
783     testIt917(fmt, myDate, date(97, 2 - 1, 3));
784     delete fmt;
785     fmt = new SimpleDateFormat((UnicodeString)"yyyyMMdd", status);
786     myDate = "19970304";
787     testIt917(fmt, myDate, date(97, 3 - 1, 4));
788     delete fmt;
789     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
790 }
791
792 // -------------------------------------
793
794 void
795 DateFormatTest::testIt917(SimpleDateFormat* fmt, UnicodeString& str, UDate expected)
796 {
797     UErrorCode status = U_ZERO_ERROR;
798     UnicodeString pattern;
799     logln((UnicodeString)"pattern=" + fmt->toPattern(pattern) + "   string=" + str);
800     Formattable o;
801     //try {
802         ((Format*)fmt)->parseObject(str, o, status);
803     //}
804     if (U_FAILURE(status)) return;
805     //catch(ParseException e) {
806     //    e.printStackTrace();
807     //    return;
808     //}
809     logln((UnicodeString)"Parsed object: " + dateToString(o.getDate()));
810     if (!(o.getDate() == expected)) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
811     UnicodeString formatted; ((Format*)fmt)->format(o, formatted, status);
812     logln((UnicodeString)"Formatted string: " + formatted);
813     if (!(formatted == str)) errln((UnicodeString)"FAIL: Expected " + str);
814     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
815 }
816
817 // -------------------------------------
818
819 /**
820  * Verify the handling of Czech June and July, which have the unique attribute that
821  * one is a proper prefix substring of the other.
822  */
823 void
824 DateFormatTest::TestCzechMonths459()
825 {
826     UErrorCode status = U_ZERO_ERROR;
827     DateFormat* fmt = DateFormat::createDateInstance(DateFormat::FULL, Locale("cs", "", ""));
828     if (fmt == NULL){
829         dataerrln("Error calling DateFormat::createDateInstance()");
830         return;
831     }
832
833     UnicodeString pattern;
834     logln((UnicodeString)"Pattern " + ((SimpleDateFormat*) fmt)->toPattern(pattern));
835     UDate june = date(97, UCAL_JUNE, 15);
836     UDate july = date(97, UCAL_JULY, 15);
837     UnicodeString juneStr; fmt->format(june, juneStr);
838     UnicodeString julyStr; fmt->format(july, julyStr);
839     //try {
840         logln((UnicodeString)"format(June 15 1997) = " + juneStr);
841         UDate d = fmt->parse(juneStr, status);
842         UnicodeString s; fmt->format(d, s);
843         int32_t month,yr,day,hr,min,sec; dateToFields(d,yr,month,day,hr,min,sec);
844         logln((UnicodeString)"  -> parse -> " + s + " (month = " + month + ")");
845         if (month != UCAL_JUNE) errln((UnicodeString)"FAIL: Month should be June");
846         logln((UnicodeString)"format(July 15 1997) = " + julyStr);
847         d = fmt->parse(julyStr, status);
848         fmt->format(d, s);
849         dateToFields(d,yr,month,day,hr,min,sec);
850         logln((UnicodeString)"  -> parse -> " + s + " (month = " + month + ")");
851         if (month != UCAL_JULY) errln((UnicodeString)"FAIL: Month should be July");
852     //}
853     //catch(ParseException e) {
854     if (U_FAILURE(status))
855         errln((UnicodeString)"Exception: " + (int32_t)status);
856     //}
857     delete fmt;
858 }
859
860 // -------------------------------------
861
862 /**
863  * Test the handling of 'D' in patterns.
864  */
865 void
866 DateFormatTest::TestLetterDPattern212()
867 {
868     UErrorCode status = U_ZERO_ERROR;
869     UnicodeString dateString("1995-040.05:01:29");
870     UnicodeString bigD("yyyy-DDD.hh:mm:ss");
871     UnicodeString littleD("yyyy-ddd.hh:mm:ss");
872     UDate expLittleD = date(95, 0, 1, 5, 1, 29);
873     UDate expBigD = expLittleD + 39 * 24 * 3600000.0;
874     expLittleD = expBigD; // Expect the same, with default lenient parsing
875     logln((UnicodeString)"dateString= " + dateString);
876     SimpleDateFormat *formatter = new SimpleDateFormat(bigD, status);
877     if (U_FAILURE(status)) {
878         dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
879         delete formatter;
880         return;
881     }
882     ParsePosition pos(0);
883     UDate myDate = formatter->parse(dateString, pos);
884     logln((UnicodeString)"Using " + bigD + " -> " + myDate);
885     if (myDate != expBigD) errln((UnicodeString)"FAIL: bigD - Expected " + dateToString(expBigD));
886     delete formatter;
887     formatter = new SimpleDateFormat(littleD, status);
888     ASSERT_OK(status);
889     pos = ParsePosition(0);
890     myDate = formatter->parse(dateString, pos);
891     logln((UnicodeString)"Using " + littleD + " -> " + dateToString(myDate));
892     if (myDate != expLittleD) errln((UnicodeString)"FAIL: littleD - Expected " + dateToString(expLittleD));
893     delete formatter;
894     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
895 }
896
897 // -------------------------------------
898
899 /**
900  * Test the day of year pattern.
901  */
902 void
903 DateFormatTest::TestDayOfYearPattern195()
904 {
905     UErrorCode status = U_ZERO_ERROR;
906     UDate today = Calendar::getNow();
907     int32_t year,month,day,hour,min,sec; dateToFields(today,year,month,day,hour,min,sec);
908     UDate expected = date(year, month, day);
909     logln((UnicodeString)"Test Date: " + dateToString(today));
910     SimpleDateFormat* sdf = (SimpleDateFormat*)DateFormat::createDateInstance();
911     if (sdf == NULL){
912         dataerrln("Error calling DateFormat::createDateInstance()");
913         return;
914     }
915     tryPattern(*sdf, today, 0, expected);
916     tryPattern(*sdf, today, "G yyyy DDD", expected);
917     delete sdf;
918     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
919 }
920
921 // -------------------------------------
922
923 void
924 DateFormatTest::tryPattern(SimpleDateFormat& sdf, UDate d, const char* pattern, UDate expected)
925 {
926     UErrorCode status = U_ZERO_ERROR;
927     if (pattern != 0) sdf.applyPattern(pattern);
928     UnicodeString thePat;
929     logln((UnicodeString)"pattern: " + sdf.toPattern(thePat));
930     UnicodeString formatResult; (*(DateFormat*)&sdf).format(d, formatResult);
931     logln((UnicodeString)" format -> " + formatResult);
932     // try {
933         UDate d2 = sdf.parse(formatResult, status);
934         logln((UnicodeString)" parse(" + formatResult + ") -> " + dateToString(d2));
935         if (d2 != expected) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
936         UnicodeString format2; (*(DateFormat*)&sdf).format(d2, format2);
937         logln((UnicodeString)" format -> " + format2);
938         if (!(formatResult == format2)) errln((UnicodeString)"FAIL: Round trip drift");
939     //}
940     //catch(Exception e) {
941     if (U_FAILURE(status))
942         errln((UnicodeString)"Error: " + (int32_t)status);
943     //}
944 }
945
946 // -------------------------------------
947
948 /**
949  * Test the handling of single quotes in patterns.
950  */
951 void
952 DateFormatTest::TestQuotePattern161()
953 {
954     UErrorCode status = U_ZERO_ERROR;
955     SimpleDateFormat* formatter = new SimpleDateFormat((UnicodeString)"MM/dd/yyyy 'at' hh:mm:ss a zzz", status);
956     if (U_FAILURE(status)) {
957         dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
958         delete formatter;
959         return;
960     }
961     UDate currentTime_1 = date(97, UCAL_AUGUST, 13, 10, 42, 28);
962     UnicodeString dateString; ((DateFormat*)formatter)->format(currentTime_1, dateString);
963     UnicodeString exp("08/13/1997 at 10:42:28 AM ");
964     logln((UnicodeString)"format(" + dateToString(currentTime_1) + ") = " + dateString);
965     if (0 != dateString.compareBetween(0, exp.length(), exp, 0, exp.length())) errln((UnicodeString)"FAIL: Expected " + exp);
966     delete formatter;
967     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
968 }
969
970 // -------------------------------------
971
972 /**
973  * Verify the correct behavior when handling invalid input strings.
974  */
975 void
976 DateFormatTest::TestBadInput135()
977 {
978     UErrorCode status = U_ZERO_ERROR;
979     DateFormat::EStyle looks[] = {
980         DateFormat::SHORT, DateFormat::MEDIUM, DateFormat::LONG, DateFormat::FULL
981     };
982     int32_t looks_length = UPRV_LENGTHOF(looks);
983     const char* strings[] = {
984         "Mar 15", "Mar 15 1997", "asdf", "3/1/97 1:23:", "3/1/00 1:23:45 AM"
985     };
986     int32_t strings_length = UPRV_LENGTHOF(strings);
987     DateFormat *full = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::LONG);
988     if(full==NULL) {
989       dataerrln("could not create date time instance");
990       return;
991     }
992     UnicodeString expected("March 1, 2000 at 1:23:45 AM ");
993     for (int32_t i = 0; i < strings_length;++i) {
994         const char* text = strings[i];
995         for (int32_t j = 0; j < looks_length;++j) {
996             DateFormat::EStyle dateLook = looks[j];
997             for (int32_t k = 0; k < looks_length;++k) {
998                 DateFormat::EStyle timeLook = looks[k];
999                 DateFormat *df = DateFormat::createDateTimeInstance(dateLook, timeLook);
1000                 if (df == NULL){
1001                     dataerrln("Error calling DateFormat::createDateTimeInstance()");
1002                     continue;
1003                 }
1004                 UnicodeString prefix = UnicodeString(text) + ", " + dateLook + "/" + timeLook + ": ";
1005                 //try {
1006                     UDate when = df->parse(text, status);
1007                     if (when == 0 && U_SUCCESS(status)) {
1008                         errln(prefix + "SHOULD NOT HAPPEN: parse returned 0.");
1009                         continue;
1010                     }
1011                     if (U_SUCCESS(status))
1012                     {
1013                         UnicodeString format;
1014                         UnicodeString pattern;
1015                         SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
1016                         if (sdtfmt != NULL) {
1017                             sdtfmt->toPattern(pattern);
1018                         }
1019                         full->format(when, format);
1020                         logln(prefix + "OK: " + format);
1021                         if (0!=format.compareBetween(0, expected.length(), expected, 0, expected.length()))
1022                             errln((UnicodeString)"FAIL: Parse \"" + text + "\", pattern \"" + pattern + "\", expected " + expected + " got " + format);
1023                     }
1024                 //}
1025                 //catch(ParseException e) {
1026                     else
1027                         status = U_ZERO_ERROR;
1028                 //}
1029                 //catch(StringIndexOutOfBoundsException e) {
1030                 //    errln(prefix + "SHOULD NOT HAPPEN: " + (int)status);
1031                 //}
1032                 delete df;
1033             }
1034         }
1035     }
1036     delete full;
1037     if (U_FAILURE(status))
1038         errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1039 }
1040
1041 static const char* const parseFormats[] = {
1042     "MMMM d, yyyy",
1043     "MMMM d yyyy",
1044     "M/d/yy",
1045     "d MMMM, yyyy",
1046     "d MMMM yyyy",
1047     "d MMMM",
1048     "MMMM d",
1049     "yyyy",
1050     "h:mm a MMMM d, yyyy"
1051 };
1052
1053 #if 0
1054 // strict inputStrings
1055 static const char* const inputStrings[] = {
1056     "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1057     "April 1, 1997", "April 1, 1997", 0, 0, 0, 0, 0, "April 1", 0, 0,
1058     "Jan 1, 1970", "January 1, 1970", 0, 0, 0, 0, 0, "January 1", 0, 0,
1059     "Jan 1 2037", 0, "January 1 2037", 0, 0, 0, 0, "January 1", 0, 0,
1060     "1/1/70", 0, 0, "1/1/70", 0, 0, 0, 0, "0001", 0,
1061     "5 May 1997", 0, 0, 0, 0, "5 May 1997", "5 May", 0, "0005", 0,
1062     "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1063     "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1064     "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1065     "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1066     "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1067 };
1068 #else
1069 // lenient inputStrings
1070 static const char* const inputStrings[] = {
1071     "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1072     "April 1, 1997", "April 1, 1997", "April 1 1997", "4/1/97", 0, 0, 0, "April 1", 0, 0,
1073     "Jan 1, 1970", "January 1, 1970", "January 1 1970", "1/1/70", 0, 0, 0, "January 1", 0, 0,
1074     "Jan 1 2037", "January 1, 2037", "January 1 2037", "1/1/37", 0, 0, 0, "January 1", 0, 0,
1075     "1/1/70", "January 1, 0070", "January 1 0070", "1/1/70", "1 January, 0070", "1 January 0070", "1 January", "January 1", "0001", 0,
1076     "5 May 1997", 0, 0, 0, "5 May, 1997", "5 May 1997", "5 May", 0, "0005", 0,
1077     "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1078     "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1079     "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1080     "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1081     "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1082 };
1083 #endif
1084
1085 // -------------------------------------
1086
1087 /**
1088  * Verify the correct behavior when parsing an array of inputs against an
1089  * array of patterns, with known results.  The results are encoded after
1090  * the input strings in each row.
1091  */
1092 void
1093 DateFormatTest::TestBadInput135a()
1094 {
1095   UErrorCode status = U_ZERO_ERROR;
1096   SimpleDateFormat* dateParse = new SimpleDateFormat(status);
1097   if(U_FAILURE(status)) {
1098     dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1099     delete dateParse;
1100     return;
1101   }
1102   const char* s;
1103   UDate date;
1104   const uint32_t PF_LENGTH = UPRV_LENGTHOF(parseFormats);
1105   const uint32_t INPUT_LENGTH = UPRV_LENGTHOF(inputStrings);
1106
1107   dateParse->applyPattern("d MMMM, yyyy");
1108   dateParse->adoptTimeZone(TimeZone::createDefault());
1109   s = "not parseable";
1110   UnicodeString thePat;
1111   logln(UnicodeString("Trying to parse \"") + s + "\" with " + dateParse->toPattern(thePat));
1112   //try {
1113   date = dateParse->parse(s, status);
1114   if (U_SUCCESS(status))
1115     errln((UnicodeString)"FAIL: Expected exception during parse");
1116   //}
1117   //catch(Exception ex) {
1118   else
1119     logln((UnicodeString)"Exception during parse: " + (int32_t)status);
1120   status = U_ZERO_ERROR;
1121   //}
1122   for (uint32_t i = 0; i < INPUT_LENGTH; i += (PF_LENGTH + 1)) {
1123     ParsePosition parsePosition(0);
1124     UnicodeString s( inputStrings[i]);
1125     for (uint32_t index = 0; index < PF_LENGTH;++index) {
1126       const char* expected = inputStrings[i + 1 + index];
1127       dateParse->applyPattern(parseFormats[index]);
1128       dateParse->adoptTimeZone(TimeZone::createDefault());
1129       //try {
1130       parsePosition.setIndex(0);
1131       date = dateParse->parse(s, parsePosition);
1132       if (parsePosition.getIndex() != 0) {
1133         UnicodeString s1, s2;
1134         s.extract(0, parsePosition.getIndex(), s1);
1135         s.extract(parsePosition.getIndex(), s.length(), s2);
1136         if (date == 0) {
1137           errln((UnicodeString)"ERROR: null result fmt=\"" +
1138                      parseFormats[index] +
1139                      "\" pos=" + parsePosition.getIndex() + " " +
1140                      s1 + "|" + s2);
1141         }
1142         else {
1143           UnicodeString result;
1144           ((DateFormat*)dateParse)->format(date, result);
1145           logln((UnicodeString)"Parsed \"" + s + "\" using \"" + dateParse->toPattern(thePat) + "\" to: " + result);
1146           if (expected == 0)
1147             errln((UnicodeString)"FAIL: Expected parse failure, got " + result);
1148           else if (!(result == expected))
1149             errln(UnicodeString("FAIL: Parse \"") + s + UnicodeString("\", expected ") + expected + UnicodeString(", got ") + result);
1150         }
1151       }
1152       else if (expected != 0) {
1153         errln(UnicodeString("FAIL: Expected ") + expected + " from \"" +
1154                      s + "\" with \"" + dateParse->toPattern(thePat) + "\"");
1155       }
1156       //}
1157       //catch(Exception ex) {
1158       if (U_FAILURE(status))
1159         errln((UnicodeString)"An exception was thrown during parse: " + (int32_t)status);
1160       //}
1161     }
1162   }
1163   delete dateParse;
1164   if (U_FAILURE(status))
1165     errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1166 }
1167
1168 // -------------------------------------
1169
1170 /**
1171  * Test the parsing of two-digit years.
1172  */
1173 void
1174 DateFormatTest::TestTwoDigitYear()
1175 {
1176     UErrorCode ec = U_ZERO_ERROR;
1177     SimpleDateFormat fmt("dd/MM/yy", Locale::getUK(), ec);
1178     if (U_FAILURE(ec)) {
1179         dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1180         return;
1181     }
1182     parse2DigitYear(fmt, "5/6/30", date(130, UCAL_JUNE, 5));
1183     parse2DigitYear(fmt, "4/6/50", date(50, UCAL_JUNE, 4));
1184 }
1185
1186 // -------------------------------------
1187
1188 void
1189 DateFormatTest::parse2DigitYear(DateFormat& fmt, const char* str, UDate expected)
1190 {
1191     UErrorCode status = U_ZERO_ERROR;
1192     //try {
1193         UDate d = fmt.parse(str, status);
1194         UnicodeString thePat;
1195         logln(UnicodeString("Parsing \"") + str + "\" with " + ((SimpleDateFormat*)&fmt)->toPattern(thePat) +
1196             "  => " + dateToString(d));
1197         if (d != expected) errln((UnicodeString)"FAIL: Expected " + expected);
1198     //}
1199     //catch(ParseException e) {
1200         if (U_FAILURE(status))
1201         errln((UnicodeString)"FAIL: Got exception");
1202     //}
1203 }
1204
1205 // -------------------------------------
1206
1207 /**
1208  * Test the formatting of time zones.
1209  */
1210 void
1211 DateFormatTest::TestDateFormatZone061()
1212 {
1213     UErrorCode status = U_ZERO_ERROR;
1214     UDate date;
1215     DateFormat *formatter;
1216     date= 859248000000.0;
1217     logln((UnicodeString)"Date 1997/3/25 00:00 GMT: " + date);
1218     formatter = new SimpleDateFormat((UnicodeString)"dd-MMM-yyyyy HH:mm", Locale::getUK(), status);
1219     if(U_FAILURE(status)) {
1220       dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1221       delete formatter;
1222       return;
1223     }
1224     formatter->adoptTimeZone(TimeZone::createTimeZone("GMT"));
1225     UnicodeString temp; formatter->format(date, temp);
1226     logln((UnicodeString)"Formatted in GMT to: " + temp);
1227     //try {
1228         UDate tempDate = formatter->parse(temp, status);
1229         logln((UnicodeString)"Parsed to: " + dateToString(tempDate));
1230         if (tempDate != date) errln((UnicodeString)"FAIL: Expected " + dateToString(date));
1231     //}
1232     //catch(Throwable t) {
1233     if (U_FAILURE(status))
1234         errln((UnicodeString)"Date Formatter throws: " + (int32_t)status);
1235     //}
1236     delete formatter;
1237 }
1238
1239 // -------------------------------------
1240
1241 /**
1242  * Test the formatting of time zones.
1243  */
1244 void
1245 DateFormatTest::TestDateFormatZone146()
1246 {
1247     TimeZone *saveDefault = TimeZone::createDefault();
1248
1249         //try {
1250     TimeZone *thedefault = TimeZone::createTimeZone("GMT");
1251     TimeZone::setDefault(*thedefault);
1252             // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
1253
1254             // check to be sure... its GMT all right
1255         TimeZone *testdefault = TimeZone::createDefault();
1256         UnicodeString testtimezone;
1257         testdefault->getID(testtimezone);
1258         if (testtimezone == "GMT")
1259             logln("Test timezone = " + testtimezone);
1260         else
1261             dataerrln("Test timezone should be GMT, not " + testtimezone);
1262
1263         UErrorCode status = U_ZERO_ERROR;
1264         // now try to use the default GMT time zone
1265         GregorianCalendar *greenwichcalendar =
1266             new GregorianCalendar(1997, 3, 4, 23, 0, status);
1267         if (U_FAILURE(status)) {
1268             dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
1269         } else {
1270             //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
1271             //greenwichcalendar.set(1997, 3, 4, 23, 0);
1272             // try anything to set hour to 23:00 !!!
1273             greenwichcalendar->set(UCAL_HOUR_OF_DAY, 23);
1274             // get time
1275             UDate greenwichdate = greenwichcalendar->getTime(status);
1276             // format every way
1277             UnicodeString DATA [] = {
1278                 UnicodeString("simple format:  "), UnicodeString("04/04/97 23:00 GMT"),
1279                     UnicodeString("MM/dd/yy HH:mm z"),
1280                 UnicodeString("full format:    "), UnicodeString("Friday, April 4, 1997 11:00:00 o'clock PM GMT"),
1281                     UnicodeString("EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z"),
1282                 UnicodeString("long format:    "), UnicodeString("April 4, 1997 11:00:00 PM GMT"),
1283                     UnicodeString("MMMM d, yyyy h:mm:ss a z"),
1284                 UnicodeString("default format: "), UnicodeString("04-Apr-97 11:00:00 PM"),
1285                     UnicodeString("dd-MMM-yy h:mm:ss a"),
1286                 UnicodeString("short format:   "), UnicodeString("4/4/97 11:00 PM"),
1287                     UnicodeString("M/d/yy h:mm a")
1288             };
1289             int32_t DATA_length = UPRV_LENGTHOF(DATA);
1290
1291             for (int32_t i=0; i<DATA_length; i+=3) {
1292                 DateFormat *fmt = new SimpleDateFormat(DATA[i+2], Locale::getEnglish(), status);
1293                 if (U_FAILURE(status)) {
1294                     dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
1295                     break;
1296                 }
1297                 fmt->setCalendar(*greenwichcalendar);
1298                 UnicodeString result;
1299                 result = fmt->format(greenwichdate, result);
1300                 logln(DATA[i] + result);
1301                 if (result != DATA[i+1])
1302                     errln("FAIL: Expected " + DATA[i+1] + ", got " + result);
1303                 delete fmt;
1304             }
1305         }
1306     //}
1307     //finally {
1308         TimeZone::adoptDefault(saveDefault);
1309     //}
1310         delete testdefault;
1311         delete greenwichcalendar;
1312         delete thedefault;
1313
1314
1315 }
1316
1317 // -------------------------------------
1318
1319 /**
1320  * Test the formatting of dates in different locales.
1321  */
1322 void
1323 DateFormatTest::TestLocaleDateFormat() // Bug 495
1324 {
1325     UDate testDate = date(97, UCAL_SEPTEMBER, 15);
1326     DateFormat *dfFrench = DateFormat::createDateTimeInstance(DateFormat::FULL,
1327         DateFormat::FULL, Locale::getFrench());
1328     DateFormat *dfUS = DateFormat::createDateTimeInstance(DateFormat::FULL,
1329         DateFormat::FULL, Locale::getUS());
1330     UnicodeString expectedFRENCH ( "lundi 15 septembre 1997 \\u00E0 00:00:00 heure d\\u2019\\u00E9t\\u00E9 du Pacifique", -1, US_INV );
1331     expectedFRENCH = expectedFRENCH.unescape();
1332     UnicodeString expectedUS ( "Monday, September 15, 1997 at 12:00:00 AM Pacific Daylight Time" );
1333     logln((UnicodeString)"Date set to : " + dateToString(testDate));
1334     UnicodeString out;
1335     if (dfUS == NULL || dfFrench == NULL){
1336         dataerrln("Error calling DateFormat::createDateTimeInstance)");
1337         delete dfUS;
1338         delete dfFrench;
1339         return;
1340     }
1341
1342     dfFrench->format(testDate, out);
1343     logln((UnicodeString)"Date Formated with French Locale " + out);
1344     if (!(out == expectedFRENCH))
1345         errln((UnicodeString)"FAIL: Expected " + expectedFRENCH);
1346     out.truncate(0);
1347     dfUS->format(testDate, out);
1348     logln((UnicodeString)"Date Formated with US Locale " + out);
1349     if (!(out == expectedUS))
1350         errln((UnicodeString)"FAIL: Expected " + expectedUS);
1351     delete dfUS;
1352     delete dfFrench;
1353 }
1354
1355 void
1356 DateFormatTest::TestFormattingLocaleTimeSeparator()
1357 {
1358     // This test not as useful is it once was, since timeSeparator
1359     // in the Arabic is changed back to ":" in CLDR 28.
1360     const UDate testDate = 874266720000.;  // Sun Sep 14 21:52:00 CET 1997
1361     logln((UnicodeString)"Date set to : " + dateToString(testDate));
1362
1363     const LocalPointer<const TimeZone> tz(TimeZone::createTimeZone("CET"));
1364
1365     const LocalPointer<DateFormat> dfArab(DateFormat::createTimeInstance(
1366             DateFormat::SHORT, Locale("ar")));
1367
1368     const LocalPointer<DateFormat> dfLatn(DateFormat::createTimeInstance(
1369             DateFormat::SHORT, Locale("ar", NULL, NULL, "numbers=latn")));
1370
1371     if (dfLatn.isNull() || dfArab.isNull()) {
1372         dataerrln("Error calling DateFormat::createTimeInstance()");
1373         return;
1374     }
1375
1376     dfArab->setTimeZone(*tz);
1377     dfLatn->setTimeZone(*tz);
1378
1379     const UnicodeString expectedArab = UnicodeString(
1380             "\\u0669:\\u0665\\u0662 \\u0645", -1, US_INV).unescape();
1381
1382     const UnicodeString expectedLatn = UnicodeString(
1383             "9:52 \\u0645", -1, US_INV).unescape();
1384
1385     UnicodeString actualArab;
1386     UnicodeString actualLatn;
1387
1388     dfArab->format(testDate, actualArab);
1389     dfLatn->format(testDate, actualLatn);
1390
1391     assertEquals("Arab", expectedArab, actualArab);
1392     assertEquals("Latn", expectedLatn, actualLatn);
1393 }
1394
1395 /**
1396  * Test DateFormat(Calendar) API
1397  */
1398 void DateFormatTest::TestDateFormatCalendar() {
1399     DateFormat *date=0, *time=0, *full=0;
1400     Calendar *cal=0;
1401     UnicodeString str;
1402     ParsePosition pos;
1403     UDate when;
1404     UErrorCode ec = U_ZERO_ERROR;
1405
1406     /* Create a formatter for date fields. */
1407     date = DateFormat::createDateInstance(DateFormat::kShort, Locale::getUS());
1408     if (date == NULL) {
1409         dataerrln("FAIL: createDateInstance failed");
1410         goto FAIL;
1411     }
1412
1413     /* Create a formatter for time fields. */
1414     time = DateFormat::createTimeInstance(DateFormat::kShort, Locale::getUS());
1415     if (time == NULL) {
1416         errln("FAIL: createTimeInstance failed");
1417         goto FAIL;
1418     }
1419
1420     /* Create a full format for output */
1421     full = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull,
1422                                               Locale::getUS());
1423     if (full == NULL) {
1424         errln("FAIL: createInstance failed");
1425         goto FAIL;
1426     }
1427
1428     /* Create a calendar */
1429     cal = Calendar::createInstance(Locale::getUS(), ec);
1430     if (cal == NULL || U_FAILURE(ec)) {
1431         errln((UnicodeString)"FAIL: Calendar::createInstance failed with " +
1432               u_errorName(ec));
1433         goto FAIL;
1434     }
1435
1436     /* Parse the date */
1437     cal->clear();
1438     str = UnicodeString("4/5/2001", "");
1439     pos.setIndex(0);
1440     date->parse(str, *cal, pos);
1441     if (pos.getIndex() != str.length()) {
1442         errln((UnicodeString)"FAIL: DateFormat::parse(4/5/2001) failed at " +
1443               pos.getIndex());
1444         goto FAIL;
1445     }
1446
1447     /* Parse the time */
1448     str = UnicodeString("5:45 PM", "");
1449     pos.setIndex(0);
1450     time->parse(str, *cal, pos);
1451     if (pos.getIndex() != str.length()) {
1452         errln((UnicodeString)"FAIL: DateFormat::parse(17:45) failed at " +
1453               pos.getIndex());
1454         goto FAIL;
1455     }
1456
1457     /* Check result */
1458     when = cal->getTime(ec);
1459     if (U_FAILURE(ec)) {
1460         errln((UnicodeString)"FAIL: cal->getTime() failed with " + u_errorName(ec));
1461         goto FAIL;
1462     }
1463     str.truncate(0);
1464     full->format(when, str);
1465     // Thursday, April 5, 2001 5:45:00 PM PDT 986517900000
1466     if (when == 986517900000.0) {
1467         logln("Ok: Parsed result: " + str);
1468     } else {
1469         errln("FAIL: Parsed result: " + str + ", exp 4/5/2001 5:45 PM");
1470     }
1471
1472  FAIL:
1473     delete date;
1474     delete time;
1475     delete full;
1476     delete cal;
1477 }
1478
1479 /**
1480  * Test DateFormat's parsing of space characters.  See jitterbug 1916.
1481  */
1482 void DateFormatTest::TestSpaceParsing() {
1483     const char* DATA[] = {
1484         "yyyy MM dd HH:mm:ss",
1485
1486         // pattern, input, expected parse or NULL if expect parse failure
1487         "MMMM d yy", " 04 05 06",  "2006 04 05 00:00:00",
1488         NULL,        "04 05 06",   "2006 04 05 00:00:00",
1489
1490         "MM d yy",   " 04 05 06",    "2006 04 05 00:00:00",
1491         NULL,        "04 05 06",     "2006 04 05 00:00:00",
1492         NULL,        "04/05/06",     "2006 04 05 00:00:00",
1493         NULL,        "04-05-06",     "2006 04 05 00:00:00",
1494         NULL,        "04.05.06",     "2006 04 05 00:00:00",
1495         NULL,        "04 / 05 / 06", "2006 04 05 00:00:00",
1496         NULL,        "Apr / 05/ 06", "2006 04 05 00:00:00",
1497         NULL,        "Apr-05-06",    "2006 04 05 00:00:00",
1498         NULL,        "Apr 05, 2006", "2006 04 05 00:00:00",
1499
1500         "MMMM d yy", " Apr 05 06", "2006 04 05 00:00:00",
1501         NULL,        "Apr 05 06",  "2006 04 05 00:00:00",
1502         NULL,        "Apr05 06",   "2006 04 05 00:00:00",
1503
1504         "hh:mm:ss a", "12:34:56 PM", "1970 01 01 12:34:56",
1505         NULL,         "12:34:56PM",  "1970 01 01 12:34:56",
1506         NULL,         "12.34.56PM",  "1970 01 01 12:34:56",
1507         NULL,         "12 : 34 : 56  PM", "1970 01 01 12:34:56",
1508
1509         "MM d yy 'at' hh:mm:ss a", "04/05/06 12:34:56 PM", "2006 04 05 12:34:56",
1510
1511         "MMMM dd yyyy hh:mm a", "September 27, 1964 21:56 PM", "1964 09 28 09:56:00",
1512         NULL,                   "November 4, 2008 0:13 AM",    "2008 11 04 00:13:00",
1513
1514         "HH'h'mm'min'ss's'", "12h34min56s", "1970 01 01 12:34:56",
1515         NULL,                "12h34mi56s",  "1970 01 01 12:34:56",
1516         NULL,                "12h34m56s",   "1970 01 01 12:34:56",
1517         NULL,                "12:34:56",    "1970 01 01 12:34:56"
1518     };
1519     const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1520
1521     expectParse(DATA, DATA_len, Locale("en"));
1522 }
1523
1524 /**
1525  * Test handling of "HHmmss" pattern.
1526  */
1527 void DateFormatTest::TestExactCountFormat() {
1528     const char* DATA[] = {
1529         "yyyy MM dd HH:mm:ss",
1530
1531         // pattern, input, expected parse or NULL if expect parse failure
1532         "HHmmss", "123456", "1970 01 01 12:34:56",
1533         NULL,     "12345",  "1970 01 01 01:23:45",
1534         NULL,     "1234",   NULL,
1535         NULL,     "00-05",  NULL,
1536         NULL,     "12-34",  NULL,
1537         NULL,     "00+05",  NULL,
1538         "ahhmm",  "PM730",  "1970 01 01 19:30:00",
1539     };
1540     const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1541
1542     expectParse(DATA, DATA_len, Locale("en"));
1543 }
1544
1545 /**
1546  * Test handling of white space.
1547  */
1548 void DateFormatTest::TestWhiteSpaceParsing() {
1549     const char* DATA[] = {
1550         "yyyy MM dd",
1551
1552         // pattern, input, expected parse or null if expect parse failure
1553
1554         // Pattern space run should parse input text space run
1555         "MM   d yy",   " 04 01 03",    "2003 04 01",
1556         NULL,          " 04  01   03 ", "2003 04 01",
1557     };
1558     const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1559
1560     expectParse(DATA, DATA_len, Locale("en"));
1561 }
1562
1563
1564 void DateFormatTest::TestInvalidPattern() {
1565     UErrorCode ec = U_ZERO_ERROR;
1566     SimpleDateFormat f(UnicodeString("Yesterday"), ec);
1567     if (U_FAILURE(ec)) {
1568         dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1569         return;
1570     }
1571     UnicodeString out;
1572     FieldPosition pos;
1573     f.format((UDate)0, out, pos);
1574     logln(out);
1575     // The bug is that the call to format() will crash.  By not
1576     // crashing, the test passes.
1577 }
1578
1579 void DateFormatTest::TestGreekMay() {
1580     UErrorCode ec = U_ZERO_ERROR;
1581     UDate date = -9896080848000.0;
1582     SimpleDateFormat fmt("EEEE, dd MMMM yyyy h:mm:ss a", Locale("el", "", ""), ec);
1583     if (U_FAILURE(ec)) {
1584         dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1585         return;
1586     }
1587     UnicodeString str;
1588     fmt.format(date, str);
1589     ParsePosition pos(0);
1590     UDate d2 = fmt.parse(str, pos);
1591     if (date != d2) {
1592         errln("FAIL: unable to parse strings where case-folding changes length");
1593     }
1594 }
1595
1596 void DateFormatTest::TestStandAloneMonths()
1597 {
1598     const char *EN_DATA[] = {
1599         "yyyy MM dd HH:mm:ss",
1600
1601         "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",
1602         "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",
1603         "yyyy LLLL dd H:mm:ss", "F",  "2004 03 10 16:36:31", "2004 March 10 16:36:31",
1604         "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",
1605
1606         "LLLL", "fp", "1970 01 01 0:00:00", "January",   "1970 01 01 0:00:00",
1607         "LLLL", "fp", "1970 02 01 0:00:00", "February",  "1970 02 01 0:00:00",
1608         "LLLL", "fp", "1970 03 01 0:00:00", "March",     "1970 03 01 0:00:00",
1609         "LLLL", "fp", "1970 04 01 0:00:00", "April",     "1970 04 01 0:00:00",
1610         "LLLL", "fp", "1970 05 01 0:00:00", "May",       "1970 05 01 0:00:00",
1611         "LLLL", "fp", "1970 06 01 0:00:00", "June",      "1970 06 01 0:00:00",
1612         "LLLL", "fp", "1970 07 01 0:00:00", "July",      "1970 07 01 0:00:00",
1613         "LLLL", "fp", "1970 08 01 0:00:00", "August",    "1970 08 01 0:00:00",
1614         "LLLL", "fp", "1970 09 01 0:00:00", "September", "1970 09 01 0:00:00",
1615         "LLLL", "fp", "1970 10 01 0:00:00", "October",   "1970 10 01 0:00:00",
1616         "LLLL", "fp", "1970 11 01 0:00:00", "November",  "1970 11 01 0:00:00",
1617         "LLLL", "fp", "1970 12 01 0:00:00", "December",  "1970 12 01 0:00:00",
1618
1619         "LLL", "fp", "1970 01 01 0:00:00", "Jan", "1970 01 01 0:00:00",
1620         "LLL", "fp", "1970 02 01 0:00:00", "Feb", "1970 02 01 0:00:00",
1621         "LLL", "fp", "1970 03 01 0:00:00", "Mar", "1970 03 01 0:00:00",
1622         "LLL", "fp", "1970 04 01 0:00:00", "Apr", "1970 04 01 0:00:00",
1623         "LLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1624         "LLL", "fp", "1970 06 01 0:00:00", "Jun", "1970 06 01 0:00:00",
1625         "LLL", "fp", "1970 07 01 0:00:00", "Jul", "1970 07 01 0:00:00",
1626         "LLL", "fp", "1970 08 01 0:00:00", "Aug", "1970 08 01 0:00:00",
1627         "LLL", "fp", "1970 09 01 0:00:00", "Sep", "1970 09 01 0:00:00",
1628         "LLL", "fp", "1970 10 01 0:00:00", "Oct", "1970 10 01 0:00:00",
1629         "LLL", "fp", "1970 11 01 0:00:00", "Nov", "1970 11 01 0:00:00",
1630         "LLL", "fp", "1970 12 01 0:00:00", "Dec", "1970 12 01 0:00:00",
1631     };
1632
1633     const char *CS_DATA[] = {
1634         "yyyy MM dd HH:mm:ss",
1635
1636         "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",
1637         "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",
1638         "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",
1639         "yyyy LLLL dd H:mm:ss", "F",  "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1640         "yyyy MMMM dd H:mm:ss", "F",  "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1641         "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",
1642         "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",
1643
1644         "LLLL", "fp", "1970 01 01 0:00:00", "leden",               "1970 01 01 0:00:00",
1645         "LLLL", "fp", "1970 02 01 0:00:00", "\\u00FAnor",           "1970 02 01 0:00:00",
1646         "LLLL", "fp", "1970 03 01 0:00:00", "b\\u0159ezen",         "1970 03 01 0:00:00",
1647         "LLLL", "fp", "1970 04 01 0:00:00", "duben",               "1970 04 01 0:00:00",
1648         "LLLL", "fp", "1970 05 01 0:00:00", "kv\\u011Bten",         "1970 05 01 0:00:00",
1649         "LLLL", "fp", "1970 06 01 0:00:00", "\\u010Derven",         "1970 06 01 0:00:00",
1650         "LLLL", "fp", "1970 07 01 0:00:00", "\\u010Dervenec",       "1970 07 01 0:00:00",
1651         "LLLL", "fp", "1970 08 01 0:00:00", "srpen",               "1970 08 01 0:00:00",
1652         "LLLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159\\u00ED", "1970 09 01 0:00:00",
1653         "LLLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDjen",     "1970 10 01 0:00:00",
1654         "LLLL", "fp", "1970 11 01 0:00:00", "listopad",            "1970 11 01 0:00:00",
1655         "LLLL", "fp", "1970 12 01 0:00:00", "prosinec",            "1970 12 01 0:00:00",
1656
1657         "LLL", "fp", "1970 01 01 0:00:00", "led",  "1970 01 01 0:00:00",
1658         "LLL", "fp", "1970 02 01 0:00:00", "\\u00FAno",  "1970 02 01 0:00:00",
1659         "LLL", "fp", "1970 03 01 0:00:00", "b\\u0159e",  "1970 03 01 0:00:00",
1660         "LLL", "fp", "1970 04 01 0:00:00", "dub",  "1970 04 01 0:00:00",
1661         "LLL", "fp", "1970 05 01 0:00:00", "kv\\u011B",  "1970 05 01 0:00:00",
1662         "LLL", "fp", "1970 06 01 0:00:00", "\\u010Dvn",  "1970 06 01 0:00:00",
1663         "LLL", "fp", "1970 07 01 0:00:00", "\\u010Dvc",  "1970 07 01 0:00:00",
1664         "LLL", "fp", "1970 08 01 0:00:00", "srp",  "1970 08 01 0:00:00",
1665         "LLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159",  "1970 09 01 0:00:00",
1666         "LLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDj", "1970 10 01 0:00:00",
1667         "LLL", "fp", "1970 11 01 0:00:00", "lis", "1970 11 01 0:00:00",
1668         "LLL", "fp", "1970 12 01 0:00:00", "pro", "1970 12 01 0:00:00",
1669     };
1670
1671     expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1672     expect(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1673 }
1674
1675 void DateFormatTest::TestStandAloneDays()
1676 {
1677     const char *EN_DATA[] = {
1678         "yyyy MM dd HH:mm:ss",
1679
1680         "cccc", "fp", "1970 01 04 0:00:00", "Sunday",    "1970 01 04 0:00:00",
1681         "cccc", "fp", "1970 01 05 0:00:00", "Monday",    "1970 01 05 0:00:00",
1682         "cccc", "fp", "1970 01 06 0:00:00", "Tuesday",   "1970 01 06 0:00:00",
1683         "cccc", "fp", "1970 01 07 0:00:00", "Wednesday", "1970 01 07 0:00:00",
1684         "cccc", "fp", "1970 01 01 0:00:00", "Thursday",  "1970 01 01 0:00:00",
1685         "cccc", "fp", "1970 01 02 0:00:00", "Friday",    "1970 01 02 0:00:00",
1686         "cccc", "fp", "1970 01 03 0:00:00", "Saturday",  "1970 01 03 0:00:00",
1687
1688         "ccc", "fp", "1970 01 04 0:00:00", "Sun", "1970 01 04 0:00:00",
1689         "ccc", "fp", "1970 01 05 0:00:00", "Mon", "1970 01 05 0:00:00",
1690         "ccc", "fp", "1970 01 06 0:00:00", "Tue", "1970 01 06 0:00:00",
1691         "ccc", "fp", "1970 01 07 0:00:00", "Wed", "1970 01 07 0:00:00",
1692         "ccc", "fp", "1970 01 01 0:00:00", "Thu", "1970 01 01 0:00:00",
1693         "ccc", "fp", "1970 01 02 0:00:00", "Fri", "1970 01 02 0:00:00",
1694         "ccc", "fp", "1970 01 03 0:00:00", "Sat", "1970 01 03 0:00:00",
1695     };
1696
1697     const char *CS_DATA[] = {
1698         "yyyy MM dd HH:mm:ss",
1699
1700         "cccc", "fp", "1970 01 04 0:00:00", "ned\\u011Ble",       "1970 01 04 0:00:00",
1701         "cccc", "fp", "1970 01 05 0:00:00", "pond\\u011Bl\\u00ED", "1970 01 05 0:00:00",
1702         "cccc", "fp", "1970 01 06 0:00:00", "\\u00FAter\\u00FD",   "1970 01 06 0:00:00",
1703         "cccc", "fp", "1970 01 07 0:00:00", "st\\u0159eda",       "1970 01 07 0:00:00",
1704         "cccc", "fp", "1970 01 01 0:00:00", "\\u010Dtvrtek",      "1970 01 01 0:00:00",
1705         "cccc", "fp", "1970 01 02 0:00:00", "p\\u00E1tek",        "1970 01 02 0:00:00",
1706         "cccc", "fp", "1970 01 03 0:00:00", "sobota",            "1970 01 03 0:00:00",
1707
1708         "ccc", "fp", "1970 01 04 0:00:00", "ne",      "1970 01 04 0:00:00",
1709         "ccc", "fp", "1970 01 05 0:00:00", "po",      "1970 01 05 0:00:00",
1710         "ccc", "fp", "1970 01 06 0:00:00", "\\u00FAt", "1970 01 06 0:00:00",
1711         "ccc", "fp", "1970 01 07 0:00:00", "st",      "1970 01 07 0:00:00",
1712         "ccc", "fp", "1970 01 01 0:00:00", "\\u010Dt", "1970 01 01 0:00:00",
1713         "ccc", "fp", "1970 01 02 0:00:00", "p\\u00E1", "1970 01 02 0:00:00",
1714         "ccc", "fp", "1970 01 03 0:00:00", "so",      "1970 01 03 0:00:00",
1715     };
1716
1717     expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1718     expect(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1719 }
1720
1721 void DateFormatTest::TestShortDays()
1722 {
1723     const char *EN_DATA[] = {
1724         "yyyy MM dd HH:mm:ss",
1725
1726         "EEEEEE, MMM d y", "fp", "2013 01 13 0:00:00", "Su, Jan 13 2013", "2013 01 13 0:00:00",
1727         "EEEEEE, MMM d y", "fp", "2013 01 16 0:00:00", "We, Jan 16 2013", "2013 01 16 0:00:00",
1728         "EEEEEE d",        "fp", "1970 01 17 0:00:00", "Sa 17",           "1970 01 17 0:00:00",
1729         "cccccc d",        "fp", "1970 01 17 0:00:00", "Sa 17",           "1970 01 17 0:00:00",
1730         "cccccc",          "fp", "1970 01 03 0:00:00", "Sa",              "1970 01 03 0:00:00",
1731     };
1732     const char *SV_DATA[] = {
1733         "yyyy MM dd HH:mm:ss",
1734
1735         "EEEEEE d MMM y",  "fp", "2013 01 13 0:00:00", "s\\u00F6 13 jan. 2013", "2013 01 13 0:00:00",
1736         "EEEEEE d MMM y",  "fp", "2013 01 16 0:00:00", "on 16 jan. 2013",       "2013 01 16 0:00:00",
1737         "EEEEEE d",        "fp", "1970 01 17 0:00:00", "l\\u00F6 17",          "1970 01 17 0:00:00",
1738         "cccccc d",        "fp", "1970 01 17 0:00:00", "l\\u00F6 17",          "1970 01 17 0:00:00",
1739         "cccccc",          "fp", "1970 01 03 0:00:00", "l\\u00F6",             "1970 01 03 0:00:00",
1740     };
1741     expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1742     expect(SV_DATA, UPRV_LENGTHOF(SV_DATA), Locale("sv", "", ""));
1743 }
1744
1745 void DateFormatTest::TestNarrowNames()
1746 {
1747     const char *EN_DATA[] = {
1748             "yyyy MM dd HH:mm:ss",
1749
1750             "yyyy MMMMM dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1751             "yyyy LLLLL dd H:mm:ss",  "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1752
1753             "MMMMM", "1970 01 01 0:00:00", "J",
1754             "MMMMM", "1970 02 01 0:00:00", "F",
1755             "MMMMM", "1970 03 01 0:00:00", "M",
1756             "MMMMM", "1970 04 01 0:00:00", "A",
1757             "MMMMM", "1970 05 01 0:00:00", "M",
1758             "MMMMM", "1970 06 01 0:00:00", "J",
1759             "MMMMM", "1970 07 01 0:00:00", "J",
1760             "MMMMM", "1970 08 01 0:00:00", "A",
1761             "MMMMM", "1970 09 01 0:00:00", "S",
1762             "MMMMM", "1970 10 01 0:00:00", "O",
1763             "MMMMM", "1970 11 01 0:00:00", "N",
1764             "MMMMM", "1970 12 01 0:00:00", "D",
1765
1766             "LLLLL", "1970 01 01 0:00:00", "J",
1767             "LLLLL", "1970 02 01 0:00:00", "F",
1768             "LLLLL", "1970 03 01 0:00:00", "M",
1769             "LLLLL", "1970 04 01 0:00:00", "A",
1770             "LLLLL", "1970 05 01 0:00:00", "M",
1771             "LLLLL", "1970 06 01 0:00:00", "J",
1772             "LLLLL", "1970 07 01 0:00:00", "J",
1773             "LLLLL", "1970 08 01 0:00:00", "A",
1774             "LLLLL", "1970 09 01 0:00:00", "S",
1775             "LLLLL", "1970 10 01 0:00:00", "O",
1776             "LLLLL", "1970 11 01 0:00:00", "N",
1777             "LLLLL", "1970 12 01 0:00:00", "D",
1778
1779             "EEEEE", "1970 01 04 0:00:00", "S",
1780             "EEEEE", "1970 01 05 0:00:00", "M",
1781             "EEEEE", "1970 01 06 0:00:00", "T",
1782             "EEEEE", "1970 01 07 0:00:00", "W",
1783             "EEEEE", "1970 01 01 0:00:00", "T",
1784             "EEEEE", "1970 01 02 0:00:00", "F",
1785             "EEEEE", "1970 01 03 0:00:00", "S",
1786
1787             "ccccc", "1970 01 04 0:00:00", "S",
1788             "ccccc", "1970 01 05 0:00:00", "M",
1789             "ccccc", "1970 01 06 0:00:00", "T",
1790             "ccccc", "1970 01 07 0:00:00", "W",
1791             "ccccc", "1970 01 01 0:00:00", "T",
1792             "ccccc", "1970 01 02 0:00:00", "F",
1793             "ccccc", "1970 01 03 0:00:00", "S",
1794
1795             "h:mm a",     "2015 01 01 10:00:00", "10:00 AM",
1796             "h:mm a",     "2015 01 01 22:00:00", "10:00 PM",
1797             "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a",
1798             "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p",
1799         };
1800
1801         const char *CS_DATA[] = {
1802             "yyyy MM dd HH:mm:ss",
1803
1804             "yyyy LLLLL dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1805             "yyyy MMMMM dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1806
1807             "MMMMM", "1970 01 01 0:00:00", "1",
1808             "MMMMM", "1970 02 01 0:00:00", "2",
1809             "MMMMM", "1970 03 01 0:00:00", "3",
1810             "MMMMM", "1970 04 01 0:00:00", "4",
1811             "MMMMM", "1970 05 01 0:00:00", "5",
1812             "MMMMM", "1970 06 01 0:00:00", "6",
1813             "MMMMM", "1970 07 01 0:00:00", "7",
1814             "MMMMM", "1970 08 01 0:00:00", "8",
1815             "MMMMM", "1970 09 01 0:00:00", "9",
1816             "MMMMM", "1970 10 01 0:00:00", "10",
1817             "MMMMM", "1970 11 01 0:00:00", "11",
1818             "MMMMM", "1970 12 01 0:00:00", "12",
1819
1820             "LLLLL", "1970 01 01 0:00:00", "1",
1821             "LLLLL", "1970 02 01 0:00:00", "2",
1822             "LLLLL", "1970 03 01 0:00:00", "3",
1823             "LLLLL", "1970 04 01 0:00:00", "4",
1824             "LLLLL", "1970 05 01 0:00:00", "5",
1825             "LLLLL", "1970 06 01 0:00:00", "6",
1826             "LLLLL", "1970 07 01 0:00:00", "7",
1827             "LLLLL", "1970 08 01 0:00:00", "8",
1828             "LLLLL", "1970 09 01 0:00:00", "9",
1829             "LLLLL", "1970 10 01 0:00:00", "10",
1830             "LLLLL", "1970 11 01 0:00:00", "11",
1831             "LLLLL", "1970 12 01 0:00:00", "12",
1832
1833             "EEEEE", "1970 01 04 0:00:00", "N",
1834             "EEEEE", "1970 01 05 0:00:00", "P",
1835             "EEEEE", "1970 01 06 0:00:00", "\\u00DA",
1836             "EEEEE", "1970 01 07 0:00:00", "S",
1837             "EEEEE", "1970 01 01 0:00:00", "\\u010C",
1838             "EEEEE", "1970 01 02 0:00:00", "P",
1839             "EEEEE", "1970 01 03 0:00:00", "S",
1840
1841             "ccccc", "1970 01 04 0:00:00", "N",
1842             "ccccc", "1970 01 05 0:00:00", "P",
1843             "ccccc", "1970 01 06 0:00:00", "\\u00DA",
1844             "ccccc", "1970 01 07 0:00:00", "S",
1845             "ccccc", "1970 01 01 0:00:00", "\\u010C",
1846             "ccccc", "1970 01 02 0:00:00", "P",
1847             "ccccc", "1970 01 03 0:00:00", "S",
1848
1849             "h:mm a",     "2015 01 01 10:00:00", "10:00 dop.",
1850             "h:mm a",     "2015 01 01 22:00:00", "10:00 odp.",
1851             "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 dop.",
1852             "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 odp.",
1853         };
1854
1855         const char *CA_DATA[] = {
1856             "yyyy MM dd HH:mm:ss",
1857
1858             "h:mm a",     "2015 01 01 10:00:00", "10:00 a. m.",
1859             "h:mm a",     "2015 01 01 22:00:00", "10:00 p. m.",
1860             "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a. m.",
1861             "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p. m.",
1862         };
1863
1864       expectFormat(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1865       expectFormat(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1866       expectFormat(CA_DATA, UPRV_LENGTHOF(CA_DATA), Locale("ca", "", ""));
1867 }
1868
1869 void DateFormatTest::TestEras()
1870 {
1871     const char *EN_DATA[] = {
1872         "yyyy MM dd",
1873
1874         "MMMM dd yyyy G",    "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
1875         "MMMM dd yyyy GG",   "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
1876         "MMMM dd yyyy GGG",  "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
1877         "MMMM dd yyyy GGGG", "fp", "1951 07 17", "July 17 1951 Anno Domini", "1951 07 17",
1878
1879         "MMMM dd yyyy G",    "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
1880         "MMMM dd yyyy GG",   "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
1881         "MMMM dd yyyy GGG",  "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
1882         "MMMM dd yyyy GGGG", "fp", "-438 07 17", "July 17 0439 Before Christ", "-438 07 17",
1883     };
1884
1885     expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1886 }
1887
1888 void DateFormatTest::TestQuarters()
1889 {
1890     const char *EN_DATA[] = {
1891         "yyyy MM dd",
1892
1893         "Q",    "fp", "1970 01 01", "1",           "1970 01 01",
1894         "QQ",   "fp", "1970 04 01", "02",          "1970 04 01",
1895         "QQQ",  "fp", "1970 07 01", "Q3",          "1970 07 01",
1896         "QQQQ", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1897
1898         "q",    "fp", "1970 01 01", "1",           "1970 01 01",
1899         "qq",   "fp", "1970 04 01", "02",          "1970 04 01",
1900         "qqq",  "fp", "1970 07 01", "Q3",          "1970 07 01",
1901         "qqqq", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1902
1903         "Qyy",  "fp", "2015 04 01", "215",         "2015 04 01",
1904         "QQyy", "fp", "2015 07 01", "0315",        "2015 07 01",
1905     };
1906
1907     expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1908 }
1909
1910 /**
1911  * Test parsing.  Input is an array that starts with the following
1912  * header:
1913  *
1914  * [0]   = pattern string to parse [i+2] with
1915  *
1916  * followed by test cases, each of which is 3 array elements:
1917  *
1918  * [i]   = pattern, or NULL to reuse prior pattern
1919  * [i+1] = input string
1920  * [i+2] = expected parse result (parsed with pattern [0])
1921  *
1922  * If expect parse failure, then [i+2] should be NULL.
1923  */
1924 void DateFormatTest::expectParse(const char** data, int32_t data_length,
1925                                  const Locale& loc) {
1926     const UDate FAIL = (UDate) -1;
1927     const UnicodeString FAIL_STR("parse failure");
1928     int32_t i = 0;
1929
1930     UErrorCode ec = U_ZERO_ERROR;
1931     SimpleDateFormat fmt("", loc, ec);
1932     SimpleDateFormat ref(data[i++], loc, ec);
1933     SimpleDateFormat gotfmt("G yyyy MM dd HH:mm:ss z", loc, ec);
1934     if (U_FAILURE(ec)) {
1935         dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1936         return;
1937     }
1938
1939     const char* currentPat = NULL;
1940     while (i<data_length) {
1941         const char* pattern  = data[i++];
1942         const char* input    = data[i++];
1943         const char* expected = data[i++];
1944
1945         ec = U_ZERO_ERROR;
1946         if (pattern != NULL) {
1947             fmt.applyPattern(pattern);
1948             currentPat = pattern;
1949         }
1950         UDate got = fmt.parse(input, ec);
1951         UnicodeString gotstr(FAIL_STR);
1952         if (U_FAILURE(ec)) {
1953             got = FAIL;
1954         } else {
1955             gotstr.remove();
1956             gotfmt.format(got, gotstr);
1957         }
1958
1959         UErrorCode ec2 = U_ZERO_ERROR;
1960         UDate exp = FAIL;
1961         UnicodeString expstr(FAIL_STR);
1962         if (expected != NULL) {
1963             expstr = expected;
1964             exp = ref.parse(expstr, ec2);
1965             if (U_FAILURE(ec2)) {
1966                 // This only happens if expected is in wrong format --
1967                 // should never happen once test is debugged.
1968                 errln("FAIL: Internal test error");
1969                 return;
1970             }
1971         }
1972
1973         if (got == exp) {
1974             logln((UnicodeString)"Ok: " + input + " x " +
1975                   currentPat + " => " + gotstr);
1976         } else {
1977             errln((UnicodeString)"FAIL: " + input + " x " +
1978                   currentPat + " => " + gotstr + ", expected " +
1979                   expstr);
1980         }
1981     }
1982 }
1983
1984 /**
1985  * Test formatting and parsing.  Input is an array that starts
1986  * with the following header:
1987  *
1988  * [0]   = pattern string to parse [i+2] with
1989  *
1990  * followed by test cases, each of which is 3 array elements:
1991  *
1992  * [i]   = pattern, or null to reuse prior pattern
1993  * [i+1] = control string, either "fp", "pf", or "F".
1994  * [i+2..] = data strings
1995  *
1996  * The number of data strings depends on the control string.
1997  * Examples:
1998  * 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",
1999  * 'f': Format date [i+2] (as parsed using pattern [0]) and expect string [i+3].
2000  * 'p': Parse string [i+3] and expect date [i+4].
2001  *
2002  * 2. "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567"
2003  * 'F': Format date [i+2] and expect string [i+3],
2004  *      then parse string [i+3] and expect date [i+2].
2005  *
2006  * 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",
2007  * 'p': Parse string [i+2] and expect date [i+3].
2008  * 'f': Format date [i+3] and expect string [i+4].
2009  */
2010 void DateFormatTest::expect(const char** data, int32_t data_length,
2011                             const Locale& loc) {
2012     int32_t i = 0;
2013     UErrorCode ec = U_ZERO_ERROR;
2014     UnicodeString str, str2;
2015     SimpleDateFormat fmt("", loc, ec);
2016     SimpleDateFormat ref(data[i++], loc, ec);
2017     SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2018     if (U_FAILURE(ec)) {
2019         dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2020         return;
2021     }
2022
2023     UnicodeString currentPat;
2024     while (i<data_length) {
2025         const char* pattern  = data[i++];
2026         if (pattern != NULL) {
2027             fmt.applyPattern(pattern);
2028             currentPat = pattern;
2029         }
2030
2031         const char* control = data[i++];
2032
2033         if (uprv_strcmp(control, "fp") == 0) {
2034             // 'f'
2035             const char* datestr = data[i++];
2036             const char* string = data[i++];
2037             UDate date = ref.parse(ctou(datestr), ec);
2038             if (!assertSuccess("parse", ec)) return;
2039             assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2040                          ctou(string),
2041                          fmt.format(date, str.remove()));
2042             // 'p'
2043             datestr = data[i++];
2044             date = ref.parse(ctou(datestr), ec);
2045             if (!assertSuccess("parse", ec)) return;
2046             UDate parsedate = fmt.parse(ctou(string), ec);
2047             if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2048                 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2049                              univ.format(date, str.remove()),
2050                              univ.format(parsedate, str2.remove()));
2051             }
2052         }
2053
2054         else if (uprv_strcmp(control, "pf") == 0) {
2055             // 'p'
2056             const char* string = data[i++];
2057             const char* datestr = data[i++];
2058             UDate date = ref.parse(ctou(datestr), ec);
2059             if (!assertSuccess("parse", ec)) return;
2060             UDate parsedate = fmt.parse(ctou(string), ec);
2061             if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2062                 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2063                              univ.format(date, str.remove()),
2064                              univ.format(parsedate, str2.remove()));
2065             }
2066             // 'f'
2067             string = data[i++];
2068             assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2069                          ctou(string),
2070                          fmt.format(date, str.remove()));
2071         }
2072
2073         else if (uprv_strcmp(control, "F") == 0) {
2074             const char* datestr  = data[i++];
2075             const char* string   = data[i++];
2076             UDate date = ref.parse(ctou(datestr), ec);
2077             if (!assertSuccess("parse", ec)) return;
2078             assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2079                          ctou(string),
2080                          fmt.format(date, str.remove()));
2081
2082             UDate parsedate = fmt.parse(string, ec);
2083             if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2084                 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2085                              univ.format(date, str.remove()),
2086                              univ.format(parsedate, str2.remove()));
2087             }
2088         }
2089
2090         else {
2091             errln((UnicodeString)"FAIL: Invalid control string " + control);
2092             return;
2093         }
2094     }
2095 }
2096
2097 /**
2098  * Test formatting.  Input is an array that starts
2099  * with the following header:
2100  *
2101  * [0]   = pattern string to parse [i+2] with
2102  *
2103  * followed by test cases, each of which is 3 array elements:
2104  *
2105  * [i]   = pattern, or null to reuse prior pattern
2106  * [i+1] = data string a
2107  * [i+2] = data string b
2108  *
2109  * Examples:
2110  * Format date [i+1] and expect string [i+2].
2111  *
2112  * "y/M/d H:mm:ss.SSSS", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567"
2113  */
2114 void DateFormatTest::expectFormat(const char** data, int32_t data_length,
2115                             const Locale& loc) {
2116     int32_t i = 0;
2117     UErrorCode ec = U_ZERO_ERROR;
2118     UnicodeString str, str2;
2119     SimpleDateFormat fmt("", loc, ec);
2120     SimpleDateFormat ref(data[i++], loc, ec);
2121     SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2122     if (U_FAILURE(ec)) {
2123         dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2124         return;
2125     }
2126
2127     UnicodeString currentPat;
2128
2129     while (i<data_length) {
2130         const char* pattern  = data[i++];
2131         if (pattern != NULL) {
2132             fmt.applyPattern(pattern);
2133             currentPat = pattern;
2134         }
2135
2136         const char* datestr = data[i++];
2137         const char* string = data[i++];
2138         UDate date = ref.parse(ctou(datestr), ec);
2139         if (!assertSuccess("parse", ec)) return;
2140         assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2141                         ctou(string),
2142                         fmt.format(date, str.remove()));
2143     }
2144 }
2145
2146 void DateFormatTest::TestGenericTime() {
2147   const Locale en("en");
2148   // Note: We no longer parse strings in different styles.
2149 /*
2150   const char* ZDATA[] = {
2151         "yyyy MM dd HH:mm zzz",
2152         // round trip
2153         "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2154         "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2155         "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2156         "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2157         // non-generic timezone string influences dst offset even if wrong for date/time
2158         "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",
2159         "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",
2160         "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",
2161         "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",
2162         // generic timezone generates dst offset appropriate for local time
2163         "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",
2164         "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",
2165         "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",
2166         "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",
2167         // daylight savings time transition edge cases.
2168         // time to parse does not really exist, PT interpreted as earlier time
2169         "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",
2170         "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",
2171         "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",
2172         "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",
2173         "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",
2174         "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",
2175         "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2176         // time to parse is ambiguous, PT interpreted as later time
2177         "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",
2178         "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",
2179         "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2180
2181         "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",
2182         "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",
2183         "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",
2184         "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",
2185         "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",
2186         "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",
2187         "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2188   };
2189 */
2190   const char* ZDATA[] = {
2191         "yyyy MM dd HH:mm zzz",
2192         // round trip
2193         "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2194         "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2195         "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2196         "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2197         // non-generic timezone string influences dst offset even if wrong for date/time
2198         "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",
2199         "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",
2200         // generic timezone generates dst offset appropriate for local time
2201         "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",
2202         "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",
2203         "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2204         "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 Pacific Time", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2205         // daylight savings time transition edge cases.
2206         // time to parse does not really exist, PT interpreted as earlier time
2207         "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",
2208         "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",
2209         "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",
2210         "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2211         // time to parse is ambiguous, PT interpreted as later time
2212         "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",
2213         "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2214
2215         "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",
2216         "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",
2217         "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",
2218         "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2219   };
2220
2221   const int32_t ZDATA_length = UPRV_LENGTHOF(ZDATA);
2222   expect(ZDATA, ZDATA_length, en);
2223
2224   UErrorCode status = U_ZERO_ERROR;
2225
2226   logln("cross format/parse tests");    // Note: We no longer support cross format/parse
2227   UnicodeString basepat("yy/MM/dd H:mm ");
2228   SimpleDateFormat formats[] = {
2229     SimpleDateFormat(basepat + "vvv", en, status),
2230     SimpleDateFormat(basepat + "vvvv", en, status),
2231     SimpleDateFormat(basepat + "zzz", en, status),
2232     SimpleDateFormat(basepat + "zzzz", en, status)
2233   };
2234   if (U_FAILURE(status)) {
2235     dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(status));
2236     return;
2237   }
2238   const int32_t formats_length = UPRV_LENGTHOF(formats);
2239
2240   UnicodeString test;
2241   SimpleDateFormat univ("yyyy MM dd HH:mm zzz", en, status);
2242   ASSERT_OK(status);
2243   const UnicodeString times[] = {
2244     "2004 01 02 03:04 PST",
2245     "2004 07 08 09:10 PDT"
2246   };
2247   int32_t times_length = UPRV_LENGTHOF(times);
2248   for (int i = 0; i < times_length; ++i) {
2249     UDate d = univ.parse(times[i], status);
2250     logln(UnicodeString("\ntime: ") + d);
2251     for (int j = 0; j < formats_length; ++j) {
2252       test.remove();
2253       formats[j].format(d, test);
2254       logln("\ntest: '" + test + "'");
2255       for (int k = 0; k < formats_length; ++k) {
2256         UDate t = formats[k].parse(test, status);
2257         if (U_SUCCESS(status)) {
2258           if (d != t) {
2259             errln((UnicodeString)"FAIL: format " + k +
2260                   " incorrectly parsed output of format " + j +
2261                   " (" + test + "), returned " +
2262                   dateToString(t) + " instead of " + dateToString(d));
2263           } else {
2264             logln((UnicodeString)"OK: format " + k + " parsed ok");
2265           }
2266         } else if (status == U_PARSE_ERROR) {
2267           errln((UnicodeString)"FAIL: format " + k +
2268                 " could not parse output of format " + j +
2269                 " (" + test + ")");
2270         }
2271       }
2272     }
2273   }
2274 }
2275
2276 void DateFormatTest::TestGenericTimeZoneOrder() {
2277   // generic times should parse the same no matter what the placement of the time zone string
2278
2279   // Note: We no longer support cross style format/parse
2280
2281   //const char* XDATA[] = {
2282   //  "yyyy MM dd HH:mm zzz",
2283   //  // standard time, explicit daylight/standard
2284   //  "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",
2285   //  "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",
2286   //  "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",
2287
2288   //  // standard time, generic
2289   //  "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",
2290   //  "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",
2291   //  "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",
2292
2293   //  // dahylight time, explicit daylight/standard
2294   //  "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",
2295   //  "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",
2296   //  "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",
2297
2298   //  // daylight time, generic
2299   //  "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",
2300   //  "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",
2301   //  "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",
2302   //};
2303   const char* XDATA[] = {
2304     "yyyy MM dd HH:mm zzz",
2305     // standard time, explicit daylight/standard
2306     "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",
2307     "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",
2308     "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",
2309
2310     // standard time, generic
2311     "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",
2312     "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",
2313     "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",
2314
2315     // dahylight time, explicit daylight/standard
2316     "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",
2317     "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",
2318     "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",
2319
2320     // daylight time, generic
2321     "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",
2322     "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",
2323     "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",
2324   };
2325   const int32_t XDATA_length = UPRV_LENGTHOF(XDATA);
2326   Locale en("en");
2327   expect(XDATA, XDATA_length, en);
2328 }
2329
2330 void DateFormatTest::TestZTimeZoneParsing(void) {
2331     UErrorCode status = U_ZERO_ERROR;
2332     const Locale en("en");
2333     UnicodeString test;
2334     //SimpleDateFormat univ("yyyy-MM-dd'T'HH:mm Z", en, status);
2335     SimpleDateFormat univ("HH:mm Z", en, status);
2336     if (failure(status, "construct SimpleDateFormat", TRUE)) return;
2337     const TimeZone *t = TimeZone::getGMT();
2338     univ.setTimeZone(*t);
2339
2340     univ.setLenient(false);
2341     ParsePosition pp(0);
2342     struct {
2343         UnicodeString input;
2344         UnicodeString expected_result;
2345     } tests[] = {
2346         { "11:00 -0200", "13:00 +0000" },
2347         { "11:00 +0200", "09:00 +0000" },
2348         { "11:00 +0400", "07:00 +0000" },
2349         { "11:00 +0530", "05:30 +0000" }
2350     };
2351
2352     UnicodeString result;
2353     int32_t tests_length = UPRV_LENGTHOF(tests);
2354     for (int i = 0; i < tests_length; ++i) {
2355         pp.setIndex(0);
2356         UDate d = univ.parse(tests[i].input, pp);
2357         if(pp.getIndex() != tests[i].input.length()){
2358             errln("Test %i: setZoneString() did not succeed. Consumed: %i instead of %i",
2359                   i, pp.getIndex(), tests[i].input.length());
2360             return;
2361         }
2362         result.remove();
2363         univ.format(d, result);
2364         if(result != tests[i].expected_result) {
2365             errln("Expected " + tests[i].expected_result
2366                   + " got " + result);
2367             return;
2368         }
2369         logln("SUCCESS: Parsed " + tests[i].input
2370               + " got " + result
2371               + " expected " + tests[i].expected_result);
2372     }
2373 }
2374
2375 void DateFormatTest::TestHost(void)
2376 {
2377 #if U_PLATFORM_HAS_WIN32_API
2378     Win32DateTimeTest::testLocales(this);
2379 #endif
2380 }
2381
2382 // Relative Date Tests
2383
2384 void DateFormatTest::TestRelative(int daysdelta,
2385                                   const Locale& loc,
2386                                   const char *expectChars) {
2387     char banner[25];
2388     sprintf(banner, "%d", daysdelta);
2389     UnicodeString bannerStr(banner, "");
2390
2391     UErrorCode status = U_ZERO_ERROR;
2392
2393     FieldPosition pos(FieldPosition::DONT_CARE);
2394     UnicodeString test;
2395     Locale en("en");
2396     DateFormat *fullrelative = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2397
2398     if (fullrelative == NULL) {
2399         dataerrln("DateFormat::createDateInstance(DateFormat::kFullRelative, %s) returned NULL", loc.getName());
2400         return;
2401     }
2402
2403     DateFormat *full         = DateFormat::createDateInstance(DateFormat::kFull        , loc);
2404
2405     if (full == NULL) {
2406         errln("DateFormat::createDateInstance(DateFormat::kFull, %s) returned NULL", loc.getName());
2407         return;
2408     }
2409
2410     DateFormat *en_full =         DateFormat::createDateInstance(DateFormat::kFull,         en);
2411
2412     if (en_full == NULL) {
2413         errln("DateFormat::createDateInstance(DateFormat::kFull, en) returned NULL");
2414         return;
2415     }
2416
2417     DateFormat *en_fulltime =         DateFormat::createDateTimeInstance(DateFormat::kFull,DateFormat::kFull,en);
2418
2419     if (en_fulltime == NULL) {
2420         errln("DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, en) returned NULL");
2421         return;
2422     }
2423
2424     UnicodeString result;
2425     UnicodeString normalResult;
2426     UnicodeString expect;
2427     UnicodeString parseResult;
2428
2429     Calendar *c = Calendar::createInstance(status);
2430
2431     // Today = Today
2432     c->setTime(Calendar::getNow(), status);
2433     if(daysdelta != 0) {
2434         c->add(Calendar::DATE,daysdelta,status);
2435     }
2436     ASSERT_OK(status);
2437
2438     // calculate the expected string
2439     if(expectChars != NULL) {
2440         expect = expectChars;
2441     } else {
2442         full->format(*c, expect, pos); // expected = normal full
2443     }
2444
2445     fullrelative   ->format(*c, result, pos);
2446     en_full        ->format(*c, normalResult, pos);
2447
2448     if(result != expect) {
2449         errln("FAIL: Relative Format ["+bannerStr+"] of "+normalResult+" failed, expected "+expect+" but got " + result);
2450     } else {
2451         logln("PASS: Relative Format ["+bannerStr+"] of "+normalResult+" got " + result);
2452     }
2453
2454
2455     //verify
2456     UDate d = fullrelative->parse(result, status);
2457     ASSERT_OK(status);
2458
2459     UnicodeString parseFormat; // parse rel->format full
2460     en_full->format(d, parseFormat, status);
2461
2462     UnicodeString origFormat;
2463     en_full->format(*c, origFormat, pos);
2464
2465     if(parseFormat!=origFormat) {
2466         errln("FAIL: Relative Parse ["+bannerStr+"] of "+result+" failed, expected "+parseFormat+" but got "+origFormat);
2467     } else {
2468         logln("PASS: Relative Parse ["+bannerStr+"] of "+result+" passed, got "+parseFormat);
2469     }
2470
2471     delete full;
2472     delete fullrelative;
2473     delete en_fulltime;
2474     delete en_full;
2475     delete c;
2476 }
2477
2478
2479 void DateFormatTest::TestRelative(void)
2480 {
2481     Locale en("en");
2482     TestRelative( 0, en, "today");
2483     TestRelative(-1, en, "yesterday");
2484     TestRelative( 1, en, "tomorrow");
2485     TestRelative( 2, en, NULL);
2486     TestRelative( -2, en, NULL);
2487     TestRelative( 3, en, NULL);
2488     TestRelative( -3, en, NULL);
2489     TestRelative( 300, en, NULL);
2490     TestRelative( -300, en, NULL);
2491 }
2492
2493 void DateFormatTest::TestRelativeClone(void)
2494 {
2495     /*
2496     Verify that a cloned formatter gives the same results
2497     and is useable after the original has been deleted.
2498     */
2499     UErrorCode status = U_ZERO_ERROR;
2500     Locale loc("en");
2501     UDate now = Calendar::getNow();
2502     DateFormat *full = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2503     if (full == NULL) {
2504         dataerrln("FAIL: Can't create Relative date instance");
2505         return;
2506     }
2507     UnicodeString result1;
2508     full->format(now, result1, status);
2509     Format *fullClone = full->clone();
2510     delete full;
2511     full = NULL;
2512
2513     UnicodeString result2;
2514     fullClone->format(now, result2, status);
2515     ASSERT_OK(status);
2516     if (result1 != result2) {
2517         errln("FAIL: Clone returned different result from non-clone.");
2518     }
2519     delete fullClone;
2520 }
2521
2522 void DateFormatTest::TestHostClone(void)
2523 {
2524     /*
2525     Verify that a cloned formatter gives the same results
2526     and is useable after the original has been deleted.
2527     */
2528     // This is mainly important on Windows.
2529     UErrorCode status = U_ZERO_ERROR;
2530     Locale loc("en_US@compat=host");
2531     UDate now = Calendar::getNow();
2532     DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull, loc);
2533     if (full == NULL) {
2534         dataerrln("FAIL: Can't create host date instance");
2535         return;
2536     }
2537     UnicodeString result1;
2538     full->format(now, result1, status);
2539     Format *fullClone = full->clone();
2540     delete full;
2541     full = NULL;
2542
2543     UnicodeString result2;
2544     fullClone->format(now, result2, status);
2545     ASSERT_OK(status);
2546     if (result1 != result2) {
2547         errln("FAIL: Clone returned different result from non-clone.");
2548     }
2549     delete fullClone;
2550 }
2551
2552 void DateFormatTest::TestHebrewClone(void)
2553 {
2554     /*
2555     Verify that a cloned formatter gives the same results
2556     and is useable after the original has been deleted.
2557     */
2558     UErrorCode status = U_ZERO_ERROR;
2559     Locale loc("he@calendar=hebrew");
2560     UDate now = Calendar::getNow();
2561     LocalPointer<DateFormat> fmt(
2562             DateFormat::createDateInstance(DateFormat::kLong, loc));
2563     if (fmt.isNull()) {
2564         dataerrln("FAIL: Can't create Hebrew date instance");
2565         return;
2566     }
2567     UnicodeString result1;
2568     fmt->format(now, result1, status);
2569     LocalPointer<Format> fmtClone(fmt->clone());
2570
2571     // free fmt to be sure that fmtClone is independent of fmt.
2572     fmt.adoptInstead(NULL);
2573
2574     UnicodeString result2;
2575     fmtClone->format(now, result2, status);
2576     ASSERT_OK(status);
2577     if (result1 != result2) {
2578         errln("FAIL: Clone returned different result from non-clone.");
2579     }
2580 }
2581
2582 static UBool getActualAndValidLocales(
2583         const Format &fmt, Locale &valid, Locale &actual) {
2584     const SimpleDateFormat* dat = dynamic_cast<const SimpleDateFormat*>(&fmt);
2585     if (dat == NULL) {
2586         return FALSE;
2587     }
2588     const DateFormatSymbols *sym = dat->getDateFormatSymbols();
2589     if (sym == NULL) {
2590         return FALSE;
2591     }
2592     UErrorCode status = U_ZERO_ERROR;
2593     valid = sym->getLocale(ULOC_VALID_LOCALE, status);
2594     actual = sym->getLocale(ULOC_ACTUAL_LOCALE, status);
2595     return U_SUCCESS(status);
2596 }
2597
2598 void DateFormatTest::TestDateFormatSymbolsClone(void)
2599 {
2600     /*
2601     Verify that a cloned formatter gives the same results
2602     and is useable after the original has been deleted.
2603     */
2604     Locale loc("de_CH_LUCERNE");
2605     LocalPointer<DateFormat> fmt(
2606             DateFormat::createDateInstance(DateFormat::kDefault, loc));
2607     Locale valid1;
2608     Locale actual1;
2609     if (!getActualAndValidLocales(*fmt, valid1, actual1)) {
2610         dataerrln("FAIL: Could not fetch valid + actual locales");
2611         return;
2612     }
2613     LocalPointer<Format> fmtClone(fmt->clone());
2614
2615     // Free fmt to be sure that fmtClone is really independent of fmt.
2616     fmt.adoptInstead(NULL);
2617     Locale valid2;
2618     Locale actual2;
2619     if (!getActualAndValidLocales(*fmtClone, valid2, actual2)) {
2620         errln("FAIL: Could not fetch valid + actual locales");
2621         return;
2622     }
2623     if (valid1 != valid2 || actual1 != actual2) {
2624         errln("Date format symbol locales of clone don't match original");
2625     }
2626 }
2627
2628 void DateFormatTest::TestTimeZoneDisplayName()
2629 {
2630     // This test data was ported from ICU4J.  Don't know why the 6th column in there because it's not being
2631     // used currently.
2632     const char *fallbackTests[][6]  = {
2633         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2634         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2635         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZZ", "-08:00", "-8:00" },
2636         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "PST", "America/Los_Angeles" },
2637         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Pacific Standard Time", "America/Los_Angeles" },
2638         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2639         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2640         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "PDT", "America/Los_Angeles" },
2641         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Pacific Daylight Time", "America/Los_Angeles" },
2642         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "PT", "America/Los_Angeles" },
2643         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Pacific Time", "America/Los_Angeles" },
2644         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "Los Angeles Time", "America/Los_Angeles" },
2645         { "en_GB", "America/Los_Angeles", "2004-01-15T12:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2646         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "Z", "-0700", "-7:00" },
2647         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2648         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2649         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2650         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2651         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2652         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2653         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2654         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "v", "MST", "America/Phoenix" },
2655         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "vvvv", "Mountain Standard Time", "America/Phoenix" },
2656         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "VVVV", "Phoenix Time", "America/Phoenix" },
2657
2658         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2659         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2660         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2661         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2662         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2663         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2664         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2665         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2666         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2667         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2668         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2669
2670         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2671         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2672         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2673         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2674         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2675         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2676         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2677         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2678         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2679         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2680         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2681
2682         { "en", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2683         { "en", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2684         { "en", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2685         { "en", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Cuba Standard Time", "-5:00" },
2686         { "en", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2687         { "en", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2688         { "en", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2689         { "en", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Cuba Daylight Time", "-4:00" },
2690         { "en", "America/Havana", "2004-07-15T00:00:00Z", "v", "Cuba Time", "America/Havana" },
2691         { "en", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Cuba Time", "America/Havana" },
2692         { "en", "America/Havana", "2004-07-15T00:00:00Z", "VVVV", "Cuba Time", "America/Havana" },
2693
2694         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2695         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2696         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2697         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2698         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2699         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2700         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2701         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2702         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2703         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2704         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2705
2706         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2707         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2708         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2709         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2710         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2711         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2712         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2713         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2714         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2715         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2716         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2717
2718         { "en", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2719         { "en", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2720         { "en", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2721         { "en", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Greenwich Mean Time", "+0:00" },
2722         { "en", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2723         { "en", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2724         { "en", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "Europe/London" },
2725         { "en", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "British Summer Time", "Europe/London" },
2726     // icu en.txt has exemplar city for this time zone
2727         { "en", "Europe/London", "2004-07-15T00:00:00Z", "v", "United Kingdom Time", "Europe/London" },
2728         { "en", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "United Kingdom Time", "Europe/London" },
2729         { "en", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "United Kingdom Time", "Europe/London" },
2730
2731         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2732         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2733         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2734         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2735         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2736         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2737         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2738         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2739         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2740         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2741
2742         // JB#5150
2743         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2744         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2745         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2746         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2747         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2748         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2749         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2750         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2751         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "India Time", "Asia/Calcutta" },
2752         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "India Standard Time", "Asia/Calcutta" },
2753
2754         // Proper CLDR primary zone support #9733
2755         { "en", "America/Santiago", "2013-01-01T00:00:00Z", "VVVV", "Chile Time", "America/Santiago" },
2756         { "en", "Pacific/Easter", "2013-01-01T00:00:00Z", "VVVV", "Easter Time", "Pacific/Easter" },
2757
2758         // ==========
2759
2760         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2761         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2762         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2763         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Normalzeit", "-8:00" },
2764         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2765         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2766         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2767         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Sommerzeit", "-7:00" },
2768         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles Zeit", "America/Los_Angeles" },
2769         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Nordamerikanische Westk\\u00fcstenzeit", "America/Los_Angeles" },
2770
2771         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2772         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2773         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2774         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2775         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2776         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2777         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2778         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2779         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2780         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2781
2782         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2783         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2784         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2785         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2786         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2787         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2788         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2789         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2790         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2791         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2792
2793         { "de", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2794         { "de", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2795         { "de", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2796         { "de", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Kubanische Normalzeit", "-5:00" },
2797         { "de", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2798         { "de", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2799         { "de", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2800         { "de", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Kubanische Sommerzeit", "-4:00" },
2801         { "de", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2802         { "de", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2803         // added to test proper fallback of country name
2804         { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2805         { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2806
2807         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2808         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2809         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2810         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2811         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2812         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2813         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2814         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2815         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2816         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2817
2818         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2819         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2820         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2821         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2822         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2823         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2824         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2825         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2826         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2827         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2828
2829         { "de", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2830         { "de", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2831         { "de", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2832         { "de", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Mittlere Greenwich-Zeit", "+0:00" },
2833         { "de", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2834         { "de", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2835         { "de", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2836         { "de", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "Britische Sommerzeit", "+1:00" },
2837         { "de", "Europe/London", "2004-07-15T00:00:00Z", "v", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2838         { "de", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2839
2840         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2841         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2842         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2843         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2844         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2845         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2846         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2847         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2848         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2849         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2850
2851         // JB#5150
2852         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2853         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2854         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2855         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2856         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2857         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2858         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2859         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2860         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "Indien Zeit", "Asia/Calcutta" },
2861         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "Indische Zeit", "Asia/Calcutta" },
2862
2863         // ==========
2864
2865         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2866         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2867         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2868         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u6807\\u51c6\\u65f6\\u95f4", "America/Los_Angeles" },
2869         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2870         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2871         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
2872         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u590f\\u4ee4\\u65f6\\u95f4", "America/Los_Angeles" },
2873     // icu zh.txt has exemplar city for this time zone
2874         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4", "America/Los_Angeles" },
2875         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u65f6\\u95f4", "America/Los_Angeles" },
2876
2877         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2878         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2879         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2880         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2881         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2882         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2883         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2884         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2885         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2886         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2887
2888         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2889         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2890         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2891         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2892         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2893         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2894         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2895         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2896         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2897         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2898
2899         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2900         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2901         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2902         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u6807\\u51c6\\u65f6\\u95f4", "-5:00" },
2903         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2904         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2905         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2906         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u590f\\u4ee4\\u65f6\\u95f4", "-4:00" },
2907         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2908         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2909
2910         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2911         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2912         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2913         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2914         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2915         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2916         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2917         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2918     // icu zh.txt does not have info for this time zone
2919         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2920         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2921
2922         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2923         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2924         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2925         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2926         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2927         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2928         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2929         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2930         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2931         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2932
2933         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2934         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2935         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2936         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2937         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2938         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u683C\\u6797\\u5C3C\\u6CBB\\u6807\\u51C6\\u65F6\\u95F4", "+0:00" },
2939         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2940         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2941         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2942         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u4ee4\\u65f6\\u95f4", "+1:00" },
2943         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2944         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2945         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2946
2947         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2948         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2949         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2950         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2951         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2952         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2953         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2954         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2955         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2956         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2957
2958         // JB#5150
2959         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2960         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2961         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2962         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2963         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2964         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2965         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2966         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2967         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2968         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2969
2970         // ==========
2971
2972         { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2973         { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2974         { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2975         { "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" },
2976         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2977         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2978         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2979         { "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" },
2980         { "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" },
2981         { "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" },
2982
2983         { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2984         { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2985         { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2986         { "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" },
2987         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2988         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2989         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2990         { "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" },
2991         { "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" },
2992         { "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" },
2993
2994         { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2995         { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2996         { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2997         { "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" },
2998         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2999         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3000         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3001         { "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" },
3002         { "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" },
3003         { "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" },
3004
3005         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3006         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3007         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3008         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-5:00" },
3009         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3010         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3011         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3012         { "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" },
3013         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092E\\u092F", "America/Havana" },
3014         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092e\\u092f", "America/Havana" },
3015
3016         { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3017         { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3018         { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3019         { "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" },
3020         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3021         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3022         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3023         { "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" },
3024         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3025         { "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" },
3026
3027         { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3028         { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3029         { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3030         { "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" },
3031         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3032         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3033         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3034         { "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" },
3035         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3036         { "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" },
3037
3038         { "hi", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3039         { "hi", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3040         { "hi", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3041         { "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" },
3042         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3043         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3044         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3045         { "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" },
3046         { "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" },
3047         { "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" },
3048
3049         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3050         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3051         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3052         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3053         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3054         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3055         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3056         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3057         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3058         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3059
3060         { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3061         { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3062         { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "IST", "+5:30" },
3063         { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3064         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3065         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3066         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "IST", "+05:30" },
3067         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3068         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IST", "Asia/Calcutta" },
3069         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "Asia/Calcutta" },
3070
3071         // ==========
3072
3073         { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3074         { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-08:00", "-8:00" },
3075         { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-8", "America/Los_Angeles" },
3076         { "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" },
3077         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3078         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-07:00", "-7:00" },
3079         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-7", "America/Los_Angeles" },
3080         { "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" },
3081     // icu bg.txt has exemplar city for this time zone
3082         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3083         { "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" },
3084         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3085
3086         { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3087         { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3088         { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3089         { "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" },
3090         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3091         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3092         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3093         { "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" },
3094         { "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" },
3095         { "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" },
3096
3097         { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3098         { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3099         { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3100         { "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" },
3101         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3102         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3103         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3104         { "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" },
3105     // icu bg.txt does not have info for this time zone
3106         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
3107         { "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" },
3108
3109         { "bg", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3110         { "bg", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-05:00", "-5:00" },
3111         { "bg", "America/Havana", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-5", "-5:00" },
3112         { "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" },
3113         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3114         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-04:00", "-4:00" },
3115         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-4", "-4:00" },
3116         { "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" },
3117         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u041a\\u0443\\u0431\\u0430", "America/Havana" },
3118         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043C\\u0435", "America/Havana" },
3119
3120         { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3121         { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3122         { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3123         { "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" },
3124         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3125         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3126         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3127         { "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" },
3128         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3129         { "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" },
3130
3131         { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3132         { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3133         { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3134         { "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" },
3135         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3136         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3137         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3138         { "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" },
3139         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3140         { "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" },
3141
3142         { "bg", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3143         { "bg", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3144         { "bg", "Europe/London", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3145         { "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" },
3146         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3147         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+01:00", "+1:00" },
3148         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+1", "+1:00" },
3149         { "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" },
3150         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u041E\\u0431\\u0435\\u0434\\u0438\\u043D\\u0435\\u043D\\u043E\\u0442\\u043E \\u043A\\u0440\\u0430\\u043B\\u0441\\u0442\\u0432\\u043E", "Europe/London" },
3151         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u041E\\u0431\\u0435\\u0434\\u0438\\u043D\\u0435\\u043D\\u043E\\u0442\\u043E \\u043A\\u0440\\u0430\\u043B\\u0441\\u0442\\u0432\\u043E", "Europe/London" },
3152
3153         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3154         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3155         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3156         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3157         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3158         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3159         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3160         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3161         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3162         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3163
3164         // JB#5150
3165         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3166         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3167         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+5:30" },
3168         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u043d\\u0434\\u0438\\u0439\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
3169         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3170         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3171         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+05:30" },
3172         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u043d\\u0434\\u0438\\u0439\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
3173         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u0418\\u043D\\u0434\\u0438\\u044F", "Asia/Calcutta" },
3174         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u043d\\u0434\\u0438\\u0439\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "Asia/Calcutta" },
3175     // ==========
3176
3177         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3178         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3179         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
3180         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u6a19\\u6e96\\u6642", "America/Los_Angeles" },
3181         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-700" },
3182         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3183         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
3184         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u590f\\u6642\\u9593", "America/Los_Angeles" },
3185     // icu ja.txt has exemplar city for this time zone
3186         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3187         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30E1\\u30EA\\u30AB\\u592A\\u5e73\\u6D0B\\u6642\\u9593", "America/Los_Angeles" },
3188         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3189
3190         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3191         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3192         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3193         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3194         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3195         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3196         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3197         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3198     // icu ja.txt does not have info for this time zone
3199         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3200         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3201
3202         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3203         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3204         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3205         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3206         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3207         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3208         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3209         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3210         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3211         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3212
3213         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3214         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3215         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3216         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u6A19\\u6E96\\u6642", "-5:00" },
3217         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3218         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3219         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3220         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u590F\\u6642\\u9593", "-4:00" },
3221         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3222         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3223
3224         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3225         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3226         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3227         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3228         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3229         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3230         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3231         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3232     // icu ja.txt does not have info for this time zone
3233         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3234         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3235
3236         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3237         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3238         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3239         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3240         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3241         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3242         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3243         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3244         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3245         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3246
3247         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3248         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3249         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3250         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u30B0\\u30EA\\u30CB\\u30C3\\u30B8\\u6A19\\u6E96\\u6642", "+0:00" },
3251         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3252         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3253         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3254         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u6642\\u9593", "+1:00" },
3255         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3256         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3257         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3258
3259         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3260         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3261         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3262         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3263         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3264         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3265         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3266         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3267         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3268         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3269
3270         // JB#5150
3271         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3272         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3273         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3274         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3275         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3276         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3277         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3278         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3279         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u30A4\\u30F3\\u30C9\\u6642\\u9593", "Asia/Calcutta" },
3280         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "Asia/Calcutta" },
3281
3282     // ==========
3283
3284         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3285         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3286         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
3287         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "GMT-08:00", "-8:00" },
3288         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3289         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3290         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
3291         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "GMT-07:00", "-7:00" },
3292         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles", "America/Los_Angeles" },
3293         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Los Angeles", "America/Los_Angeles" },
3294
3295         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3296         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3297         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3298         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3299         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3300         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3301         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3302         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3303         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3304         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3305
3306         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3307         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3308         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3309         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3310         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3311         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3312         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3313         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3314         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3315         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3316
3317         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3318         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3319         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3320         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "GMT-05:00", "-5:00" },
3321         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3322         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3323         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3324         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "GMT-04:00", "-4:00" },
3325         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "v", "CU", "America/Havana" },
3326         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "CU", "America/Havana" },
3327
3328         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3329         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3330         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3331         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3332         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3333         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3334         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3335         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3336         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3337         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3338
3339         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3340         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3341         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3342         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3343         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3344         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3345         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3346         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3347         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3348         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3349
3350         { "ti", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3351         { "ti", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3352         { "ti", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3353         { "ti", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "GMT", "+0:00" },
3354         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3355         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3356         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3357         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "GMT+01:00", "+1:00" },
3358         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "v", "GB", "Europe/London" },
3359         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "GB", "Europe/London" },
3360
3361         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3362         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3363         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3364         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3365         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3366         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3367         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3368         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3369         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3370         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3371
3372         // JB#5150
3373         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3374         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3375         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3376         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3377         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3378         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3379         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3380         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3381         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IN", "Alna/Calcutta" },
3382         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "IN", "Asia/Calcutta" },
3383
3384         // Ticket#8589 Partial location name to use country name if the zone is the golden
3385         // zone for the time zone's country.
3386         { "en_MX", "America/Chicago", "1995-07-15T00:00:00Z", "vvvv", "Central Time (United States)", "America/Chicago"},
3387
3388         // Tests proper handling of time zones that should have empty sets when inherited from the parent.
3389         // For example, en_GB understands CET as Central European Time, but en_HK, which inherits from en_GB
3390         // does not
3391         { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3392         { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3393         { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "CET", "+1:00"},
3394         { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "CEST", "+2:00"},
3395         { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3396         { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3397         { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "GMT+1", "+1:00"},
3398         { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "GMT+2", "+2:00"},
3399
3400         { NULL, NULL, NULL, NULL, NULL, NULL },
3401     };
3402
3403     UErrorCode status = U_ZERO_ERROR;
3404     Calendar *cal = GregorianCalendar::createInstance(status);
3405     if (failure(status, "GregorianCalendar::createInstance", TRUE)) return;
3406     SimpleDateFormat testfmt(UnicodeString("yyyy-MM-dd'T'HH:mm:ss'Z'"), status);
3407     if (failure(status, "SimpleDateFormat constructor", TRUE)) return;
3408     testfmt.setTimeZone(*TimeZone::getGMT());
3409
3410     for (int i = 0; fallbackTests[i][0]; i++) {
3411         const char **testLine = fallbackTests[i];
3412         UnicodeString info[5];
3413         for ( int j = 0 ; j < 5 ; j++ ) {
3414             info[j] = UnicodeString(testLine[j], -1, US_INV);
3415         }
3416         info[4] = info[4].unescape();
3417         logln("%s;%s;%s;%s", testLine[0], testLine[1], testLine[2], testLine[3]);
3418
3419         TimeZone *tz = TimeZone::createTimeZone(info[1]);
3420
3421         UDate d = testfmt.parse(testLine[2], status);
3422         cal->setTime(d, status);
3423         if (U_FAILURE(status)) {
3424             errln(UnicodeString("Failed to set date: ") + testLine[2]);
3425         }
3426
3427         SimpleDateFormat fmt(info[3], Locale(testLine[0]),status);
3428         ASSERT_OK(status);
3429         cal->adoptTimeZone(tz);
3430         UnicodeString result;
3431         FieldPosition pos(FieldPosition::DONT_CARE);
3432         fmt.format(*cal,result,pos);
3433         if (result != info[4]) {
3434             errln(info[0] + ";" + info[1] + ";" + info[2] + ";" + info[3] + " expected: '" +
3435                   info[4] + "' but got: '" + result + "'");
3436         }
3437     }
3438     delete cal;
3439 }
3440
3441 void DateFormatTest::TestRoundtripWithCalendar(void) {
3442     UErrorCode status = U_ZERO_ERROR;
3443
3444     TimeZone *tz = TimeZone::createTimeZone("Europe/Paris");
3445     TimeZone *gmt = TimeZone::createTimeZone("Etc/GMT");
3446
3447     Calendar *calendars[] = {
3448         Calendar::createInstance(*tz, Locale("und@calendar=gregorian"), status),
3449         Calendar::createInstance(*tz, Locale("und@calendar=buddhist"), status),
3450 //        Calendar::createInstance(*tz, Locale("und@calendar=hebrew"), status),
3451         Calendar::createInstance(*tz, Locale("und@calendar=islamic"), status),
3452         Calendar::createInstance(*tz, Locale("und@calendar=japanese"), status),
3453         NULL
3454     };
3455     if (U_FAILURE(status)) {
3456         dataerrln("Failed to initialize calendars: %s", u_errorName(status));
3457         for (int i = 0; calendars[i] != NULL; i++) {
3458             delete calendars[i];
3459         }
3460         return;
3461     }
3462
3463     //FIXME The formatters commented out below are currently failing because of
3464     // the calendar calculation problem reported by #6691
3465
3466     // The order of test formatters must match the order of calendars above.
3467     DateFormat *formatters[] = {
3468         DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("en_US")), //calendar=gregorian
3469         DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("th_TH")), //calendar=buddhist
3470 //        DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("he_IL@calendar=hebrew")),
3471         DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ar_EG@calendar=islamic")),
3472 //        DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ja_JP@calendar=japanese")),
3473         NULL
3474     };
3475
3476     UDate d = Calendar::getNow();
3477     UnicodeString buf;
3478     FieldPosition fpos;
3479     ParsePosition ppos;
3480
3481     for (int i = 0; formatters[i] != NULL; i++) {
3482         buf.remove();
3483         fpos.setBeginIndex(0);
3484         fpos.setEndIndex(0);
3485         calendars[i]->setTime(d, status);
3486
3487         // Normal case output - the given calendar matches the calendar
3488         // used by the formatter
3489         formatters[i]->format(*calendars[i], buf, fpos);
3490         UnicodeString refStr(buf);
3491
3492         for (int j = 0; calendars[j] != NULL; j++) {
3493             if (j == i) {
3494                 continue;
3495             }
3496             buf.remove();
3497             fpos.setBeginIndex(0);
3498             fpos.setEndIndex(0);
3499             calendars[j]->setTime(d, status);
3500
3501             // Even the different calendar type is specified,
3502             // we should get the same result.
3503             formatters[i]->format(*calendars[j], buf, fpos);
3504             if (refStr != buf) {
3505                 errln((UnicodeString)"FAIL: Different format result with a different calendar for the same time -"
3506                         + "\n Reference calendar type=" + calendars[i]->getType()
3507                         + "\n Another calendar type=" + calendars[j]->getType()
3508                         + "\n Expected result=" + refStr
3509                         + "\n Actual result=" + buf);
3510             }
3511         }
3512
3513         calendars[i]->setTimeZone(*gmt);
3514         calendars[i]->clear();
3515         ppos.setErrorIndex(-1);
3516         ppos.setIndex(0);
3517
3518         // Normal case parse result - the given calendar matches the calendar
3519         // used by the formatter
3520         formatters[i]->parse(refStr, *calendars[i], ppos);
3521
3522         for (int j = 0; calendars[j] != NULL; j++) {
3523             if (j == i) {
3524                 continue;
3525             }
3526             calendars[j]->setTimeZone(*gmt);
3527             calendars[j]->clear();
3528             ppos.setErrorIndex(-1);
3529             ppos.setIndex(0);
3530
3531             // Even the different calendar type is specified,
3532             // we should get the same time and time zone.
3533             formatters[i]->parse(refStr, *calendars[j], ppos);
3534             if (calendars[i]->getTime(status) != calendars[j]->getTime(status)
3535                 || calendars[i]->getTimeZone() != calendars[j]->getTimeZone()) {
3536                 UnicodeString tzid;
3537                 errln((UnicodeString)"FAIL: Different parse result with a different calendar for the same string -"
3538                         + "\n Reference calendar type=" + calendars[i]->getType()
3539                         + "\n Another calendar type=" + calendars[j]->getType()
3540                         + "\n Date string=" + refStr
3541                         + "\n Expected time=" + calendars[i]->getTime(status)
3542                         + "\n Expected time zone=" + calendars[i]->getTimeZone().getID(tzid)
3543                         + "\n Actual time=" + calendars[j]->getTime(status)
3544                         + "\n Actual time zone=" + calendars[j]->getTimeZone().getID(tzid));
3545             }
3546         }
3547         if (U_FAILURE(status)) {
3548             errln((UnicodeString)"FAIL: " + u_errorName(status));
3549             break;
3550         }
3551     }
3552
3553     delete tz;
3554     delete gmt;
3555     for (int i = 0; calendars[i] != NULL; i++) {
3556         delete calendars[i];
3557     }
3558     for (int i = 0; formatters[i] != NULL; i++) {
3559         delete formatters[i];
3560     }
3561 }
3562
3563 /*
3564 void DateFormatTest::TestRelativeError(void)
3565 {
3566     UErrorCode status;
3567     Locale en("en");
3568
3569     DateFormat *en_reltime_reldate =         DateFormat::createDateTimeInstance(DateFormat::kFullRelative,DateFormat::kFullRelative,en);
3570     if(en_reltime_reldate == NULL) {
3571         logln("PASS: rel date/rel time failed");
3572     } else {
3573         errln("FAIL: rel date/rel time created, should have failed.");
3574         delete en_reltime_reldate;
3575     }
3576 }
3577
3578 void DateFormatTest::TestRelativeOther(void)
3579 {
3580     logln("Nothing in this test. When we get more data from CLDR, put in some tests of -2, +2, etc. ");
3581 }
3582 */
3583
3584 void DateFormatTest::Test6338(void)
3585 {
3586     UErrorCode status = U_ZERO_ERROR;
3587
3588     SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("ar"), status);
3589     if (failure(status, "new SimpleDateFormat", TRUE)) return;
3590
3591     UDate dt1 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3592     UnicodeString str1;
3593     str1 = fmt1->format(dt1, str1);
3594     logln(str1);
3595
3596     UDate dt11 = fmt1->parse(str1, status);
3597     failure(status, "fmt->parse");
3598
3599     UnicodeString str11;
3600     str11 = fmt1->format(dt11, str11);
3601     logln(str11);
3602
3603     if (str1 != str11) {
3604         errln((UnicodeString)"FAIL: Different dates str1:" + str1
3605             + " str2:" + str11);
3606     }
3607     delete fmt1;
3608
3609     /////////////////
3610
3611     status = U_ZERO_ERROR;
3612     SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("y M d"), Locale("ar"), status);
3613     failure(status, "new SimpleDateFormat");
3614
3615     UDate dt2 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3616     UnicodeString str2;
3617     str2 = fmt2->format(dt2, str2);
3618     logln(str2);
3619
3620     UDate dt22 = fmt2->parse(str2, status);
3621     failure(status, "fmt->parse");
3622
3623     UnicodeString str22;
3624     str22 = fmt2->format(dt22, str22);
3625     logln(str22);
3626
3627     if (str2 != str22) {
3628         errln((UnicodeString)"FAIL: Different dates str1:" + str2
3629             + " str2:" + str22);
3630     }
3631     delete fmt2;
3632
3633     /////////////////
3634
3635     status = U_ZERO_ERROR;
3636     SimpleDateFormat *fmt3 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("en-us"), status);
3637     failure(status, "new SimpleDateFormat");
3638
3639     UDate dt3 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3640     UnicodeString str3;
3641     str3 = fmt3->format(dt3, str3);
3642     logln(str3);
3643
3644     UDate dt33 = fmt3->parse(str3, status);
3645     failure(status, "fmt->parse");
3646
3647     UnicodeString str33;
3648     str33 = fmt3->format(dt33, str33);
3649     logln(str33);
3650
3651     if (str3 != str33) {
3652         errln((UnicodeString)"FAIL: Different dates str1:" + str3
3653             + " str2:" + str33);
3654     }
3655     delete fmt3;
3656
3657     /////////////////
3658
3659     status = U_ZERO_ERROR;
3660     SimpleDateFormat *fmt4 = new SimpleDateFormat(UnicodeString("y M  d"), Locale("en-us"), status);
3661     failure(status, "new SimpleDateFormat");
3662
3663     UDate dt4 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3664     UnicodeString str4;
3665     str4 = fmt4->format(dt4, str4);
3666     logln(str4);
3667
3668     UDate dt44 = fmt4->parse(str4, status);
3669     failure(status, "fmt->parse");
3670
3671     UnicodeString str44;
3672     str44 = fmt4->format(dt44, str44);
3673     logln(str44);
3674
3675     if (str4 != str44) {
3676         errln((UnicodeString)"FAIL: Different dates str1:" + str4
3677             + " str2:" + str44);
3678     }
3679     delete fmt4;
3680
3681 }
3682
3683 void DateFormatTest::Test6726(void)
3684 {
3685     // status
3686 //    UErrorCode status = U_ZERO_ERROR;
3687
3688     // fmtf, fmtl, fmtm, fmts;
3689     UnicodeString strf, strl, strm, strs;
3690     UDate dt = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3691
3692     Locale loc("ja");
3693     DateFormat* fmtf = DateFormat::createDateTimeInstance(DateFormat::FULL, DateFormat::FULL, loc);
3694     DateFormat* fmtl = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::FULL, loc);
3695     DateFormat* fmtm = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, loc);
3696     DateFormat* fmts = DateFormat::createDateTimeInstance(DateFormat::SHORT, DateFormat::FULL, loc);
3697     if (fmtf == NULL || fmtl == NULL || fmtm == NULL || fmts == NULL) {
3698         dataerrln("Unable to create DateFormat. got NULL.");
3699         /* It may not be true that if one is NULL all is NULL.  Just to be safe. */
3700         delete fmtf;
3701         delete fmtl;
3702         delete fmtm;
3703         delete fmts;
3704
3705         return;
3706     }
3707     strf = fmtf->format(dt, strf);
3708     strl = fmtl->format(dt, strl);
3709     strm = fmtm->format(dt, strm);
3710     strs = fmts->format(dt, strs);
3711
3712
3713     logln("strm.charAt(10)=%04X wanted 0x20\n", strm.charAt(10));
3714     if (strm.charAt(10) != UChar(0x0020)) {
3715       errln((UnicodeString)"FAIL: Improper formatted date: " + strm );
3716     }
3717     logln("strs.charAt(10)=%04X wanted 0x20\n", strs.charAt(8));
3718     if (strs.charAt(10)  != UChar(0x0020)) {
3719         errln((UnicodeString)"FAIL: Improper formatted date: " + strs);
3720     }
3721
3722     delete fmtf;
3723     delete fmtl;
3724     delete fmtm;
3725     delete fmts;
3726
3727     return;
3728 }
3729
3730 /**
3731  * Test DateFormat's parsing of default GMT variants.  See ticket#6135
3732  */
3733 void DateFormatTest::TestGMTParsing() {
3734     const char* DATA[] = {
3735         "HH:mm:ss Z",
3736
3737         // pattern, input, expected output (in quotes)
3738         "HH:mm:ss Z",       "10:20:30 GMT+03:00",   "10:20:30 +0300",
3739         "HH:mm:ss Z",       "10:20:30 UT-02:00",    "10:20:30 -0200",
3740         "HH:mm:ss Z",       "10:20:30 GMT",         "10:20:30 +0000",
3741         "HH:mm:ss vvvv",    "10:20:30 UT+10:00",    "10:20:30 +1000",
3742         "HH:mm:ss zzzz",    "10:20:30 UTC",         "10:20:30 +0000",   // standalone "UTC"
3743         "ZZZZ HH:mm:ss",    "UT 10:20:30",          "10:20:30 +0000",
3744         "z HH:mm:ss",       "UT+0130 10:20:30",     "10:20:30 +0130",
3745         "z HH:mm:ss",       "UTC+0130 10:20:30",    "10:20:30 +0130",
3746         // Note: GMT-1100 no longer works because of the introduction of the short
3747         // localized GMT support. Previous implementation support this level of
3748         // leniency (no separator char in localized GMT format), but the new
3749         // implementation handles GMT-11 as the legitimate short localized GMT format
3750         // and stop at there. Otherwise, roundtrip would be broken.
3751         //"HH mm Z ss",       "10 20 GMT-1100 30",    "10:20:30 -1100",
3752         "HH mm Z ss",       "10 20 GMT-11 30",    "10:20:30 -1100",
3753         "HH:mm:ssZZZZZ",    "14:25:45Z",            "14:25:45 +0000",
3754         "HH:mm:ssZZZZZ",    "15:00:00-08:00",       "15:00:00 -0800",
3755     };
3756     const int32_t DATA_len = UPRV_LENGTHOF(DATA);
3757     expectParse(DATA, DATA_len, Locale("en"));
3758 }
3759
3760 // Test case for localized GMT format parsing
3761 // with no delimitters in offset format (Chinese locale)
3762 void DateFormatTest::Test6880() {
3763     UErrorCode status = U_ZERO_ERROR;
3764     UDate d1, d2, dp1, dp2, dexp1, dexp2;
3765     UnicodeString s1, s2;
3766
3767     TimeZone *tz = TimeZone::createTimeZone("Asia/Shanghai");
3768     GregorianCalendar gcal(*tz, status);
3769     if (failure(status, "construct GregorianCalendar", TRUE)) return;
3770
3771     gcal.clear();
3772     gcal.set(1900, UCAL_JULY, 1, 12, 00);   // offset 8:05:43
3773     d1 = gcal.getTime(status);
3774
3775     gcal.clear();
3776     gcal.set(1950, UCAL_JULY, 1, 12, 00);   // offset 8:00
3777     d2 = gcal.getTime(status);
3778
3779     gcal.clear();
3780     gcal.set(1970, UCAL_JANUARY, 1, 12, 00);
3781     dexp2 = gcal.getTime(status);
3782     dexp1 = dexp2 - (5*60 + 43)*1000;   // subtract 5m43s
3783
3784     if (U_FAILURE(status)) {
3785         errln("FAIL: Gregorian calendar error");
3786     }
3787
3788     DateFormat *fmt = DateFormat::createTimeInstance(DateFormat::kFull, Locale("zh"));
3789     if (fmt == NULL) {
3790         dataerrln("Unable to create DateFormat. Got NULL.");
3791         return;
3792     }
3793     fmt->adoptTimeZone(tz);
3794
3795     fmt->format(d1, s1);
3796     fmt->format(d2, s2);
3797
3798     dp1 = fmt->parse(s1, status);
3799     dp2 = fmt->parse(s2, status);
3800
3801     if (U_FAILURE(status)) {
3802         errln("FAIL: Parse failure");
3803     }
3804
3805     if (dp1 != dexp1) {
3806         errln("FAIL: Failed to parse " + s1 + " parsed: " + dp1 + " expected: " + dexp1);
3807     }
3808     if (dp2 != dexp2) {
3809         errln("FAIL: Failed to parse " + s2 + " parsed: " + dp2 + " expected: " + dexp2);
3810     }
3811
3812     delete fmt;
3813 }
3814
3815 typedef struct {
3816     const char * localeStr;
3817     UBool        lenient;
3818     UBool        expectFail;
3819     UnicodeString datePattern;
3820     UnicodeString dateString;
3821 } NumAsStringItem;
3822
3823 void DateFormatTest::TestNumberAsStringParsing()
3824 {
3825     const NumAsStringItem items[] = {
3826         // loc lenient fail?  datePattern                                         dateString
3827         { "",   FALSE, TRUE,  UnicodeString("y MMMM d HH:mm:ss"),                 UnicodeString("2009 7 14 08:43:57") },
3828         { "",   TRUE,  FALSE, UnicodeString("y MMMM d HH:mm:ss"),                 UnicodeString("2009 7 14 08:43:57") },
3829         { "en", FALSE, FALSE, UnicodeString("MMM d, y"),                          UnicodeString("Jul 14, 2009") },
3830         { "en", TRUE,  FALSE, UnicodeString("MMM d, y"),                          UnicodeString("Jul 14, 2009") },
3831         { "en", FALSE, TRUE,  UnicodeString("MMM d, y"),                          UnicodeString("7 14, 2009") },
3832         { "en", TRUE,  FALSE, UnicodeString("MMM d, y"),                          UnicodeString("7 14, 2009") },
3833         { "ja", FALSE, FALSE, UnicodeString("yyyy/MM/dd"),                        UnicodeString("2009/07/14")         },
3834         { "ja", TRUE,  FALSE, UnicodeString("yyyy/MM/dd"),                        UnicodeString("2009/07/14")         },
3835       //{ "ja", FALSE, FALSE, UnicodeString("yyyy/MMMMM/d"),                      UnicodeString("2009/7/14")          }, // #8860 covers test failure
3836         { "ja", TRUE,  FALSE, UnicodeString("yyyy/MMMMM/d"),                      UnicodeString("2009/7/14")          },
3837         { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"),   CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   },
3838         { "ja", TRUE,  FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"),   CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   },
3839         { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"),        CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   },
3840         { "ja", TRUE,  FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"),        CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   }, // #8820 fixes test failure
3841         { "ko", FALSE, FALSE, UnicodeString("yyyy. M. d."),                       UnicodeString("2009. 7. 14.")       },
3842         { "ko", TRUE,  FALSE, UnicodeString("yyyy. M. d."),                       UnicodeString("2009. 7. 14.")       },
3843         { "ko", FALSE, FALSE, UnicodeString("yyyy. MMMMM d."),                    CharsToUnicodeString("2009. 7\\uC6D4 14.")             },
3844         { "ko", TRUE,  FALSE, UnicodeString("yyyy. MMMMM d."),                    CharsToUnicodeString("2009. 7\\uC6D4 14.")             }, // #8820 fixes test failure
3845         { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3846         { "ko", TRUE,  FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3847         { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"),      CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3848         { "ko", TRUE,  FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"),      CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") }, // #8820 fixes test failure
3849         { NULL, FALSE, FALSE, UnicodeString(""),                                  UnicodeString("")                   }
3850     };
3851     const NumAsStringItem * itemPtr;
3852     for (itemPtr = items; itemPtr->localeStr != NULL; itemPtr++ ) {
3853         Locale locale = Locale::createFromName(itemPtr->localeStr);
3854         UErrorCode status = U_ZERO_ERROR;
3855         SimpleDateFormat *formatter = new SimpleDateFormat(itemPtr->datePattern, locale, status);
3856         if (formatter == NULL || U_FAILURE(status)) {
3857             dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3858             return;
3859         }
3860
3861         formatter->setLenient(itemPtr->lenient);
3862         formatter->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->lenient, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->lenient, status);
3863         UDate date1 = formatter->parse(itemPtr->dateString, status);
3864         if (U_FAILURE(status)) {
3865             if (!itemPtr->expectFail) {
3866                 errln("FAIL, err when expected success: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3867                         ": using pattern \"" + itemPtr->datePattern + "\", could not parse \"" + itemPtr->dateString + "\"; err: " + u_errorName(status) );
3868             }
3869         } else if (itemPtr->expectFail) {
3870                 errln("FAIL, expected err but got none: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3871                         ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\"." );
3872         } else if (!itemPtr->lenient) {
3873             UnicodeString formatted;
3874             formatter->format(date1, formatted);
3875             if (formatted != itemPtr->dateString) {
3876                 errln("FAIL, mismatch formatting parsed date: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3877                         ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\", formatted result \"" + formatted + "\".");
3878             }
3879         }
3880
3881         delete formatter;
3882     }
3883 }
3884
3885 void DateFormatTest::TestISOEra() {
3886
3887     const char* data[] = {
3888     // input, output
3889     "BC 4004-10-23T07:00:00Z", "BC 4004-10-23T07:00:00Z",
3890     "AD 4004-10-23T07:00:00Z", "AD 4004-10-23T07:00:00Z",
3891     "-4004-10-23T07:00:00Z"  , "BC 4005-10-23T07:00:00Z",
3892     "4004-10-23T07:00:00Z"   , "AD 4004-10-23T07:00:00Z",
3893     };
3894
3895     int32_t numData = 8;
3896
3897     UErrorCode status = U_ZERO_ERROR;
3898
3899     // create formatter
3900     SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("GGG yyyy-MM-dd'T'HH:mm:ss'Z"), status);
3901     failure(status, "new SimpleDateFormat", TRUE);
3902     if (status == U_MISSING_RESOURCE_ERROR) {
3903         if (fmt1 != NULL) {
3904             delete fmt1;
3905         }
3906         return;
3907     }
3908     for(int i=0; i < numData; i+=2) {
3909         // create input string
3910         UnicodeString in = data[i];
3911
3912         // parse string to date
3913         UDate dt1 = fmt1->parse(in, status);
3914         failure(status, "fmt->parse", TRUE);
3915
3916         // format date back to string
3917         UnicodeString out;
3918         out = fmt1->format(dt1, out);
3919         logln(out);
3920
3921         // check that roundtrip worked as expected
3922         UnicodeString expected = data[i+1];
3923         if (out != expected) {
3924             dataerrln((UnicodeString)"FAIL: " + in + " -> " + out + " expected -> " + expected);
3925         }
3926     }
3927
3928     delete fmt1;
3929 }
3930 void DateFormatTest::TestFormalChineseDate() {
3931
3932     UErrorCode status = U_ZERO_ERROR;
3933     UnicodeString pattern ("y\\u5e74M\\u6708d\\u65e5", -1, US_INV );
3934     pattern = pattern.unescape();
3935     UnicodeString override ("y=hanidec;M=hans;d=hans", -1, US_INV );
3936
3937     // create formatter
3938     SimpleDateFormat *sdf = new SimpleDateFormat(pattern,override,Locale::getChina(),status);
3939     if (failure(status, "new SimpleDateFormat with override", TRUE)) {
3940         return;
3941     }
3942
3943     UDate thedate = date(2009-1900, UCAL_JULY, 28);
3944     FieldPosition pos(FieldPosition::DONT_CARE);
3945     UnicodeString result;
3946     sdf->format(thedate,result,pos);
3947
3948     UnicodeString expected = "\\u4e8c\\u3007\\u3007\\u4e5d\\u5e74\\u4e03\\u6708\\u4e8c\\u5341\\u516b\\u65e5";
3949     expected = expected.unescape();
3950     if (result != expected) {
3951         dataerrln((UnicodeString)"FAIL: -> " + result + " expected -> " + expected);
3952     }
3953
3954     UDate parsedate = sdf->parse(expected,status);
3955     if ( parsedate != thedate ) {
3956         UnicodeString pat1 ("yyyy-MM-dd'T'HH:mm:ss'Z'", -1, US_INV );
3957         SimpleDateFormat *usf = new SimpleDateFormat(pat1,Locale::getEnglish(),status);
3958         UnicodeString parsedres,expres;
3959         usf->format(parsedate,parsedres,pos);
3960         usf->format(thedate,expres,pos);
3961         dataerrln((UnicodeString)"FAIL: parsed -> " + parsedres + " expected -> " + expres);
3962         delete usf;
3963     }
3964     delete sdf;
3965 }
3966
3967 // Test case for #8675
3968 // Incorrect parse offset with stand alone GMT string on 2nd or later iteration.
3969 void DateFormatTest::TestStandAloneGMTParse() {
3970     UErrorCode status = U_ZERO_ERROR;
3971     SimpleDateFormat *sdf = new SimpleDateFormat("ZZZZ", Locale(""), status);
3972
3973     if (U_SUCCESS(status)) {
3974
3975         UnicodeString inText("GMT$$$");
3976         for (int32_t i = 0; i < 10; i++) {
3977             ParsePosition pos(0);
3978             sdf->parse(inText, pos);
3979             if (pos.getIndex() != 3) {
3980                 errln((UnicodeString)"FAIL: Incorrect output parse position: actual=" + pos.getIndex() + " expected=3");
3981             }
3982         }
3983
3984         delete sdf;
3985     } else {
3986         dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3987     }
3988 }
3989
3990 void DateFormatTest::TestParsePosition() {
3991     const char* TestData[][4] = {
3992         // {<pattern>, <lead>, <date string>, <trail>}
3993         {"yyyy-MM-dd HH:mm:ssZ", "", "2010-01-10 12:30:00+0500", ""},
3994         {"yyyy-MM-dd HH:mm:ss ZZZZ", "", "2010-01-10 12:30:00 GMT+05:00", ""},
3995         {"Z HH:mm:ss", "", "-0100 13:20:30", ""},
3996         {"y-M-d Z", "", "2011-8-25 -0400", " Foo"},
3997         {"y/M/d H:mm:ss z", "", "2011/7/1 12:34:00 PDT", ""},
3998         {"y/M/d H:mm:ss z", "+123", "2011/7/1 12:34:00 PDT", " PST"},
3999         {"vvvv a h:mm:ss", "", "Pacific Time AM 10:21:45", ""},
4000         {"HH:mm v M/d", "111", "14:15 PT 8/10", " 12345"},
4001         {"'time zone:' VVVV 'date:' yyyy-MM-dd", "xxxx", "time zone: Los Angeles Time date: 2010-02-25", "xxxx"},
4002         {"yG", "", "2012AD", ""},
4003         {"yG", "", "2012", "x"},
4004         {0, 0, 0, 0},
4005     };
4006
4007     for (int32_t i = 0; TestData[i][0]; i++) {
4008         UErrorCode status = U_ZERO_ERROR;
4009         SimpleDateFormat *sdf = new SimpleDateFormat(UnicodeString(TestData[i][0]), status);
4010         if (failure(status, "new SimpleDateFormat", TRUE)) return;
4011
4012         int32_t startPos, resPos;
4013
4014         // lead text
4015         UnicodeString input(TestData[i][1]);
4016         startPos = input.length();
4017
4018         // date string
4019         input += TestData[i][2];
4020         resPos = input.length();
4021
4022         // trail text
4023         input += TestData[i][3];
4024
4025         ParsePosition pos(startPos);
4026         //UDate d = sdf->parse(input, pos);
4027         (void)sdf->parse(input, pos);
4028
4029         if (pos.getIndex() != resPos) {
4030             errln(UnicodeString("FAIL: Parsing [") + input + "] with pattern [" + TestData[i][0] + "] returns position - "
4031                 + pos.getIndex() + ", expected - " + resPos);
4032         }
4033
4034         delete sdf;
4035     }
4036 }
4037
4038
4039 typedef struct {
4040     int32_t era;
4041     int32_t year;
4042     int32_t month; // 1-based
4043     int32_t isLeapMonth;
4044     int32_t day;
4045 } ChineseCalTestDate;
4046
4047 #define NUM_TEST_DATES 3
4048
4049 typedef struct {
4050     const char *   locale;
4051     int32_t        style; // <0 => custom
4052     UnicodeString  dateString[NUM_TEST_DATES];
4053 } MonthPatternItem;
4054
4055 void DateFormatTest::TestMonthPatterns()
4056 {
4057     const ChineseCalTestDate dates[NUM_TEST_DATES] = {
4058         // era yr mo lp da
4059         {  78, 29, 4, 0, 2 }, // (in chinese era 78) gregorian 2012-4-22
4060         {  78, 29, 4, 1, 2 }, // (in chinese era 78) gregorian 2012-5-22
4061         {  78, 29, 5, 0, 2 }, // (in chinese era 78) gregorian 2012-6-20
4062     };
4063
4064     const MonthPatternItem items[] = {
4065         // locale                     date style;           expected formats for the 3 dates above
4066         { "root@calendar=chinese",    DateFormat::kLong,  { UnicodeString("2012(ren-chen) M04 2"),  UnicodeString("2012(ren-chen) M04bis 2"),  UnicodeString("2012(ren-chen) M05 2") } },
4067         { "root@calendar=chinese",    DateFormat::kShort, { UnicodeString("2012-04-02"),    UnicodeString("2012-04bis-02"),         UnicodeString("2012-05-02") } },
4068         { "root@calendar=chinese",    -1,                 { UnicodeString("29-4-2"),        UnicodeString("29-4bis-2"),             UnicodeString("29-5-2") } },
4069         { "root@calendar=chinese",    -2,                 { UnicodeString("78x29-4-2"),     UnicodeString("78x29-4bis-2"),          UnicodeString("78x29-5-2") } },
4070         { "root@calendar=chinese",    -3,                 { UnicodeString("ren-chen-4-2"),  UnicodeString("ren-chen-4bis-2"),       UnicodeString("ren-chen-5-2") } },
4071         { "root@calendar=chinese",    -4,                 { UnicodeString("ren-chen M04 2"),  UnicodeString("ren-chen M04bis 2"),   UnicodeString("ren-chen M05 2") } },
4072         { "en@calendar=gregorian",    -3,                 { UnicodeString("2012-4-22"),     UnicodeString("2012-5-22"),             UnicodeString("2012-6-20") } },
4073         { "en@calendar=chinese",      DateFormat::kLong,  { UnicodeString("Fourth Month 2, 2012(ren-chen)"), UnicodeString("Fourth Monthbis 2, 2012(ren-chen)"), UnicodeString("Fifth Month 2, 2012(ren-chen)") } },
4074         { "en@calendar=chinese",      DateFormat::kShort, { UnicodeString("4/2/2012"),      UnicodeString("4bis/2/2012"),           UnicodeString("5/2/2012") } },
4075         { "zh@calendar=chinese",      DateFormat::kLong,  { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4076                                                             CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u95F0\\u56DB\\u6708\\u521D\\u4E8C"),
4077                                                             CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4078         { "zh@calendar=chinese",      DateFormat::kShort, { CharsToUnicodeString("2012/4/2"),
4079                                                             CharsToUnicodeString("2012/\\u95F04/2"),
4080                                                             CharsToUnicodeString("2012/5/2") } },
4081         { "zh@calendar=chinese",      -3,                 { CharsToUnicodeString("\\u58EC\\u8FB0-4-2"),
4082                                                             CharsToUnicodeString("\\u58EC\\u8FB0-\\u95F04-2"),
4083                                                             CharsToUnicodeString("\\u58EC\\u8FB0-5-2") } },
4084         { "zh@calendar=chinese",      -4,                 { CharsToUnicodeString("\\u58EC\\u8FB0 \\u56DB\\u6708 2"),
4085                                                             CharsToUnicodeString("\\u58EC\\u8FB0 \\u95F0\\u56DB\\u6708 2"),
4086                                                             CharsToUnicodeString("\\u58EC\\u8FB0 \\u4E94\\u6708 2") } },
4087         { "zh_Hant@calendar=chinese", DateFormat::kLong,  { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4088                                                             CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u958F\\u56DB\\u6708\\u521D\\u4E8C"),
4089                                                             CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4090         { "zh_Hant@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("2012/4/2"),
4091                                                             CharsToUnicodeString("2012/\\u958F4/2"),
4092                                                             CharsToUnicodeString("2012/5/2") } },
4093         { "fr@calendar=chinese",      DateFormat::kLong,  { CharsToUnicodeString("2 s\\u00ECyu\\u00E8 ren-chen"),
4094                                                             CharsToUnicodeString("2 s\\u00ECyu\\u00E8bis ren-chen"),
4095                                                             CharsToUnicodeString("2 w\\u01D4yu\\u00E8 ren-chen") } },
4096         { "fr@calendar=chinese",      DateFormat::kShort, { UnicodeString("2/4/29"),        UnicodeString("2/4bis/29"),             UnicodeString("2/5/29") } },
4097         { "en@calendar=dangi",        DateFormat::kLong,  { UnicodeString("Third Monthbis 2, 2012(ren-chen)"),  UnicodeString("Fourth Month 2, 2012(ren-chen)"),       UnicodeString("Fifth Month 1, 2012(ren-chen)") } },
4098         { "en@calendar=dangi",        DateFormat::kShort, { UnicodeString("3bis/2/2012"),   UnicodeString("4/2/2012"),              UnicodeString("5/1/2012") } },
4099         { "en@calendar=dangi",        -2,                 { UnicodeString("78x29-3bis-2"),  UnicodeString("78x29-4-2"),             UnicodeString("78x29-5-1") } },
4100         { "ko@calendar=dangi",        DateFormat::kLong,  { CharsToUnicodeString("\\uC784\\uC9C4\\uB144 \\uC7243\\uC6D4 2\\uC77C"),
4101                                                             CharsToUnicodeString("\\uC784\\uC9C4\\uB144 4\\uC6D4 2\\uC77C"),
4102                                                             CharsToUnicodeString("\\uC784\\uC9C4\\uB144 5\\uC6D4 1\\uC77C") } },
4103         { "ko@calendar=dangi",        DateFormat::kShort, { CharsToUnicodeString("29. \\uC7243. 2."),
4104                                                             CharsToUnicodeString("29. 4. 2."),
4105                                                             CharsToUnicodeString("29. 5. 1.") } },
4106         // terminator
4107         { NULL,                       0,                  { UnicodeString(""), UnicodeString(""), UnicodeString("") } }
4108     };
4109
4110     //.                               style: -1        -2            -3       -4
4111     const UnicodeString customPatterns[] = { "y-Ml-d", "G'x'y-Ml-d", "U-M-d", "U MMM d" }; // like old root pattern, using 'l'
4112
4113     UErrorCode status = U_ZERO_ERROR;
4114     Locale rootChineseCalLocale = Locale::createFromName("root@calendar=chinese");
4115     Calendar * rootChineseCalendar = Calendar::createInstance(rootChineseCalLocale, status);
4116     if (U_SUCCESS(status)) {
4117         const MonthPatternItem * itemPtr;
4118         for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4119             Locale locale = Locale::createFromName(itemPtr->locale);
4120             DateFormat * dmft = (itemPtr->style >= 0)?
4121                     DateFormat::createDateInstance((DateFormat::EStyle)itemPtr->style, locale):
4122                     new SimpleDateFormat(customPatterns[-itemPtr->style - 1], locale, status);
4123             if ( dmft != NULL ) {
4124                 if (U_SUCCESS(status)) {
4125                     const ChineseCalTestDate * datePtr = dates;
4126                     int32_t idate;
4127                     for (idate = 0; idate < NUM_TEST_DATES; idate++, datePtr++) {
4128                         rootChineseCalendar->clear();
4129                         rootChineseCalendar->set(UCAL_ERA, datePtr->era);
4130                         rootChineseCalendar->set(datePtr->year, datePtr->month-1, datePtr->day);
4131                         rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, datePtr->isLeapMonth);
4132                         UnicodeString result;
4133                         FieldPosition fpos(FieldPosition::DONT_CARE);
4134                         dmft->format(*rootChineseCalendar, result, fpos);
4135                         if ( result.compare(itemPtr->dateString[idate]) != 0 ) {
4136                             errln( UnicodeString("FAIL: Chinese calendar format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4137                                     ", expected \"" + itemPtr->dateString[idate] + "\", got \"" + result + "\"");
4138                         } else {
4139                             // formatted OK, try parse
4140                             ParsePosition ppos(0);
4141                             // ensure we are really parsing the fields we should be
4142                             rootChineseCalendar->set(UCAL_YEAR, 1);
4143                             rootChineseCalendar->set(UCAL_MONTH, 0);
4144                             rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, 0);
4145                             rootChineseCalendar->set(UCAL_DATE, 1);
4146                             //
4147                             dmft->parse(result, *rootChineseCalendar, ppos);
4148                             int32_t year = rootChineseCalendar->get(UCAL_YEAR, status);
4149                             int32_t month = rootChineseCalendar->get(UCAL_MONTH, status) + 1;
4150                             int32_t isLeapMonth = rootChineseCalendar->get(UCAL_IS_LEAP_MONTH, status);
4151                             int32_t day = rootChineseCalendar->get(UCAL_DATE, status);
4152                             if ( ppos.getIndex() < result.length() || year != datePtr->year || month != datePtr->month || isLeapMonth != datePtr->isLeapMonth || day != datePtr->day ) {
4153                                 errln( UnicodeString("FAIL: Chinese calendar parse for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4154                                     ", string \"" + result + "\", expected " + datePtr->year +"-"+datePtr->month+"("+datePtr->isLeapMonth+")-"+datePtr->day + ", got pos " +
4155                                     ppos.getIndex() + " " + year +"-"+month+"("+isLeapMonth+")-"+day);
4156                             }
4157                         }
4158                     }
4159                 } else {
4160                     dataerrln("Error creating SimpleDateFormat for Chinese calendar- %s", u_errorName(status));
4161                 }
4162                 delete dmft;
4163             } else {
4164                 dataerrln("FAIL: Unable to create DateFormat for Chinese calendar- %s", u_errorName(status));
4165             }
4166         }
4167         delete rootChineseCalendar;
4168     } else {
4169         errln(UnicodeString("FAIL: Unable to create Calendar for root@calendar=chinese"));
4170     }
4171 }
4172
4173 typedef struct {
4174     const char * locale;
4175     UnicodeString pattern;
4176     UDisplayContext capitalizationContext;
4177     UnicodeString expectedFormat;
4178 } TestContextItem;
4179
4180 void DateFormatTest::TestContext()
4181 {
4182     const UDate july022008 = 1215000001979.0;
4183     const TestContextItem items[] = {
4184         //locale              pattern    capitalizationContext                              expected formatted date
4185         { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_NONE,                      UnicodeString("juillet 2008") },
4186 #if !UCONFIG_NO_BREAK_ITERATION
4187         { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    UnicodeString("juillet 2008") },
4188         { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, UnicodeString("Juillet 2008") },
4189         { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU,       UnicodeString("juillet 2008") },
4190         { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE,            UnicodeString("Juillet 2008") },
4191 #endif
4192         { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_NONE,                      CharsToUnicodeString("\\u010Dervenec 2008") },
4193 #if !UCONFIG_NO_BREAK_ITERATION
4194         { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    CharsToUnicodeString("\\u010Dervenec 2008") },
4195         { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, CharsToUnicodeString("\\u010Cervenec 2008") },
4196         { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU,       CharsToUnicodeString("\\u010Cervenec 2008") },
4197         { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE,            CharsToUnicodeString("\\u010Dervenec 2008") },
4198 #endif
4199         // terminator
4200         { NULL, UnicodeString(""),       (UDisplayContext)0, UnicodeString("") }
4201     };
4202     UErrorCode status = U_ZERO_ERROR;
4203     Calendar* cal = Calendar::createInstance(status);
4204     if (U_FAILURE(status)) {
4205         dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4206     } else {
4207         cal->setTime(july022008, status);
4208         const TestContextItem * itemPtr;
4209         for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4210            Locale locale = Locale::createFromName(itemPtr->locale);
4211            status = U_ZERO_ERROR;
4212            SimpleDateFormat * sdmft = new SimpleDateFormat(itemPtr->pattern, locale, status);
4213            if (U_FAILURE(status)) {
4214                 dataerrln(UnicodeString("FAIL: Unable to create SimpleDateFormat for specified pattern with locale ") + UnicodeString(itemPtr->locale));
4215            } else {
4216                sdmft->setContext(itemPtr->capitalizationContext, status);
4217                UnicodeString result;
4218                FieldPosition pos(FieldPosition::DONT_CARE);
4219                sdmft->format(*cal, result, pos);
4220                if (result.compare(itemPtr->expectedFormat) != 0) {
4221                    errln(UnicodeString("FAIL: format for locale ") + UnicodeString(itemPtr->locale) +
4222                            ", status " + (int)status +
4223                            ", capitalizationContext " + (int)itemPtr->capitalizationContext +
4224                            ", expected " + itemPtr->expectedFormat + ", got " + result);
4225                }
4226            }
4227            if (sdmft) {
4228                delete sdmft;
4229            }
4230         }
4231     }
4232     if (cal) {
4233         delete cal;
4234     }
4235 }
4236
4237 // test item for a particular locale + calendar and date format
4238 typedef struct {
4239     int32_t era;
4240     int32_t year;
4241     int32_t month;
4242     int32_t day;
4243     int32_t hour;
4244     int32_t minute;
4245     UnicodeString formattedDate;
4246 } CalAndFmtTestItem;
4247
4248 // test item giving locale + calendar, date format, and CalAndFmtTestItems
4249 typedef struct {
4250     const char * locale; // with calendar
4251     DateFormat::EStyle style;
4252     UnicodeString pattern; // ignored unless style == DateFormat::kNone
4253     const CalAndFmtTestItem *caftItems;
4254 } TestNonGregoItem;
4255
4256 void DateFormatTest::TestNonGregoFmtParse()
4257 {
4258     // test items for he@calendar=hebrew, long date format
4259     const CalAndFmtTestItem cafti_he_hebrew_long[] = {
4260         {  0, 4999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05D3\\u05F3\\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4261         {  0, 5100,  0,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05E7\\u05F3") },
4262         {  0, 5774,  5,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05D0\\u05D3\\u05E8 \\u05D0\\u05F3 \\u05EA\\u05E9\\u05E2\\u05F4\\u05D3") },
4263         {  0, 5999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4264         {  0, 6100,  0,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05D5\\u05F3\\u05E7\\u05F3") },
4265         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4266     };
4267     const CalAndFmtTestItem cafti_zh_chinese_custU[] = {
4268         { 78,   31,  0,  1, 12, 0, CharsToUnicodeString("2014\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4269         { 77,   31,  0,  1, 12, 0, CharsToUnicodeString("1954\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4270         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4271     };
4272     const CalAndFmtTestItem cafti_zh_chinese_custNoU[] = {
4273         { 78,   31,  0,  1, 12, 0, CharsToUnicodeString("2014\\u5E74\\u6B63\\u67081") },
4274         { 77,   31,  0,  1, 12, 0, CharsToUnicodeString("1954\\u5E74\\u6B63\\u67081") },
4275         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4276     };
4277     const CalAndFmtTestItem cafti_ja_japanese_custGy[] = {
4278         {235,   26,  2,  5, 12, 0, CharsToUnicodeString("2014(\\u5E73\\u621026)\\u5E743\\u67085\\u65E5") },
4279         {234,   60,  2,  5, 12, 0, CharsToUnicodeString("1985(\\u662D\\u548C60)\\u5E743\\u67085\\u65E5") },
4280         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4281     };
4282     const CalAndFmtTestItem cafti_ja_japanese_custNoGy[] = {
4283         {235,   26,  2,  5, 12, 0, CharsToUnicodeString("2014\\u5E743\\u67085\\u65E5") },
4284         {234,   60,  2,  5, 12, 0, CharsToUnicodeString("1985\\u5E743\\u67085\\u65E5") },
4285         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4286     };
4287     const CalAndFmtTestItem cafti_en_islamic_cust[] = {
4288         {  0, 1384,  0,  1, 12, 0, UnicodeString("1 Muh. 1384 AH, 1964") },
4289         {  0, 1436,  0,  1, 12, 0, UnicodeString("1 Muh. 1436 AH, 2014") },
4290         {  0, 1487,  0,  1, 12, 0, UnicodeString("1 Muh. 1487 AH, 2064") },
4291         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4292     };
4293     // overal test items
4294     const TestNonGregoItem items[] = {
4295         { "he@calendar=hebrew",   DateFormat::kLong, UnicodeString(""),                 cafti_he_hebrew_long },
4296         { "zh@calendar=chinese",  DateFormat::kNone, CharsToUnicodeString("rU\\u5E74MMMd"),                cafti_zh_chinese_custU },
4297         { "zh@calendar=chinese",  DateFormat::kNone, CharsToUnicodeString("r\\u5E74MMMd"),                 cafti_zh_chinese_custNoU },
4298         { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r(Gy)\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custGy },
4299         { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74M\\u6708d\\u65E5"),     cafti_ja_japanese_custNoGy },
4300         { "en@calendar=islamic",  DateFormat::kNone, UnicodeString("d MMM y G, r"),     cafti_en_islamic_cust },
4301         { NULL, DateFormat::kNone, UnicodeString(""), NULL } // terminator
4302     };
4303     const TestNonGregoItem * itemPtr;
4304     for (itemPtr = items; itemPtr->locale != NULL; itemPtr++) {
4305         Locale locale = Locale::createFromName(itemPtr->locale);
4306         DateFormat * dfmt = NULL;
4307         UErrorCode status = U_ZERO_ERROR;
4308         if (itemPtr->style != DateFormat::kNone) {
4309             dfmt = DateFormat::createDateInstance(itemPtr->style, locale);
4310         } else {
4311             dfmt = new SimpleDateFormat(itemPtr->pattern, locale, status);
4312         }
4313         if (U_FAILURE(status)) {
4314             dataerrln("new SimpleDateFormat fails for locale %s", itemPtr->locale);
4315         } else  if (dfmt == NULL) {
4316             dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->locale);
4317         } else {
4318             Calendar * cal = (dfmt->getCalendar())->clone();
4319             if (cal == NULL) {
4320                 dataerrln("(DateFormat::getCalendar)->clone() fails for locale %s", itemPtr->locale);
4321             } else {
4322                 const CalAndFmtTestItem * caftItemPtr;
4323                 for (caftItemPtr = itemPtr->caftItems; caftItemPtr->year != 0; caftItemPtr++) {
4324                     cal->clear();
4325                     cal->set(UCAL_ERA,    caftItemPtr->era);
4326                     cal->set(UCAL_YEAR,   caftItemPtr->year);
4327                     cal->set(UCAL_MONTH,  caftItemPtr->month);
4328                     cal->set(UCAL_DATE,   caftItemPtr->day);
4329                     cal->set(UCAL_HOUR_OF_DAY, caftItemPtr->hour);
4330                     cal->set(UCAL_MINUTE, caftItemPtr->minute);
4331                     UnicodeString result;
4332                     FieldPosition fpos(FieldPosition::DONT_CARE);
4333                     dfmt->format(*cal, result, fpos);
4334                     if ( result.compare(caftItemPtr->formattedDate) != 0 ) {
4335                         errln( UnicodeString("FAIL: date format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4336                                 ", expected \"" + caftItemPtr->formattedDate + "\", got \"" + result + "\"");
4337                     } else {
4338                         // formatted OK, try parse
4339                         ParsePosition ppos(0);
4340                         dfmt->parse(result, *cal, ppos);
4341                         status = U_ZERO_ERROR;
4342                         int32_t era = cal->get(UCAL_ERA, status);
4343                         int32_t year = cal->get(UCAL_YEAR, status);
4344                         int32_t month = cal->get(UCAL_MONTH, status);
4345                         int32_t day = cal->get(UCAL_DATE, status);
4346                         if ( U_FAILURE(status) || ppos.getIndex() < result.length() || era != caftItemPtr->era ||
4347                                 year != caftItemPtr->year || month != caftItemPtr->month || day != caftItemPtr->day ) {
4348                             errln( UnicodeString("FAIL: date parse for locale ") + UnicodeString(itemPtr->locale) +
4349                                 ", style " + itemPtr->style + ", string \"" + result + "\", expected " +
4350                                 caftItemPtr->era +":"+caftItemPtr->year +"-"+caftItemPtr->month+"-"+caftItemPtr->day + ", got pos " +
4351                                 ppos.getIndex() + " " + year +"-"+month+"-"+day + " status " + UnicodeString(u_errorName(status)) );
4352                         }
4353                     }
4354                 }
4355                 delete cal;
4356             }
4357             delete dfmt;
4358         }
4359     }
4360 }
4361
4362 typedef struct {
4363     const char*         localeID;
4364     DateFormat::EStyle  style;
4365     UnicodeString       expectPattern;
4366     UnicodeString       expectFormat;
4367 } TestFmtWithNumSysItem;
4368 enum { kBBufMax = 128 };
4369 void DateFormatTest::TestFormatsWithNumberSystems()
4370 {
4371     LocalPointer<TimeZone> zone(TimeZone::createTimeZone(UnicodeString("UTC")));
4372     const UDate date = 1451556000000.0; // for UTC: grego 31-Dec-2015 10 AM, hebrew 19 tevet 5776, chinese yi-wei 11mo 21day
4373     const TestFmtWithNumSysItem items[] = {
4374         { "haw@calendar=gregorian", DateFormat::kShort, UnicodeString("d/M/yy"),               UnicodeString("31/xii/15") },
4375         { "he@calendar=hebrew",     DateFormat::kLong, CharsToUnicodeString("d \\u05D1MMMM y"), CharsToUnicodeString("\\u05D9\\u05F4\\u05D8 \\u05D1\\u05D8\\u05D1\\u05EA \\u05EA\\u05E9\\u05E2\\u05F4\\u05D5") }, 
4376         { "zh@calendar=chinese",      DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u5341\\u4E00\\u6708\\u5EFF\\u4E00") },
4377         { "zh_Hant@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u51AC\\u6708\\u5EFF\\u4E00") },
4378         { "ja@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("U\\u5E74MMMd\\u65E5"), CharsToUnicodeString("\\u4E59\\u672A\\u5E74\\u5341\\u4E00\\u6708\\u4E8C\\u4E00\\u65E5") },
4379         { NULL, DateFormat::kNone, UnicodeString(""), UnicodeString("") },
4380     };
4381     const TestFmtWithNumSysItem * itemPtr;
4382     for (itemPtr = items; itemPtr->localeID != NULL; itemPtr++) {
4383         char bExpected[kBBufMax];
4384         char bResult[kBBufMax];
4385         UErrorCode status = U_ZERO_ERROR;
4386         Locale locale = Locale::createFromName(itemPtr->localeID);
4387         LocalPointer<Calendar> cal(Calendar::createInstance(zone.orphan(), locale, status));
4388         if (U_FAILURE(status)) {
4389             dataerrln("Calendar::createInstance fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4390             continue;
4391         }
4392         cal->setTime(date, status);
4393         if (U_FAILURE(status)) {
4394             dataerrln("Calendar::setTime fails for locale %s, date %.1f, status %s", itemPtr->localeID, date, u_errorName(status));
4395             continue;
4396         }
4397         LocalPointer<SimpleDateFormat> sdfmt(static_cast<SimpleDateFormat *>(DateFormat::createDateInstance(itemPtr->style, locale)));
4398         if (sdfmt.isNull()) {
4399             dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->localeID);
4400             continue;
4401         }
4402         UnicodeString getFormat;
4403         sdfmt->format(*(cal.getAlias()), getFormat, NULL, status);
4404         if (U_FAILURE(status)) {
4405             errln("DateFormat::format fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4406             continue;
4407         }
4408         if (getFormat.compare(itemPtr->expectFormat) != 0) {
4409             itemPtr->expectFormat.extract(0, itemPtr->expectFormat.length(), bExpected, kBBufMax);
4410             getFormat.extract(0, getFormat.length(), bResult, kBBufMax);
4411             errln("DateFormat::format for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4412         }
4413         UnicodeString getPattern;
4414         sdfmt->toPattern(getPattern);
4415         if (getPattern.compare(itemPtr->expectPattern) != 0) {
4416             itemPtr->expectPattern.extract(0, itemPtr->expectPattern.length(), bExpected, kBBufMax);
4417             getPattern.extract(0, getPattern.length(), bResult, kBBufMax);
4418             errln("DateFormat::toPattern() for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4419         }
4420     }
4421 }
4422
4423 static const UDate TEST_DATE = 1326585600000.;  // 2012-jan-15
4424
4425 void DateFormatTest::TestDotAndAtLeniency() {
4426     // Test for date/time parsing regression with CLDR 22.1/ICU 50 pattern strings.
4427     // For details see http://bugs.icu-project.org/trac/ticket/9789
4428     static const char *locales[] = { "en", "fr" };
4429     for (int32_t i = 0; i < UPRV_LENGTHOF(locales); ++i) {
4430         Locale locale(locales[i]);
4431
4432         for (DateFormat::EStyle dateStyle = DateFormat::FULL; dateStyle <= DateFormat::SHORT;
4433                   dateStyle = static_cast<DateFormat::EStyle>(dateStyle + 1)) {
4434             LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance(dateStyle, locale));
4435
4436             for (DateFormat::EStyle timeStyle = DateFormat::FULL; timeStyle <= DateFormat::SHORT;
4437                       timeStyle = static_cast<DateFormat::EStyle>(timeStyle + 1)) {
4438                 LocalPointer<DateFormat> format(DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale));
4439                 LocalPointer<DateFormat> timeFormat(DateFormat::createTimeInstance(timeStyle, locale));
4440                 UnicodeString formattedString;
4441                 if (format.isNull()) {
4442                     dataerrln("Unable to create DateFormat");
4443                     continue;
4444                 }
4445                 format->format(TEST_DATE, formattedString);
4446
4447                 if (!showParse(*format, formattedString)) {
4448                     errln(UnicodeString("    with date-time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4449                 }
4450
4451                 UnicodeString ds, ts;
4452                 formattedString = dateFormat->format(TEST_DATE, ds) + "  " + timeFormat->format(TEST_DATE, ts);
4453                 if (!showParse(*format, formattedString)) {
4454                     errln(UnicodeString("    with date sp sp time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4455                 }
4456                 if (formattedString.indexOf("n ") >= 0) { // will add "." after the end of text ending in 'n', like Jan.
4457                     UnicodeString plusDot(formattedString);
4458                     plusDot.findAndReplace("n ", "n. ").append(".");
4459                     if (!showParse(*format, plusDot)) {
4460                         errln(UnicodeString("    with date plus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4461                     }
4462                 }
4463                 if (formattedString.indexOf(". ") >= 0) { // will subtract "." at the end of strings.
4464                     UnicodeString minusDot(formattedString);
4465                     minusDot.findAndReplace(". ", " ");
4466                     if (!showParse(*format, minusDot)) {
4467                         errln(UnicodeString("    with date minus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4468                     }
4469                 }
4470             }
4471         }
4472     }
4473 }
4474
4475 UBool DateFormatTest::showParse(DateFormat &format, const UnicodeString &formattedString) {
4476     ParsePosition parsePosition;
4477     UDate parsed = format.parse(formattedString, parsePosition);
4478     UBool ok = TEST_DATE == parsed && parsePosition.getIndex() == formattedString.length();
4479     UnicodeString pattern;
4480     static_cast<SimpleDateFormat &>(format).toPattern(pattern);
4481     if (ok) {
4482         logln(pattern + "  parsed: " + formattedString);
4483     } else {
4484         errln(pattern + "  fails to parse: " + formattedString);
4485     }
4486     return ok;
4487 }
4488
4489
4490 typedef struct {
4491     const char * locale;
4492     UBool leniency;
4493     UnicodeString parseString;
4494     UnicodeString pattern;
4495     UnicodeString expectedResult;       // empty string indicates expected error
4496 } TestDateFormatLeniencyItem;
4497
4498 void DateFormatTest::TestDateFormatLeniency() {
4499     // For details see http://bugs.icu-project.org/trac/ticket/10261
4500
4501     const UDate july022008 = 1215000001979.0;
4502     const TestDateFormatLeniencyItem items[] = {
4503         //locale    leniency    parse String                    pattern                             expected result
4504         { "en",     true,       UnicodeString("2008-07 02"),    UnicodeString("yyyy-LLLL dd"),      UnicodeString("2008-July 02") },
4505         { "en",     false,      UnicodeString("2008-07 02"),    UnicodeString("yyyy-LLLL dd"),      UnicodeString("") },
4506         { "en",     true,       UnicodeString("2008-Jan 02"),   UnicodeString("yyyy-LLL. dd"),      UnicodeString("2008-Jan. 02") },
4507         { "en",     false,      UnicodeString("2008-Jan 02"),   UnicodeString("yyyy-LLL. dd"),      UnicodeString("") },
4508         { "en",     true,       UnicodeString("2008-Jan--02"),  UnicodeString("yyyy-MMM' -- 'dd"),  UnicodeString("2008-Jan -- 02") },
4509         { "en",     false,      UnicodeString("2008-Jan--02"),  UnicodeString("yyyy-MMM' -- 'dd"),  UnicodeString("") },
4510         // terminator
4511         { NULL,     true,       UnicodeString(""),              UnicodeString(""),                  UnicodeString("") }
4512     };
4513     UErrorCode status = U_ZERO_ERROR;
4514     LocalPointer<Calendar> cal(Calendar::createInstance(status));
4515     if (U_FAILURE(status)) {
4516         dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4517         return;
4518     }
4519     cal->setTime(july022008, status);
4520     const TestDateFormatLeniencyItem * itemPtr;
4521     LocalPointer<SimpleDateFormat> sdmft;
4522     for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4523
4524        Locale locale = Locale::createFromName(itemPtr->locale);
4525        status = U_ZERO_ERROR;
4526        ParsePosition pos(0);
4527        sdmft.adoptInsteadAndCheckErrorCode(new SimpleDateFormat(itemPtr->pattern, locale, status), status);
4528        if (U_FAILURE(status)) {
4529            dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4530            continue;
4531        }
4532        sdmft->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->leniency, status).
4533               setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->leniency, status).
4534               setBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, itemPtr->leniency, status);
4535        UDate d = sdmft->parse(itemPtr->parseString, pos);
4536
4537        if(itemPtr->expectedResult.length() == 0) {
4538            if(pos.getErrorIndex() != -1) {
4539                continue;
4540            } else {
4541                 errln("error: unexpected parse success - " + itemPtr->parseString +
4542                     " - pattern " + itemPtr->pattern +
4543                     " - error index " + pos.getErrorIndex() +
4544                     " - leniency " + itemPtr->leniency);
4545                 continue;
4546            }
4547        }
4548        if(pos.getErrorIndex() != -1) {
4549            errln("error: parse error for string - "  + itemPtr->parseString +
4550                  " - pattern " + itemPtr->pattern +
4551                  " - idx " + pos.getIndex() +
4552                  " - error index "+pos.getErrorIndex() +
4553                  " - leniency " + itemPtr->leniency);
4554             continue;
4555         }
4556
4557        UnicodeString formatResult("");
4558        sdmft->format(d, formatResult);
4559        if(formatResult.compare(itemPtr->expectedResult) != 0) {
4560            errln("error: unexpected format result. pattern["+itemPtr->pattern+"] expected[" + itemPtr->expectedResult + "]  but result was[" + formatResult + "]");
4561            continue;
4562         } else {
4563             logln("formatted results match! - " + formatResult);
4564         }
4565
4566     }
4567 }
4568
4569
4570 typedef struct {
4571     UBool leniency;
4572     UnicodeString parseString;
4573     UnicodeString pattern;
4574     UnicodeString expectedResult;       // empty string indicates expected error
4575 } TestMultiPatternMatchItem;
4576
4577 void DateFormatTest::TestParseMultiPatternMatch() {
4578         // For details see http://bugs.icu-project.org/trac/ticket/10336
4579     const TestMultiPatternMatchItem items[] = {
4580           // leniency    parse String                                 pattern                               expected result
4581             {true,       UnicodeString("2013-Sep 13"),                UnicodeString("yyyy-MMM dd"),         UnicodeString("2013-Sep 13")},
4582             {true,       UnicodeString("2013-September 14"),          UnicodeString("yyyy-MMM dd"),         UnicodeString("2013-Sep 14")},
4583             {false,      UnicodeString("2013-September 15"),          UnicodeString("yyyy-MMM dd"),         UnicodeString("")},
4584             {false,      UnicodeString("2013-September 16"),          UnicodeString("yyyy-MMMM dd"),        UnicodeString("2013-September 16")},
4585             {true,       UnicodeString("2013-Sep 17"),                UnicodeString("yyyy-LLL dd"),         UnicodeString("2013-Sep 17")},
4586             {true,       UnicodeString("2013-September 18"),          UnicodeString("yyyy-LLL dd"),         UnicodeString("2013-Sep 18")},
4587             {false,      UnicodeString("2013-September 19"),          UnicodeString("yyyy-LLL dd"),         UnicodeString("")},
4588             {false,      UnicodeString("2013-September 20"),          UnicodeString("yyyy-LLLL dd"),        UnicodeString("2013-September 20")},
4589             {true,       UnicodeString("2013 Sat Sep 21"),            UnicodeString("yyyy EEE MMM dd"),     UnicodeString("2013 Sat Sep 21")},
4590             {true,       UnicodeString("2013 Sunday Sep 22"),         UnicodeString("yyyy EEE MMM dd"),     UnicodeString("2013 Sun Sep 22")},
4591             {false,      UnicodeString("2013 Monday Sep 23"),         UnicodeString("yyyy EEE MMM dd"),     UnicodeString("")},
4592             {false,      UnicodeString("2013 Tuesday Sep 24"),        UnicodeString("yyyy EEEE MMM dd"),    UnicodeString("2013 Tuesday Sep 24")},
4593             {true,       UnicodeString("2013 Wed Sep 25"),            UnicodeString("yyyy eee MMM dd"),     UnicodeString("2013 Wed Sep 25")},
4594             {true,       UnicodeString("2013 Thu Sep 26"),            UnicodeString("yyyy eee MMM dd"),     UnicodeString("2013 Thu Sep 26")},
4595             {false,      UnicodeString("2013 Friday Sep 27"),         UnicodeString("yyyy eee MMM dd"),     UnicodeString("")},
4596             {false,      UnicodeString("2013 Saturday Sep 28"),       UnicodeString("yyyy eeee MMM dd"),    UnicodeString("2013 Saturday Sep 28")},
4597             {true,       UnicodeString("2013 Sun Sep 29"),            UnicodeString("yyyy ccc MMM dd"),     UnicodeString("2013 Sun Sep 29")},
4598             {true,       UnicodeString("2013 Monday Sep 30"),         UnicodeString("yyyy ccc MMM dd"),     UnicodeString("2013 Mon Sep 30")},
4599             {false,      UnicodeString("2013 Sunday Oct 13"),         UnicodeString("yyyy ccc MMM dd"),     UnicodeString("")},
4600             {false,      UnicodeString("2013 Monday Oct 14"),         UnicodeString("yyyy cccc MMM dd"),    UnicodeString("2013 Monday Oct 14")},
4601             {true,       UnicodeString("2013 Oct 15 Q4"),             UnicodeString("yyyy MMM dd QQQ"),     UnicodeString("2013 Oct 15 Q4")},
4602             {true,       UnicodeString("2013 Oct 16 4th quarter"),    UnicodeString("yyyy MMM dd QQQ"),     UnicodeString("2013 Oct 16 Q4")},
4603             {false,      UnicodeString("2013 Oct 17 4th quarter"),    UnicodeString("yyyy MMM dd QQQ"),     UnicodeString("")},
4604             {false,      UnicodeString("2013 Oct 18 Q4"),             UnicodeString("yyyy MMM dd QQQ"),     UnicodeString("2013 Oct 18 Q4")},
4605             {true,       UnicodeString("2013 Oct 19 Q4"),             UnicodeString("yyyy MMM dd qqqq"),    UnicodeString("2013 Oct 19 4th quarter")},
4606             {true,       UnicodeString("2013 Oct 20 4th quarter"),    UnicodeString("yyyy MMM dd qqqq"),    UnicodeString("2013 Oct 20 4th quarter")},
4607             {false,      UnicodeString("2013 Oct 21 Q4"),             UnicodeString("yyyy MMM dd qqqq"),    UnicodeString("")},
4608             {false,      UnicodeString("2013 Oct 22 4th quarter"),    UnicodeString("yyyy MMM dd qqqq"),    UnicodeString("2013 Oct 22 4th quarter")},
4609             {false,      UnicodeString("--end--"),                    UnicodeString(""),                    UnicodeString("")},
4610     };
4611
4612     UErrorCode status = U_ZERO_ERROR;
4613     LocalPointer<Calendar> cal(Calendar::createInstance(status));
4614     if (U_FAILURE(status)) {
4615         dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4616         return;
4617     }
4618     const TestMultiPatternMatchItem * itemPtr;
4619     DateFormat* sdmft = DateFormat::createDateInstance();
4620     if (sdmft == NULL) {
4621         dataerrln(UnicodeString("FAIL: Unable to create DateFormat"));
4622         return;
4623     }
4624     for (itemPtr = items; itemPtr->parseString != "--end--"; itemPtr++ ) {
4625        status = U_ZERO_ERROR;
4626        ParsePosition pos(0);
4627        ((SimpleDateFormat*) sdmft)->applyPattern(itemPtr->pattern);
4628        if (U_FAILURE(status)) {
4629            dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4630            continue;
4631        }
4632        sdmft->setBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, itemPtr->leniency, status);
4633        UDate d = sdmft->parse(itemPtr->parseString, pos);
4634
4635        if(itemPtr->expectedResult.length() == 0) {
4636            if(pos.getErrorIndex() != -1) {
4637                continue;
4638            } else {
4639                 errln("error: unexpected parse success - " + itemPtr->parseString +
4640                     " - error index " + pos.getErrorIndex() +
4641                     " - leniency " + itemPtr->leniency);
4642                 continue;
4643            }
4644         }
4645         if(pos.getErrorIndex() != -1) {
4646             errln("error: parse error for string - " +itemPtr->parseString + " -- idx["+pos.getIndex()+"] errIdx["+pos.getErrorIndex()+"]");
4647             continue;
4648         }
4649
4650         UnicodeString formatResult("");
4651         sdmft->format(d, formatResult);
4652         if(formatResult.compare(itemPtr->expectedResult) != 0) {
4653             errln("error: unexpected format result. expected[" + itemPtr->expectedResult + "]  but result was[" + formatResult + "]");
4654         } else {
4655             logln("formatted results match! - " + formatResult);
4656         }
4657     }
4658     delete sdmft;
4659 }
4660
4661 void DateFormatTest::TestParseLeniencyAPIs() {
4662     UErrorCode status = U_ZERO_ERROR;
4663     LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance());
4664     DateFormat *fmt = dateFormat.getAlias();
4665     if (fmt == NULL) {
4666         dataerrln("Failed calling dateFormat.getAlias()");
4667         return;
4668     }
4669
4670     assertTrue("isLenient default", fmt->isLenient());
4671     assertTrue("isCalendarLenient default", fmt->isCalendarLenient());
4672     assertTrue("ALLOW_WHITESPACE default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4673     assertTrue("ALLOW_NUMERIC default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4674     assertTrue("PARTIAL_MATCH default", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4675     assertTrue("MULTIPLE_PATTERNS default", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4676
4677     // Set calendar to strict
4678     fmt->setCalendarLenient(FALSE);
4679
4680     assertFalse("isLeninent after setCalendarLenient(FALSE)", fmt->isLenient());
4681     assertFalse("isCalendarLenient after setCalendarLenient(FALSE)", fmt->isCalendarLenient());
4682     assertTrue("ALLOW_WHITESPACE after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4683     assertTrue("ALLOW_NUMERIC  after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4684
4685     // Set to strict
4686     fmt->setLenient(FALSE);
4687
4688     assertFalse("isLeninent after setLenient(FALSE)", fmt->isLenient());
4689     assertFalse("isCalendarLenient after setLenient(FALSE)", fmt->isCalendarLenient());
4690     assertFalse("ALLOW_WHITESPACE after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4691     assertFalse("ALLOW_NUMERIC  after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4692     // These two boolean attributes are NOT affected according to the API specification
4693     assertTrue("PARTIAL_MATCH after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4694     assertTrue("MULTIPLE_PATTERNS after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4695
4696     // Allow white space leniency
4697     fmt->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, TRUE, status);
4698
4699     assertFalse("isLeninent after ALLOW_WHITESPACE/TRUE", fmt->isLenient());
4700     assertFalse("isCalendarLenient after ALLOW_WHITESPACE/TRUE", fmt->isCalendarLenient());
4701     assertTrue("ALLOW_WHITESPACE after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4702     assertFalse("ALLOW_NUMERIC  after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4703
4704     // Set to lenient
4705     fmt->setLenient(TRUE);
4706
4707     assertTrue("isLenient after setLenient(TRUE)", fmt->isLenient());
4708     assertTrue("isCalendarLenient after setLenient(TRUE)", fmt->isCalendarLenient());
4709     assertTrue("ALLOW_WHITESPACE after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4710     assertTrue("ALLOW_NUMERIC after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4711 }
4712
4713 void DateFormatTest::TestNumberFormatOverride() {
4714     UErrorCode status = U_ZERO_ERROR;
4715     UnicodeString fields = (UnicodeString) "M";
4716
4717     LocalPointer<SimpleDateFormat> fmt;
4718     fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4719     if (!assertSuccess("SimpleDateFormat with pattern MM d", status)) {
4720         return;
4721     }
4722
4723
4724     for(int i=0; i<3; i++){
4725         NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4726         assertSuccess("NumberFormat en_US", status);
4727         fmt->adoptNumberFormat(fields, check_nf, status);
4728         assertSuccess("adoptNumberFormat check_nf", status);
4729
4730         const NumberFormat* get_nf = fmt->getNumberFormatForField((UChar)0x004D /*'M'*/);
4731         if (get_nf != check_nf) errln("FAIL: getter and setter do not work");
4732     }
4733     NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4734     assertSuccess("NumberFormat en_US", status);
4735     fmt->adoptNumberFormat(check_nf); // make sure using the same NF will not crash
4736
4737     const char * DATA [][2] = {
4738         { "", "\\u521D\\u516D \\u5341\\u4E94"},
4739         { "M", "\\u521D\\u516D 15"},
4740         { "Mo", "\\u521D\\u516D 15"},
4741         { "Md", "\\u521D\\u516D \\u5341\\u4E94"},
4742         { "MdMMd", "\\u521D\\u516D \\u5341\\u4E94"},
4743         { "mixed", "\\u521D\\u516D \\u5341\\u4E94"}
4744     };
4745
4746     UDate test_date = date(97, 6 - 1, 15);
4747
4748     for(int i=0; i < UPRV_LENGTHOF(DATA); i++){
4749         fields = DATA[i][0];
4750
4751         LocalPointer<SimpleDateFormat> fmt;
4752         fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4753         assertSuccess("SimpleDateFormat with pattern MM d", status);
4754         NumberFormat* overrideNF = NumberFormat::createInstance(Locale::createFromName("zh@numbers=hanidays"),status);
4755         assertSuccess("NumberFormat zh@numbers=hanidays", status);
4756
4757         if (fields == (UnicodeString) "") { // use the one w/o fields
4758             fmt->adoptNumberFormat(overrideNF);
4759         } else if (fields == (UnicodeString) "mixed") { // set 1 field at first but then full override, both(M & d) should be override
4760             NumberFormat* singleOverrideNF = NumberFormat::createInstance(Locale::createFromName("en@numbers=hebr"),status);
4761             assertSuccess("NumberFormat en@numbers=hebr", status);
4762
4763             fields = (UnicodeString) "M";
4764             fmt->adoptNumberFormat(fields, singleOverrideNF, status);
4765             assertSuccess("adoptNumberFormat singleOverrideNF", status);
4766
4767             fmt->adoptNumberFormat(overrideNF);
4768         } else if (fields == (UnicodeString) "Mo"){ // o is invlid field
4769             fmt->adoptNumberFormat(fields, overrideNF, status);
4770             if(status == U_INVALID_FORMAT_ERROR) {
4771                 status = U_ZERO_ERROR;
4772                 continue;
4773             }
4774         } else {
4775             fmt->adoptNumberFormat(fields, overrideNF, status);
4776             assertSuccess("adoptNumberFormat overrideNF", status);
4777         }
4778
4779         UnicodeString result;
4780         FieldPosition pos(FieldPosition::DONT_CARE);
4781         fmt->format(test_date,result, pos);
4782
4783         UnicodeString expected = ((UnicodeString)DATA[i][1]).unescape();;
4784
4785         if (result != expected)
4786             errln("FAIL: Expected " + expected + " get: " + result);
4787     }
4788 }
4789
4790 void DateFormatTest::TestCreateInstanceForSkeleton() {
4791     UErrorCode status = U_ZERO_ERROR;
4792     LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4793             "yMMMMd", "en", status));
4794     if (!assertSuccess("Create with pattern yMMMMd", status)) {
4795         return;
4796     }
4797     UnicodeString result;
4798     FieldPosition pos(FieldPosition::DONT_CARE);
4799     fmt->format(date(98, 5-1, 25), result, pos);
4800     assertEquals("format yMMMMd", "May 25, 1998", result);
4801     fmt.adoptInstead(DateFormat::createInstanceForSkeleton(
4802             "yMd", "en", status));
4803     if (!assertSuccess("Create with pattern yMd", status)) {
4804         return;
4805     }
4806     result.remove();
4807     fmt->format(date(98, 5-1, 25), result, pos);
4808     assertEquals("format yMd", "5/25/1998", result);
4809 }
4810
4811 void DateFormatTest::TestCreateInstanceForSkeletonDefault() {
4812     UErrorCode status = U_ZERO_ERROR;
4813     Locale savedLocale;
4814     Locale::setDefault(Locale::getUS(), status);
4815     LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4816             "yMMMd", status));
4817     Locale::setDefault(savedLocale, status);
4818     if (!assertSuccess("Create with pattern yMMMd", status)) {
4819         return;
4820     }
4821     UnicodeString result;
4822     FieldPosition pos(FieldPosition::DONT_CARE);
4823     fmt->format(date(98, 5-1, 25), result, pos);
4824     assertEquals("format yMMMd", "May 25, 1998", result);
4825 }
4826
4827 void DateFormatTest::TestCreateInstanceForSkeletonWithCalendar() {
4828     UErrorCode status = U_ZERO_ERROR;
4829     LocalPointer<DateFormat> fmt(
4830             DateFormat::createInstanceForSkeleton(
4831                     Calendar::createInstance(
4832                             TimeZone::createTimeZone("GMT-3:00"),
4833                             status),
4834                     "yMdHm", "en", status));
4835     if (!assertSuccess("Create with pattern yMMMMd", status)) {
4836         return;
4837     }
4838     UnicodeString result;
4839     FieldPosition pos(FieldPosition::DONT_CARE);
4840
4841     LocalPointer<Calendar> cal(Calendar::createInstance(
4842         TimeZone::createTimeZone("GMT-7:00"),
4843         status));
4844     if (!assertSuccess("Creating GMT-7 time zone failed", status)) {
4845         return;
4846     }
4847     cal->clear();
4848     cal->set(1998, 5-1, 25, 0, 0, 0);
4849
4850     // date format time zone should be 4 hours ahead.
4851     fmt->format(cal->getTime(status), result, pos);
4852     assertEquals("format yMdHm", "5/25/1998, 04:00", result);
4853     assertSuccess("", status);
4854 }
4855
4856 void DateFormatTest::TestDFSCreateForLocaleNonGregorianLocale() {
4857     UErrorCode status = U_ZERO_ERROR;
4858     Locale fa("fa");
4859     LocalPointer<DateFormatSymbols> sym(
4860             DateFormatSymbols::createForLocale(fa, status));
4861     if (!assertSuccess("", status)) {
4862         return;
4863     }
4864
4865     // Farsi should default to the persian calendar, not gregorian
4866     int32_t count;
4867     const UnicodeString *months = sym->getShortMonths(count);
4868
4869     // First persian month.
4870     UnicodeString expected("\\u0641\\u0631\\u0648\\u0631\\u062f\\u06cc\\u0646");
4871     assertEquals("", expected.unescape(), months[0]);
4872 }
4873
4874 void DateFormatTest::TestDFSCreateForLocaleWithCalendarInLocale() {
4875     UErrorCode status = U_ZERO_ERROR;
4876     Locale en_heb("en@calendar=hebrew");
4877     LocalPointer<DateFormatSymbols> sym(
4878             DateFormatSymbols::createForLocale(en_heb, status));
4879     if (!assertSuccess("", status)) {
4880         return;
4881     }
4882
4883     // We should get the months of the hebrew calendar, not the gregorian
4884     // calendar.
4885     int32_t count;
4886     const UnicodeString *months = sym->getShortMonths(count);
4887
4888     // First hebrew month.
4889     UnicodeString expected("Tishri");
4890     assertEquals("", expected, months[0]);
4891 }
4892
4893 void DateFormatTest::TestChangeCalendar() {
4894     UErrorCode status = U_ZERO_ERROR;
4895     Locale en("en");
4896     Locale en_heb("en@calendar=hebrew");
4897     LocalPointer<DateFormat> fmt(
4898             DateFormat::createInstanceForSkeleton("yMMMd", en, status));
4899     if (!assertSuccess("", status)) {
4900         return;
4901     }
4902     fmt->adoptCalendar(Calendar::createInstance(en_heb, status));
4903     if (!assertSuccess("", status)) {
4904         return;
4905     }
4906     UnicodeString result;
4907     FieldPosition pos(FieldPosition::DONT_CARE);
4908     fmt->format(date(98, 5-1, 25), result, pos);
4909     assertEquals("format yMMMd", "Iyar 29, 5758", result);
4910 }
4911
4912 void DateFormatTest::TestPatternFromSkeleton() {
4913     static const struct {
4914         const Locale& locale;
4915         const char* const skeleton;
4916         const char* const pattern;
4917     } TESTDATA[] = {
4918         // Ticket #11985
4919         {Locale::getEnglish(), "jjmm", "h:mm a"},
4920         {Locale::getEnglish(), "JJmm", "hh:mm"},
4921         {Locale::getGerman(), "jjmm", "HH:mm"},
4922         {Locale::getGerman(), "JJmm", "HH:mm"}
4923     };
4924
4925     for (size_t i = 0; i < UPRV_LENGTHOF(TESTDATA); i++) {
4926         UErrorCode status = U_ZERO_ERROR;
4927         LocalPointer<DateFormat> fmt(
4928                 DateFormat::createInstanceForSkeleton(
4929                         TESTDATA[i].skeleton, TESTDATA[i].locale, status));
4930         if (!assertSuccess("createInstanceForSkeleton", status)) {
4931             return;
4932         }
4933         UnicodeString pattern;
4934         static_cast<const SimpleDateFormat*>(fmt.getAlias())->toPattern(pattern);
4935         assertEquals("Format pattern", TESTDATA[i].pattern, pattern);
4936     }
4937 }
4938
4939 void DateFormatTest::TestAmPmMidnightNoon() {
4940     // Some times on 2015-11-13 (UTC+0).
4941     UDate k000000 = 1447372800000.0;
4942     UDate k000030 = 1447372830000.0;
4943     UDate k003000 = 1447374600000.0;
4944     UDate k060000 = 1447394400000.0;
4945     UDate k120000 = 1447416000000.0;
4946     UDate k180000 = 1447437600000.0;
4947
4948     UErrorCode errorCode = U_ZERO_ERROR;
4949     SimpleDateFormat sdf(UnicodeString(), errorCode);
4950     if (U_FAILURE(errorCode)) {
4951         dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
4952         return;
4953     }
4954     const TimeZone *tz = TimeZone::getGMT();
4955     sdf.setTimeZone(*tz);
4956     UnicodeString out;
4957
4958     // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
4959     // For ICU 57 output of "midnight" is temporarily suppressed.
4960
4961     // Short.
4962     sdf.applyPattern(UnicodeString("hh:mm:ss bbb"));
4963
4964     // assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4965     assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4966     assertEquals("hh:mm:ss bbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
4967     assertEquals("hh:mm:ss bbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
4968     assertEquals("hh:mm:ss bbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
4969     assertEquals("hh:mm:ss bbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
4970     assertEquals("hh:mm:ss bbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
4971
4972     sdf.applyPattern(UnicodeString("hh:mm bbb"));
4973
4974     // assertEquals("hh:mm bbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
4975     assertEquals("hh:mm bbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
4976     // assertEquals("hh:mm bbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
4977     assertEquals("hh:mm bbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
4978     assertEquals("hh:mm bbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
4979
4980     sdf.applyPattern(UnicodeString("hh bbb"));
4981
4982     // assertEquals("hh bbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
4983     assertEquals("hh bbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
4984     // assertEquals("hh bbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
4985     assertEquals("hh bbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
4986     // assertEquals("hh bbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
4987     assertEquals("hh bbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
4988
4989     // Wide.
4990     sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
4991
4992     // assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4993     assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4994     assertEquals("hh:mm:ss bbbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
4995     assertEquals("hh:mm:ss bbbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
4996     assertEquals("hh:mm:ss bbbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
4997     assertEquals("hh:mm:ss bbbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
4998     assertEquals("hh:mm:ss bbbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
4999
5000     sdf.applyPattern(UnicodeString("hh:mm bbbb"));
5001
5002     // assertEquals("hh:mm bbbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5003     assertEquals("hh:mm bbbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
5004     // assertEquals("hh:mm bbbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5005     assertEquals("hh:mm bbbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
5006     assertEquals("hh:mm bbbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
5007
5008     sdf.applyPattern(UnicodeString("hh bbbb"));
5009
5010     // assertEquals("hh bbbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5011     assertEquals("hh bbbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
5012     // assertEquals("hh bbbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5013     assertEquals("hh bbbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
5014     // assertEquals("hh bbbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5015     assertEquals("hh bbbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
5016
5017     // Narrow.
5018     sdf.applyPattern(UnicodeString("hh:mm:ss bbbbb"));
5019
5020     // assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5021     assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 a", sdf.format(k000000, out.remove()));
5022     assertEquals("hh:mm:ss bbbbb | 00:00:30", "12:00:30 a", sdf.format(k000030, out.remove()));
5023     assertEquals("hh:mm:ss bbbbb | 00:30:00", "12:30:00 a", sdf.format(k003000, out.remove()));
5024     assertEquals("hh:mm:ss bbbbb | 06:00:00", "06:00:00 a", sdf.format(k060000, out.remove()));
5025     assertEquals("hh:mm:ss bbbbb | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5026     assertEquals("hh:mm:ss bbbbb | 18:00:00", "06:00:00 p", sdf.format(k180000, out.remove()));
5027
5028     sdf.applyPattern(UnicodeString("hh:mm bbbbb"));
5029
5030     // assertEquals("hh:mm bbbbb | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5031     assertEquals("hh:mm bbbbb | 00:00:00", "12:00 a", sdf.format(k000000, out.remove()));
5032     // assertEquals("hh:mm bbbbb | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5033     assertEquals("hh:mm bbbbb | 00:00:30", "12:00 a", sdf.format(k000030, out.remove()));
5034     assertEquals("hh:mm bbbbb | 00:30:00", "12:30 a", sdf.format(k003000, out.remove()));
5035
5036     sdf.applyPattern(UnicodeString("hh bbbbb"));
5037
5038     // assertEquals("hh bbbbb | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5039     assertEquals("hh bbbbb | 00:00:00", "12 a", sdf.format(k000000, out.remove()));
5040     // assertEquals("hh bbbbb | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5041     assertEquals("hh bbbbb | 00:00:30", "12 a", sdf.format(k000030, out.remove()));
5042     // assertEquals("hh bbbbb | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5043     assertEquals("hh bbbbb | 00:30:00", "12 a", sdf.format(k003000, out.remove()));
5044 }
5045
5046 void DateFormatTest::TestFlexibleDayPeriod() {
5047     // Some times on 2015-11-13 (UTC+0).
5048     UDate k000000 = 1447372800000.0;
5049     UDate k000030 = 1447372830000.0;
5050     UDate k003000 = 1447374600000.0;
5051     UDate k060000 = 1447394400000.0;
5052     UDate k120000 = 1447416000000.0;
5053     UDate k180000 = 1447437600000.0;
5054
5055     UErrorCode errorCode = U_ZERO_ERROR;
5056     SimpleDateFormat sdf(UnicodeString(), errorCode);
5057     if (U_FAILURE(errorCode)) {
5058         dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5059         return;
5060     }
5061     const TimeZone *tz = TimeZone::getGMT();
5062     sdf.setTimeZone(*tz);
5063     UnicodeString out;
5064
5065     // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5066     // For ICU 57 output of "midnight" is temporarily suppressed.
5067
5068     // Short.
5069     sdf.applyPattern(UnicodeString("hh:mm:ss BBB"));
5070
5071     // assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5072     assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5073     assertEquals("hh:mm:ss BBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5074     assertEquals("hh:mm:ss BBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5075     assertEquals("hh:mm:ss BBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5076     assertEquals("hh:mm:ss BBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5077     assertEquals("hh:mm:ss BBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5078
5079     sdf.applyPattern(UnicodeString("hh:mm BBB"));
5080
5081     // assertEquals("hh:mm BBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5082     assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5083     // assertEquals("hh:mm BBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5084     assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5085     assertEquals("hh:mm BBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5086
5087     sdf.applyPattern(UnicodeString("hh BBB"));
5088
5089     // assertEquals("hh BBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5090     assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5091     // assertEquals("hh BBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5092     assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5093     // assertEquals("hh BBB | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5094     assertEquals("hh BBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5095
5096     // Wide.
5097     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5098
5099     // assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5100     assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5101     assertEquals("hh:mm:ss BBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5102     assertEquals("hh:mm:ss BBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5103     assertEquals("hh:mm:ss BBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5104     assertEquals("hh:mm:ss BBBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5105     assertEquals("hh:mm:ss BBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5106
5107     sdf.applyPattern(UnicodeString("hh:mm BBBB"));
5108
5109     // assertEquals("hh:mm BBBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5110     assertEquals("hh:mm BBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5111     // assertEquals("hh:mm BBBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5112     assertEquals("hh:mm BBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5113     assertEquals("hh:mm BBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5114
5115     sdf.applyPattern(UnicodeString("hh BBBB"));
5116
5117     // assertEquals("hh BBBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5118     assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5119     // assertEquals("hh BBBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5120     assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5121     // assertEquals("hh BBBB | 00:80:00", "12 midnight", sdf.format(k003000, out.remove()));
5122     assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5123
5124     // Narrow.
5125     sdf.applyPattern(UnicodeString("hh:mm:ss BBBBB"));
5126
5127     // assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5128     assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5129     assertEquals("hh:mm:ss BBBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5130     assertEquals("hh:mm:ss BBBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5131     assertEquals("hh:mm:ss BBBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5132     assertEquals("hh:mm:ss BBBBB | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5133     assertEquals("hh:mm:ss BBBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5134
5135     sdf.applyPattern(UnicodeString("hh:mm BBBBB"));
5136
5137     // assertEquals("hh:mm BBBBB | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5138     assertEquals("hh:mm BBBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5139     // assertEquals("hh:mm BBBBB | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5140     assertEquals("hh:mm BBBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5141     assertEquals("hh:mm BBBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5142
5143     sdf.applyPattern(UnicodeString("hh BBBBB"));
5144
5145     // assertEquals("hh BBBBB | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5146     assertEquals("hh BBBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5147     // assertEquals("hh BBBBB | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5148     assertEquals("hh BBBBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5149     // assertEquals("hh BBBBB | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5150     assertEquals("hh BBBBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5151 }
5152
5153 void DateFormatTest::TestDayPeriodWithLocales() {
5154     // Some times on 2015-11-13 (UTC+0).
5155     UDate k000000 = 1447372800000.0;
5156     UDate k010000 = 1447376400000.0;
5157     UDate k120000 = 1447416000000.0;
5158     UDate k220000 = 1447452000000.0;
5159
5160     UErrorCode errorCode = U_ZERO_ERROR;
5161     const TimeZone *tz = TimeZone::getGMT();
5162     UnicodeString out;
5163
5164     // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5165     // For ICU 57 output of "midnight" and its localized equivalentns is temporarily suppressed.
5166
5167     // Locale de has a word for midnight, but not noon.
5168     SimpleDateFormat sdf(UnicodeString(), Locale::getGermany(), errorCode);
5169     if (U_FAILURE(errorCode)) {
5170         dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5171         return;
5172     }
5173     sdf.setTimeZone(*tz);
5174
5175     sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
5176
5177     // assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 Mitternacht",
5178     //     sdf.format(k000000, out.remove()));
5179     assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 vorm.",
5180         sdf.format(k000000, out.remove()));
5181     assertEquals("hh:mm:ss bbbb | 12:00:00 | de", "12:00:00 nachm.",
5182         sdf.format(k120000, out.remove()));
5183
5184     // Locale ee has a rule that wraps around midnight (21h - 4h).
5185     sdf = SimpleDateFormat(UnicodeString(), Locale("ee"), errorCode);
5186     sdf.setTimeZone(*tz);
5187
5188     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5189
5190     assertEquals("hh:mm:ss BBBB | 22:00:00 | ee", UnicodeString("10:00:00 z\\u00E3").unescape(),
5191         sdf.format(k220000, out.remove()));
5192     assertEquals("hh:mm:ss BBBB | 00:00:00 | ee", UnicodeString("12:00:00 z\\u00E3").unescape(),
5193         sdf.format(k000000, out.remove()));
5194     assertEquals("hh:mm:ss BBBB | 01:00:00 | ee", UnicodeString("01:00:00 z\\u00E3").unescape(),
5195         sdf.format(k010000, out.remove()));
5196
5197     // Locale root has rules for AM/PM only.
5198     sdf = SimpleDateFormat(UnicodeString(), Locale("root"), errorCode);
5199     sdf.setTimeZone(*tz);
5200
5201     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5202
5203     assertEquals("hh:mm:ss BBBB | 00:00:00 | root", "12:00:00 AM",
5204         sdf.format(k000000, out.remove()));
5205     assertEquals("hh:mm:ss BBBB | 12:00:00 | root", "12:00:00 PM",
5206         sdf.format(k120000, out.remove()));
5207
5208     // Empty string should behave exactly as root.
5209     sdf = SimpleDateFormat(UnicodeString(), Locale(""), errorCode);
5210     sdf.setTimeZone(*tz);
5211
5212     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5213
5214     assertEquals("hh:mm:ss BBBB | 00:00:00 | \"\" (root)", "12:00:00 AM",
5215         sdf.format(k000000, out.remove()));
5216     assertEquals("hh:mm:ss BBBB | 12:00:00 | \"\" (root)", "12:00:00 PM",
5217         sdf.format(k120000, out.remove()));
5218
5219     // Locale en_US should fall back to en.
5220     sdf = SimpleDateFormat(UnicodeString(), Locale("en_US"), errorCode);
5221     sdf.setTimeZone(*tz);
5222
5223     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5224
5225     // assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 midnight",
5226     //     sdf.format(k000000, out.remove()));
5227     assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 at night",
5228          sdf.format(k000000, out.remove()));
5229     assertEquals("hh:mm:ss BBBB | 01:00:00 | en_US", "01:00:00 at night",
5230         sdf.format(k010000, out.remove()));
5231     assertEquals("hh:mm:ss BBBB | 12:00:00 | en_US", "12:00:00 noon",
5232         sdf.format(k120000, out.remove()));
5233
5234     // Locale es_CO should not fall back to es and should have a
5235     // different string for 1 in the morning.
5236     // (es_CO: "de la manana" (first n has a tilde) vs. es: "de la madrugada")
5237     sdf = SimpleDateFormat(UnicodeString(), Locale("es_CO"), errorCode);
5238     sdf.setTimeZone(*tz);
5239
5240     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5241     assertEquals("hh:mm:ss BBBB | 01:00:00 | es_CO", UnicodeString("01:00:00 de la ma\\u00F1ana").unescape(),
5242         sdf.format(k010000, out.remove()));
5243
5244     sdf = SimpleDateFormat(UnicodeString(), Locale("es"), errorCode);
5245     sdf.setTimeZone(*tz);
5246
5247     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5248     assertEquals("hh:mm:ss BBBB | 01:00:00 | es", "01:00:00 de la madrugada",
5249         sdf.format(k010000, out.remove()));
5250 }
5251
5252 void DateFormatTest::TestMinuteSecondFieldsInOddPlaces() {
5253     // Some times on 2015-11-13 (UTC+0).
5254     UDate k000000 = 1447372800000.0;
5255     UDate k000030 = 1447372830000.0;
5256     UDate k003000 = 1447374600000.0;
5257     UDate k060030 = 1447394430000.0;
5258     UDate k063000 = 1447396200000.0;
5259
5260     UErrorCode errorCode = U_ZERO_ERROR;
5261     const TimeZone *tz = TimeZone::getGMT();
5262     UnicodeString out;
5263
5264     // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5265     // For ICU 57 output of "midnight" is temporarily suppressed.
5266
5267     // Seconds field is not present.
5268
5269     // Apply pattern through constructor to make sure parsePattern() is called during initialization.
5270     SimpleDateFormat sdf(UnicodeString("hh:mm 'ss' bbbb"), errorCode);
5271     if (U_FAILURE(errorCode)) {
5272         dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5273         return;
5274     }
5275     sdf.setTimeZone(*tz);
5276
5277     // assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss midnight",
5278     //     sdf.format(k000030, out.remove()));
5279     assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss AM",
5280         sdf.format(k000030, out.remove()));
5281     assertEquals("hh:mm 'ss' bbbb | 06:00:30", "06:00 ss AM",
5282         sdf.format(k060030, out.remove()));
5283
5284     sdf.applyPattern(UnicodeString("hh:mm 'ss' BBBB"));
5285
5286     // assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss midnight",
5287     //     sdf.format(k000030, out.remove()));
5288     assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss at night",
5289         sdf.format(k000030, out.remove()));
5290     assertEquals("hh:mm 'ss' BBBB | 06:00:30", "06:00 ss in the morning",
5291         sdf.format(k060030, out.remove()));
5292
5293     // Minutes field is not present.
5294     sdf.applyPattern(UnicodeString("hh 'mm ss' bbbb"));
5295
5296     // assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss midnight",
5297     //     sdf.format(k003000, out.remove()));
5298     assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss AM",
5299         sdf.format(k003000, out.remove()));
5300     assertEquals("hh 'mm ss' bbbb | 06:30:00", "06 mm ss AM",
5301         sdf.format(k063000, out.remove()));
5302
5303     sdf.applyPattern(UnicodeString("hh 'mm ss' BBBB"));
5304
5305     // assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss midnight",
5306     //     sdf.format(k003000, out.remove()));
5307     assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss at night",
5308         sdf.format(k003000, out.remove()));
5309     assertEquals("hh 'mm ss' BBBB | 06:30:00", "06 mm ss in the morning",
5310         sdf.format(k063000, out.remove()));
5311
5312     // Minutes and seconds fields appear after day periods.
5313     sdf.applyPattern(UnicodeString("bbbb hh:mm:ss"));
5314
5315     // assertEquals("bbbb hh:mm:ss | 00:00:00", "midnight 12:00:00",
5316     //     sdf.format(k000000, out.remove()));
5317     assertEquals("bbbb hh:mm:ss | 00:00:00", "AM 12:00:00",
5318         sdf.format(k000000, out.remove()));
5319     assertEquals("bbbb hh:mm:ss | 00:00:30", "AM 12:00:30",
5320         sdf.format(k000030, out.remove()));
5321     assertEquals("bbbb hh:mm:ss | 00:30:00", "AM 12:30:00",
5322         sdf.format(k003000, out.remove()));
5323
5324     sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5325
5326     // assertEquals("BBBB hh:mm:ss | 00:00:00", "midnight 12:00:00",
5327     //     sdf.format(k000000, out.remove()));
5328     assertEquals("BBBB hh:mm:ss | 00:00:00", "at night 12:00:00",
5329         sdf.format(k000000, out.remove()));
5330     assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5331         sdf.format(k000030, out.remove()));
5332     assertEquals("BBBB hh:mm:ss | 00:30:00", "at night 12:30:00",
5333         sdf.format(k003000, out.remove()));
5334
5335     // Confirm applyPattern() reparses the pattern string.
5336     sdf.applyPattern(UnicodeString("BBBB hh"));
5337     // assertEquals("BBBB hh | 00:00:30", "midnight 12",
5338     //     sdf.format(k000030, out.remove()));
5339     assertEquals("BBBB hh | 00:00:30", "at night 12",
5340          sdf.format(k000030, out.remove()));
5341
5342     sdf.applyPattern(UnicodeString("BBBB hh:mm:'ss'"));
5343     // assertEquals("BBBB hh:mm:'ss' | 00:00:30", "midnight 12:00:ss",
5344     //     sdf.format(k000030, out.remove()));
5345     assertEquals("BBBB hh | 00:00:30", "at night 12:00:ss",
5346         sdf.format(k000030, out.remove()));
5347
5348     sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5349     assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5350         sdf.format(k000030, out.remove()));
5351 }
5352
5353 void DateFormatTest::TestDayPeriodParsing() {
5354     // Some times on 2015-11-13 (UTC+0).
5355     UDate k000000 = 1447372800000.0;
5356     UDate k003700 = 1447375020000.0;
5357     UDate k010000 = 1447376400000.0;
5358     UDate k013000 = 1447378200000.0;
5359     UDate k030000 = 1447383600000.0;
5360     UDate k090000 = 1447405200000.0;
5361     UDate k120000 = 1447416000000.0;
5362     UDate k130000 = 1447419600000.0;
5363     UDate k133700 = 1447421820000.0;
5364     UDate k150000 = 1447426800000.0;
5365     UDate k190000 = 1447441200000.0;
5366     UDate k193000 = 1447443000000.0;
5367     UDate k200000 = 1447444800000.0;
5368     UDate k210000 = 1447448400000.0;
5369
5370     UErrorCode errorCode = U_ZERO_ERROR;
5371     SimpleDateFormat sdf(UnicodeString(), errorCode);
5372     if (U_FAILURE(errorCode)) {
5373         dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5374         return;
5375     }
5376     const TimeZone *tz = TimeZone::getGMT();
5377     sdf.setTimeZone(*tz);
5378     UnicodeString out;
5379
5380     // 'B' -- flexible day periods
5381     // A day period on its own parses to the center of that period.
5382     sdf.applyPattern(UnicodeString("yyyy-MM-dd B"));
5383     assertEquals("yyyy-MM-dd B | 2015-11-13 midnight",
5384         k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5385     assertEquals("yyyy-MM-dd B | 2015-11-13 noon",
5386         k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5387     assertEquals("yyyy-MM-dd B | 2015-11-13 in the afternoon",
5388         k150000, sdf.parse(UnicodeString("2015-11-13 in the afternoon"), errorCode));
5389     assertEquals("yyyy-MM-dd B | 2015-11-13 in the evening",
5390         k193000, sdf.parse(UnicodeString("2015-11-13 in the evening"), errorCode));
5391     assertEquals("yyyy-MM-dd B | 2015-11-13 at night",
5392         k013000, sdf.parse(UnicodeString("2015-11-13 at night"), errorCode));
5393
5394     // If time and day period are consistent with each other then time is parsed accordingly.
5395     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5396     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 midnight",
5397         k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5398     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 noon",
5399         k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5400     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 at night",
5401         k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5402     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 in the afternoon",
5403         k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5404     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 in the morning",
5405         k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5406     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 at night",
5407         k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5408
5409     // If the hour is 13 thru 23 then day period has no effect on time (since time is assumed
5410     // to be in 24-hour format).
5411     sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5412     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 midnight",
5413         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5414     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 noon",
5415         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5416     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5417         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5418     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the afternoon",
5419         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the afternoon"), errorCode));
5420     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the morning",
5421         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the morning"), errorCode));
5422     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5423         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5424
5425     // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5426     // This unfortunately means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5427     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5428     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 midnight",
5429         k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5430     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 noon",
5431         k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5432
5433     // But when parsed with 'H', 0 indicates a 24-hour time, therefore we disregard the day period.
5434     sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5435     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 midnight",
5436         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5437     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 noon",
5438         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5439     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5440         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5441     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the afternoon",
5442         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the afternoon"), errorCode));
5443     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the morning",
5444         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the morning"), errorCode));
5445     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5446         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5447
5448     // Even when parsed with 'H', hours 1 thru 12 are considered 12-hour time and takes
5449     // day period into account in parsing.
5450     sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5451     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 midnight",
5452         k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5453     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 noon",
5454         k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5455     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 at night",
5456         k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5457     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 in the afternoon",
5458         k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5459     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 in the morning",
5460         k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5461     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 at night",
5462         k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5463
5464     // If a 12-hour time and the day period don't agree with each other, time is parsed as close
5465     // to the given day period as possible.
5466     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5467
5468     // AFTERNOON1 is [12, 18), but "7 in the afternoon" parses to 19:00.
5469     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 07:00 in the afternoon",
5470         k190000, sdf.parse(UnicodeString("2015-11-13 07:00 in the afternoon"), errorCode));
5471     // NIGHT1 is [21, 6), but "8 at night" parses to 20:00.
5472     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 08:00 at night",
5473         k200000, sdf.parse(UnicodeString("2015-11-13 08:00 at night"), errorCode));
5474
5475     // 'b' -- fixed day periods (AM, PM, midnight, noon)
5476     // On their own, "midnight" parses to 00:00 and "noon" parses to 12:00.
5477     // AM and PM are handled by the 'a' parser (which doesn't handle this case well).
5478     sdf.applyPattern(UnicodeString("yyyy-MM-dd b"));
5479     assertEquals("yyyy-MM-dd b | 2015-11-13 midnight",
5480         k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5481     assertEquals("yyyy-MM-dd b | 2015-11-13 noon",
5482         k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5483
5484     // For 12-hour times, AM and PM should be parsed as if with pattern character 'a'.
5485     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5486     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 AM",
5487         k010000, sdf.parse(UnicodeString("2015-11-13 01:00 AM"), errorCode));
5488     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 PM",
5489         k130000, sdf.parse(UnicodeString("2015-11-13 01:00 PM"), errorCode));
5490
5491     // 12 midnight parses to 00:00, and 12 noon parses to 12:00.
5492     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 midnight",
5493         k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5494     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 noon",
5495         k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5496
5497     // Hours 13-23 indicate 24-hour time so we disregard "midnight" or "noon".
5498     // Again, AM and PM are handled by the 'a' parser which doesn't handle this case well.
5499     sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5500     assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 midnight",
5501         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5502     assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 noon",
5503         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5504
5505     // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5506     // Again, this means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5507     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5508     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 midnight",
5509         k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5510     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 noon",
5511         k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5512
5513     // With 'H' though 0 indicates a 24-hour time, therefore we disregard the day period.
5514     sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5515     assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 midnight",
5516         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5517     assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 noon",
5518         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5519
5520     // If "midnight" or "noon" is parsed with a 12-hour time other than 12:00, choose
5521     // the version that's closer to the period given.
5522     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5523     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 midnight",
5524         k030000, sdf.parse(UnicodeString("2015-11-13 03:00 midnight"), errorCode));
5525     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 noon",
5526         k150000, sdf.parse(UnicodeString("2015-11-13 03:00 noon"), errorCode));
5527 }
5528
5529 #endif /* #if !UCONFIG_NO_FORMATTING */
5530
5531 //eof