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