• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * COPYRIGHT:
5  * Copyright (c) 1997-2016, International Business Machines
6  * Corporation and others. All Rights Reserved.
7  ********************************************************************/
8 
9 #include "unicode/utypes.h"
10 
11 #if !UCONFIG_NO_FORMATTING
12 
13 #include "dtfmttst.h"
14 #include "unicode/localpointer.h"
15 #include "unicode/timezone.h"
16 #include "unicode/gregocal.h"
17 #include "unicode/smpdtfmt.h"
18 #include "unicode/datefmt.h"
19 #include "unicode/dtptngen.h"
20 #include "unicode/simpletz.h"
21 #include "unicode/strenum.h"
22 #include "unicode/dtfmtsym.h"
23 #include "cmemory.h"
24 #include "cstring.h"
25 #include "caltest.h"  // for fieldName
26 #include <stdio.h> // for sprintf
27 
28 #if U_PLATFORM_HAS_WIN32_API
29 #include "windttst.h"
30 #endif
31 
32 #define ASSERT_OK(status)  if(U_FAILURE(status)) {errcheckln(status, #status " = %s @ %s:%d", u_errorName(status), __FILE__, __LINE__); return; }
33 
34 // *****************************************************************************
35 // class DateFormatTest
36 // *****************************************************************************
37 
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     TESTCASE_AUTO(TestFormatsWithNumberSystems);
100     /*
101     TESTCASE_AUTO(TestRelativeError);
102     TESTCASE_AUTO(TestRelativeOther);
103     */
104     TESTCASE_AUTO(TestDotAndAtLeniency);
105     TESTCASE_AUTO(TestDateFormatLeniency);
106     TESTCASE_AUTO(TestParseMultiPatternMatch);
107 
108     TESTCASE_AUTO(TestParseLeniencyAPIs);
109     TESTCASE_AUTO(TestNumberFormatOverride);
110     TESTCASE_AUTO(TestCreateInstanceForSkeleton);
111     TESTCASE_AUTO(TestCreateInstanceForSkeletonDefault);
112     TESTCASE_AUTO(TestCreateInstanceForSkeletonWithCalendar);
113     TESTCASE_AUTO(TestDFSCreateForLocaleNonGregorianLocale);
114     TESTCASE_AUTO(TestDFSCreateForLocaleWithCalendarInLocale);
115     TESTCASE_AUTO(TestChangeCalendar);
116 
117     TESTCASE_AUTO(TestPatternFromSkeleton);
118 
119     TESTCASE_AUTO(TestAmPmMidnightNoon);
120     TESTCASE_AUTO(TestFlexibleDayPeriod);
121     TESTCASE_AUTO(TestDayPeriodWithLocales);
122     TESTCASE_AUTO(TestMinuteSecondFieldsInOddPlaces);
123     TESTCASE_AUTO(TestDayPeriodParsing);
124 
125     TESTCASE_AUTO_END;
126 }
127 
TestPatterns()128 void DateFormatTest::TestPatterns() {
129     static const struct {
130         const char *actualPattern;
131         const char *expectedPattern;
132         const char *localeID;
133         const char *expectedLocalPattern;
134     } EXPECTED[] = {
135         {UDAT_YEAR, "y","en","y"},
136 
137         {UDAT_QUARTER, "QQQQ", "en", "QQQQ"},
138         {UDAT_ABBR_QUARTER, "QQQ", "en", "QQQ"},
139         {UDAT_YEAR_QUARTER, "yQQQQ", "en", "QQQQ y"},
140         {UDAT_YEAR_ABBR_QUARTER, "yQQQ", "en", "QQQ y"},
141 
142         {UDAT_NUM_MONTH, "M", "en", "L"},
143         {UDAT_ABBR_MONTH, "MMM", "en", "LLL"},
144         {UDAT_MONTH, "MMMM", "en", "LLLL"},
145         {UDAT_YEAR_NUM_MONTH, "yM","en","M/y"},
146         {UDAT_YEAR_ABBR_MONTH, "yMMM","en","MMM y"},
147         {UDAT_YEAR_MONTH, "yMMMM","en","MMMM y"},
148 
149         {UDAT_DAY, "d","en","d"},
150         {UDAT_YEAR_NUM_MONTH_DAY, "yMd", "en", "M/d/y"},
151         {UDAT_YEAR_ABBR_MONTH_DAY, "yMMMd", "en", "MMM d, y"},
152         {UDAT_YEAR_MONTH_DAY, "yMMMMd", "en", "MMMM d, y"},
153         {UDAT_YEAR_NUM_MONTH_WEEKDAY_DAY, "yMEd", "en", "EEE, M/d/y"},
154         {UDAT_YEAR_ABBR_MONTH_WEEKDAY_DAY, "yMMMEd", "en", "EEE, MMM d, y"},
155         {UDAT_YEAR_MONTH_WEEKDAY_DAY, "yMMMMEEEEd", "en", "EEEE, MMMM d, y"},
156 
157         {UDAT_NUM_MONTH_DAY, "Md","en","M/d"},
158         {UDAT_ABBR_MONTH_DAY, "MMMd","en","MMM d"},
159         {UDAT_MONTH_DAY, "MMMMd","en","MMMM d"},
160         {UDAT_NUM_MONTH_WEEKDAY_DAY, "MEd","en","EEE, M/d"},
161         {UDAT_ABBR_MONTH_WEEKDAY_DAY, "MMMEd","en","EEE, MMM d"},
162         {UDAT_MONTH_WEEKDAY_DAY, "MMMMEEEEd","en","EEEE, MMMM d"},
163 
164         {UDAT_HOUR, "j", "en", "h a"}, // (fixed expected result per ticket 6872<-6626)
165         {UDAT_HOUR24, "H", "en", "HH"}, // (fixed expected result per ticket 6872<-6626
166 
167         {UDAT_MINUTE, "m", "en", "m"},
168         {UDAT_HOUR_MINUTE, "jm","en","h:mm a"}, // (fixed expected result per ticket 6872<-7180)
169         {UDAT_HOUR24_MINUTE, "Hm", "en", "HH:mm"}, // (fixed expected result per ticket 6872<-6626)
170 
171         {UDAT_SECOND, "s", "en", "s"},
172         {UDAT_HOUR_MINUTE_SECOND, "jms","en","h:mm:ss a"}, // (fixed expected result per ticket 6872<-7180)
173         {UDAT_HOUR24_MINUTE_SECOND, "Hms","en","HH:mm:ss"}, // (fixed expected result per ticket 6872<-6626)
174         {UDAT_MINUTE_SECOND, "ms", "en", "mm:ss"}, // (fixed expected result per ticket 6872<-6626)
175 
176         {UDAT_LOCATION_TZ, "VVVV", "en", "VVVV"},
177         {UDAT_GENERIC_TZ, "vvvv", "en", "vvvv"},
178         {UDAT_ABBR_GENERIC_TZ, "v", "en", "v"},
179         {UDAT_SPECIFIC_TZ, "zzzz", "en", "zzzz"},
180         {UDAT_ABBR_SPECIFIC_TZ, "z", "en", "z"},
181         {UDAT_ABBR_UTC_TZ, "ZZZZ", "en", "ZZZZ"},
182 
183         {UDAT_YEAR_NUM_MONTH_DAY UDAT_ABBR_UTC_TZ, "yMdZZZZ", "en", "M/d/y, ZZZZ"},
184         {UDAT_MONTH_DAY UDAT_LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d, VVVV"}
185     };
186 
187     IcuTestErrorCode errorCode(*this, "TestPatterns()");
188     for (int32_t i = 0; i < UPRV_LENGTHOF(EXPECTED); i++) {
189         // Verify that patterns have the correct values
190         UnicodeString actualPattern(EXPECTED[i].actualPattern, -1, US_INV);
191         UnicodeString expectedPattern(EXPECTED[i].expectedPattern, -1, US_INV);
192         Locale locale(EXPECTED[i].localeID);
193         if (actualPattern != expectedPattern) {
194             errln("FAILURE! Expected pattern: " + expectedPattern +
195                     " but was: " + actualPattern);
196         }
197 
198         // Verify that DataFormat instances produced contain the correct
199         // localized patterns
200         // TODO: use DateFormat::getInstanceForSkeleton(), ticket #9029
201         // Java test code:
202         // DateFormat date1 = DateFormat.getPatternInstance(actualPattern,
203         //         locale);
204         // DateFormat date2 = DateFormat.getPatternInstance(Calendar.getInstance(locale),
205         //         actualPattern, locale);
206         LocalPointer<DateTimePatternGenerator> generator(
207                 DateTimePatternGenerator::createInstance(locale, errorCode));
208         if(errorCode.logDataIfFailureAndReset("DateTimePatternGenerator::createInstance() failed for locale ID \"%s\"", EXPECTED[i].localeID)) {
209             continue;
210         }
211         UnicodeString pattern = generator->getBestPattern(actualPattern, errorCode);
212         SimpleDateFormat date1(pattern, locale, errorCode);
213         SimpleDateFormat date2(pattern, locale, errorCode);
214         date2.adoptCalendar(Calendar::createInstance(locale, errorCode));
215         if(errorCode.logIfFailureAndReset("DateFormat::getInstanceForSkeleton() failed")) {
216             errln("  for actualPattern \"%s\" & locale ID \"%s\"",
217                   EXPECTED[i].actualPattern, EXPECTED[i].localeID);
218             continue;
219         }
220 
221         UnicodeString expectedLocalPattern(EXPECTED[i].expectedLocalPattern, -1, US_INV);
222         UnicodeString actualLocalPattern1;
223         UnicodeString actualLocalPattern2;
224         date1.toLocalizedPattern(actualLocalPattern1, errorCode);
225         date2.toLocalizedPattern(actualLocalPattern2, errorCode);
226         if (actualLocalPattern1 != expectedLocalPattern) {
227             errln("FAILURE! Expected local pattern: " + expectedLocalPattern
228                     + " but was: " + actualLocalPattern1);
229         }
230         if (actualLocalPattern2 != expectedLocalPattern) {
231             errln("FAILURE! Expected local pattern: " + expectedLocalPattern
232                     + " but was: " + actualLocalPattern2);
233         }
234     }
235 }
236 
237 // Test written by Wally Wedel and emailed to me.
TestWallyWedel()238 void DateFormatTest::TestWallyWedel()
239 {
240     UErrorCode status = U_ZERO_ERROR;
241     /*
242      * Instantiate a TimeZone so we can get the ids.
243      */
244     TimeZone *tz = new SimpleTimeZone(7,"");
245     /*
246      * Computational variables.
247      */
248     int32_t offset, hours, minutes, seconds;
249     /*
250      * Instantiate a SimpleDateFormat set up to produce a full time
251      zone name.
252      */
253     SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)"zzzz", status);
254     /*
255      * A String array for the time zone ids.
256      */
257     int32_t ids_length;
258     StringEnumeration* ids = TimeZone::createEnumeration();
259     if (ids == NULL) {
260         dataerrln("Unable to create TimeZone enumeration.");
261         if (sdf != NULL) {
262             delete sdf;
263         }
264         return;
265     }
266     ids_length = ids->count(status);
267     /*
268      * How many ids do we have?
269      */
270     logln("Time Zone IDs size: %d", ids_length);
271     /*
272      * Column headings (sort of)
273      */
274     logln("Ordinal ID offset(h:m) name");
275     /*
276      * Loop through the tzs.
277      */
278     UDate today = Calendar::getNow();
279     Calendar *cal = Calendar::createInstance(status);
280     for (int32_t i = 0; i < ids_length; i++) {
281         // logln(i + " " + ids[i]);
282         const UnicodeString* id = ids->snext(status);
283         TimeZone *ttz = TimeZone::createTimeZone(*id);
284         // offset = ttz.getRawOffset();
285         cal->setTimeZone(*ttz);
286         cal->setTime(today, status);
287         offset = cal->get(UCAL_ZONE_OFFSET, status) + cal->get(UCAL_DST_OFFSET, status);
288         // logln(i + " " + ids[i] + " offset " + offset);
289         const char* sign = "+";
290         if (offset < 0) {
291             sign = "-";
292             offset = -offset;
293         }
294         hours = offset/3600000;
295         minutes = (offset%3600000)/60000;
296         seconds = (offset%60000)/1000;
297         UnicodeString dstOffset = (UnicodeString)"" + sign + (hours < 10 ? "0" : "") +
298             (int32_t)hours + ":" + (minutes < 10 ? "0" : "") + (int32_t)minutes;
299         if (seconds != 0) {
300             dstOffset = dstOffset + ":" + (seconds < 10 ? "0" : "") + seconds;
301         }
302         /*
303          * Instantiate a date so we can display the time zone name.
304          */
305         sdf->setTimeZone(*ttz);
306         /*
307          * Format the output.
308          */
309         UnicodeString fmtOffset;
310         FieldPosition pos(FieldPosition::DONT_CARE);
311         sdf->format(today,fmtOffset, pos);
312         // UnicodeString fmtOffset = tzS.toString();
313         UnicodeString *fmtDstOffset = 0;
314         if (fmtOffset.startsWith("GMT") && fmtOffset.length() != 3)
315         {
316             //fmtDstOffset = fmtOffset->substring(3);
317             fmtDstOffset = new UnicodeString();
318             fmtOffset.extract(3, fmtOffset.length(), *fmtDstOffset);
319         }
320         /*
321          * Show our result.
322          */
323         UBool ok = fmtDstOffset == 0 || *fmtDstOffset == dstOffset;
324         if (ok)
325         {
326             logln(UnicodeString() + i + " " + *id + " " + dstOffset +
327                   " " + fmtOffset +
328                   (fmtDstOffset != 0 ? " ok" : " ?"));
329         }
330         else
331         {
332             errln(UnicodeString() + i + " " + *id + " " + dstOffset +
333                   " " + fmtOffset + " *** FAIL ***");
334         }
335         delete ttz;
336         delete fmtDstOffset;
337     }
338     delete cal;
339     //  delete ids;   // TODO:  BAD API
340     delete ids;
341     delete sdf;
342     delete tz;
343 }
344 
345 // -------------------------------------
346 
347 /**
348  * Test operator==
349  */
350 void
TestEquals()351 DateFormatTest::TestEquals()
352 {
353     DateFormat* fmtA = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
354     DateFormat* fmtB = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
355     if ( fmtA == NULL || fmtB == NULL){
356         dataerrln("Error calling DateFormat::createDateTimeInstance");
357         delete fmtA;
358         delete fmtB;
359         return;
360     }
361 
362     if (!(*fmtA == *fmtB)) errln((UnicodeString)"FAIL");
363     delete fmtA;
364     delete fmtB;
365 
366     TimeZone* test = TimeZone::createTimeZone("PDT");
367     delete test;
368 }
369 
370 // -------------------------------------
371 
372 /**
373  * Test the parsing of 2-digit years.
374  */
375 void
TestTwoDigitYearDSTParse(void)376 DateFormatTest::TestTwoDigitYearDSTParse(void)
377 {
378     UErrorCode status = U_ZERO_ERROR;
379     SimpleDateFormat* fullFmt = new SimpleDateFormat((UnicodeString)"EEE MMM dd HH:mm:ss.SSS zzz yyyy G", status);
380     SimpleDateFormat *fmt = new SimpleDateFormat((UnicodeString)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status);
381     //DateFormat* fmt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, Locale::ENGLISH);
382     UnicodeString* s = new UnicodeString("03-Apr-04 2:20:47 o'clock AM PST", "");
383     TimeZone* defaultTZ = TimeZone::createDefault();
384     TimeZone* PST = TimeZone::createTimeZone("PST");
385     int32_t defaultOffset = defaultTZ->getRawOffset();
386     int32_t PSTOffset = PST->getRawOffset();
387     int32_t hour = 2 + (defaultOffset - PSTOffset) / (60*60*1000);
388     // hour is the expected hour of day, in units of seconds
389     hour = ((hour < 0) ? hour + 24 : hour) * 60*60;
390 
391     UnicodeString str;
392 
393     if(U_FAILURE(status)) {
394         dataerrln("Could not set up test. exitting - %s", u_errorName(status));
395         return;
396     }
397 
398     UDate d = fmt->parse(*s, status);
399     logln(*s + " P> " + ((DateFormat*)fullFmt)->format(d, str));
400     int32_t y, m, day, hr, min, sec;
401     dateToFields(d, y, m, day, hr, min, sec);
402     hour += defaultTZ->inDaylightTime(d, status) ? 1 : 0;
403     hr = hr*60*60;
404     if (hr != hour)
405         errln((UnicodeString)"FAIL: Should parse to hour " + hour + " but got " + hr);
406 
407     if (U_FAILURE(status))
408         errln((UnicodeString)"FAIL: " + (int32_t)status);
409 
410     delete s;
411     delete fmt;
412     delete fullFmt;
413     delete PST;
414     delete defaultTZ;
415 }
416 
417 // -------------------------------------
418 
toHexString(int32_t i)419 UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
420 
421 UnicodeString&
escape(UnicodeString & s)422 DateFormatTest::escape(UnicodeString& s)
423 {
424     UnicodeString buf;
425     for (int32_t i=0; i<s.length(); ++i)
426     {
427         UChar c = s[(int32_t)i];
428         if (c <= (UChar)0x7F) buf += c;
429         else {
430             buf += (UChar)0x5c; buf += (UChar)0x55;
431             buf += toHexString((c & 0xF000) >> 12);
432             buf += toHexString((c & 0x0F00) >> 8);
433             buf += toHexString((c & 0x00F0) >> 4);
434             buf += toHexString(c & 0x000F);
435         }
436     }
437     return (s = buf);
438 }
439 
440 // -------------------------------------
441 
442 /**
443  * This MUST be kept in sync with DateFormatSymbols.gPatternChars.
444  */
445 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
446 static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:";
447 #else
448 static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB";
449 #endif
450 
451 /**
452  * A list of the names of all the fields in DateFormat.
453  * This MUST be kept in sync with DateFormat.
454  */
455 static const char* DATEFORMAT_FIELD_NAMES[] = {
456     "ERA_FIELD",
457     "YEAR_FIELD",
458     "MONTH_FIELD",
459     "DATE_FIELD",
460     "HOUR_OF_DAY1_FIELD",
461     "HOUR_OF_DAY0_FIELD",
462     "MINUTE_FIELD",
463     "SECOND_FIELD",
464     "MILLISECOND_FIELD",
465     "DAY_OF_WEEK_FIELD",
466     "DAY_OF_YEAR_FIELD",
467     "DAY_OF_WEEK_IN_MONTH_FIELD",
468     "WEEK_OF_YEAR_FIELD",
469     "WEEK_OF_MONTH_FIELD",
470     "AM_PM_FIELD",
471     "HOUR1_FIELD",
472     "HOUR0_FIELD",
473     "TIMEZONE_FIELD",
474     "YEAR_WOY_FIELD",
475     "DOW_LOCAL_FIELD",
476     "EXTENDED_YEAR_FIELD",
477     "JULIAN_DAY_FIELD",
478     "MILLISECONDS_IN_DAY_FIELD",
479     "TIMEZONE_RFC_FIELD",
480     "GENERIC_TIMEZONE_FIELD",
481     "STAND_ALONE_DAY_FIELD",
482     "STAND_ALONE_MONTH_FIELD",
483     "QUARTER_FIELD",
484     "STAND_ALONE_QUARTER_FIELD",
485     "TIMEZONE_SPECIAL_FIELD",
486     "YEAR_NAME_FIELD",
487     "TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD",
488     "TIMEZONE_ISO_FIELD",
489     "TIMEZONE_ISO_LOCAL_FIELD",
490     "RELATED_YEAR_FIELD",
491     "AM_PM_MIDNIGHT_NOON_FIELD",
492     "FLEXIBLE_DAY_PERIOD_FIELD",
493     "UDAT_TIME_SEPARATOR_FIELD",
494 };
495 
496 static const int32_t DATEFORMAT_FIELD_NAMES_LENGTH =
497     UPRV_LENGTHOF(DATEFORMAT_FIELD_NAMES);
498 
499 /**
500  * Verify that returned field position indices are correct.
501  */
TestFieldPosition()502 void DateFormatTest::TestFieldPosition() {
503     UErrorCode ec = U_ZERO_ERROR;
504     int32_t i, j, exp;
505     UnicodeString buf;
506 
507     // Verify data
508     DateFormatSymbols rootSyms(Locale(""), ec);
509     if (U_FAILURE(ec)) {
510         dataerrln("Unable to create DateFormatSymbols - %s", u_errorName(ec));
511         return;
512     }
513 
514     // local pattern chars data is not longer loaded
515     // from icu locale bundle
516     assertEquals("patternChars", PATTERN_CHARS, rootSyms.getLocalPatternChars(buf));
517     assertEquals("patternChars", PATTERN_CHARS, DateFormatSymbols::getPatternUChars());
518     assertTrue("DATEFORMAT_FIELD_NAMES", DATEFORMAT_FIELD_NAMES_LENGTH == UDAT_FIELD_COUNT);
519 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
520     assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS));
521 #else
522     assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS) + 1); // +1 for missing TIME_SEPARATOR pattern char
523 #endif
524 
525     // Create test formatters
526     const int32_t COUNT = 4;
527     DateFormat* dateFormats[COUNT];
528     dateFormats[0] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getUS());
529     dateFormats[1] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getFrance());
530     // Make the pattern "G y M d..."
531     buf.remove().append(PATTERN_CHARS);
532     for (j=buf.length()-1; j>=0; --j) buf.insert(j, (UChar)32/*' '*/);
533     dateFormats[2] = new SimpleDateFormat(buf, Locale::getUS(), ec);
534     // Make the pattern "GGGG yyyy MMMM dddd..."
535     for (j=buf.length()-1; j>=0; j-=2) {
536         for (i=0; i<3; ++i) {
537             buf.insert(j, buf.charAt(j));
538         }
539     }
540     dateFormats[3] = new SimpleDateFormat(buf, Locale::getUS(), ec);
541     if(U_FAILURE(ec)){
542         errln(UnicodeString("Could not create SimpleDateFormat object for locale en_US. Error: " )+ UnicodeString(u_errorName(ec)));
543         return;
544     }
545     UDate aug13 = 871508052513.0;
546 
547     // Expected output field values for above DateFormats on aug13
548     // Fields are given in order of DateFormat field number
549     const char* EXPECTED[] = {
550         "", "1997", "August", "13", "", "", "34", "12", "", "Wednesday",
551         "", "", "", "", "PM", "2", "", "Pacific Daylight Time", "", "",
552         "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
553 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
554         ":",
555 #else
556         "",
557 #endif
558 
559         "", "1997", "ao\\u00FBt", "13", "", "14", "34", "12", "", "mercredi",
560         "", "", "", "", "", "", "", "heure d\\u2019\\u00E9t\\u00E9 du Pacifique", "", "",
561         "", "", "", "", "",  "", "", "", "", "", "", "", "", "", "", "", "",
562 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
563         ":",
564 #else
565         "",
566 #endif
567 
568         "AD", "1997", "8", "13", "14", "14", "34", "12", "5", "Wed",
569         "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4",
570         "1997", "2450674", "52452513", "-0700", "PT",  "4", "8", "3", "3", "uslax",
571         "1997", "GMT-7", "-07", "-07", "1997", "PM", "in the afternoon",
572 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
573         ":",
574 #else
575         "",
576 #endif
577 
578         "Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130", "Wednesday",
579         "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "Wednesday",
580         "1997", "2450674", "52452513", "GMT-07:00", "Pacific Time",  "Wednesday", "August", "3rd quarter", "3rd quarter", "Los Angeles Time",
581         "1997", "GMT-07:00", "-0700", "-0700", "1997", "PM", "in the afternoon",
582 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
583         ":",
584 #else
585         "",
586 #endif
587     };
588 
589     const int32_t EXPECTED_LENGTH = UPRV_LENGTHOF(EXPECTED);
590 
591     assertTrue("data size", EXPECTED_LENGTH == COUNT * UDAT_FIELD_COUNT);
592 
593     TimeZone* PT = TimeZone::createTimeZone("America/Los_Angeles");
594     for (j = 0, exp = 0; j < COUNT; ++j) {
595         //  String str;
596         DateFormat* df = dateFormats[j];
597         df->setTimeZone(*PT);
598         SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
599         if (sdtfmt != NULL) {
600             logln(" Pattern = " + sdtfmt->toPattern(buf.remove()));
601         } else {
602             logln(" Pattern = ? (not a SimpleDateFormat)");
603         }
604         logln((UnicodeString)"  Result = " + df->format(aug13, buf.remove()));
605 
606         int32_t expBase = exp; // save for later
607         for (i = 0; i < UDAT_FIELD_COUNT; ++i, ++exp) {
608             FieldPosition pos(i);
609             buf.remove();
610             df->format(aug13, buf, pos);
611             UnicodeString field;
612             buf.extractBetween(pos.getBeginIndex(), pos.getEndIndex(), field);
613             assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
614                          ctou(EXPECTED[exp]), field);
615         }
616 
617         // test FieldPositionIterator API
618         logln("FieldPositionIterator");
619         {
620           UErrorCode status = U_ZERO_ERROR;
621           FieldPositionIterator posIter;
622           FieldPosition fp;
623 
624           buf.remove();
625           df->format(aug13, buf, &posIter, status);
626           while (posIter.next(fp)) {
627             int32_t i = fp.getField();
628             UnicodeString field;
629             buf.extractBetween(fp.getBeginIndex(), fp.getEndIndex(), field);
630             assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
631                          ctou(EXPECTED[expBase + i]), field);
632           }
633 
634         }
635     }
636 
637 
638     // test null posIter
639     buf.remove();
640     UErrorCode status = U_ZERO_ERROR;
641     dateFormats[0]->format(aug13, buf, NULL, status);
642     // if we didn't crash, we succeeded.
643 
644     for (i=0; i<COUNT; ++i) {
645         delete dateFormats[i];
646     }
647     delete PT;
648 }
649 
650 // -------------------------------------
651 
652 /**
653  * General parse/format tests.  Add test cases as needed.
654  */
TestGeneral()655 void DateFormatTest::TestGeneral() {
656     const char* DATA[] = {
657         "yyyy MM dd HH:mm:ss.SSS",
658 
659         // Milliseconds are left-justified, since they format as fractions of a second
660         "y/M/d H:mm:ss.S", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5", "2004 03 10 16:36:31.500",
661         "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.56", "2004 03 10 16:36:31.560",
662         "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567",
663         "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5670",
664     };
665     expect(DATA, UPRV_LENGTHOF(DATA), Locale("en", "", ""));
666 }
667 
668 // -------------------------------------
669 
670 /**
671  * Verify that strings which contain incomplete specifications are parsed
672  * correctly.  In some instances, this means not being parsed at all, and
673  * returning an appropriate error.
674  */
675 void
TestPartialParse994()676 DateFormatTest::TestPartialParse994()
677 {
678     UErrorCode status = U_ZERO_ERROR;
679     SimpleDateFormat* f = new SimpleDateFormat(status);
680     if (U_FAILURE(status)) {
681         dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
682         delete f;
683         return;
684     }
685     UDate null = 0;
686     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", date(97, 1 - 1, 17, 10, 11, 42));
687     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null);
688     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null);
689     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null);
690     tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null);
691     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
692     delete f;
693 }
694 
695 // -------------------------------------
696 
697 void
tryPat994(SimpleDateFormat * format,const char * pat,const char * str,UDate expected)698 DateFormatTest::tryPat994(SimpleDateFormat* format, const char* pat, const char* str, UDate expected)
699 {
700     UErrorCode status = U_ZERO_ERROR;
701     UDate null = 0;
702     logln(UnicodeString("Pattern \"") + pat + "\"   String \"" + str + "\"");
703     //try {
704         format->applyPattern(pat);
705         UDate date = format->parse(str, status);
706         if (U_FAILURE(status) || date == null)
707         {
708             logln((UnicodeString)"ParseException: " + (int32_t)status);
709             if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
710         }
711         else
712         {
713             UnicodeString f;
714             ((DateFormat*)format)->format(date, f);
715             logln(UnicodeString(" parse(") + str + ") -> " + dateToString(date));
716             logln((UnicodeString)" format -> " + f);
717             if (expected == null ||
718                 !(date == expected)) errln((UnicodeString)"FAIL: Expected null");//" + expected);
719             if (!(f == str)) errln(UnicodeString("FAIL: Expected ") + str);
720         }
721     //}
722     //catch(ParseException e) {
723     //    logln((UnicodeString)"ParseException: " + e.getMessage());
724     //    if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
725     //}
726     //catch(Exception e) {
727     //    errln((UnicodeString)"*** Exception:");
728     //    e.printStackTrace();
729     //}
730 }
731 
732 // -------------------------------------
733 
734 /**
735  * Verify the behavior of patterns in which digits for different fields run together
736  * without intervening separators.
737  */
738 void
TestRunTogetherPattern985()739 DateFormatTest::TestRunTogetherPattern985()
740 {
741     UErrorCode status = U_ZERO_ERROR;
742     UnicodeString format("yyyyMMddHHmmssSSS");
743     UnicodeString now, then;
744     //UBool flag;
745     SimpleDateFormat *formatter = new SimpleDateFormat(format, status);
746     if (U_FAILURE(status)) {
747         dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
748         delete formatter;
749         return;
750     }
751     UDate date1 = Calendar::getNow();
752     ((DateFormat*)formatter)->format(date1, now);
753     logln(now);
754     ParsePosition pos(0);
755     UDate date2 = formatter->parse(now, pos);
756     if (date2 == 0) then = UnicodeString("Parse stopped at ") + pos.getIndex();
757     else ((DateFormat*)formatter)->format(date2, then);
758     logln(then);
759     if (!(date2 == date1)) errln((UnicodeString)"FAIL");
760     delete formatter;
761     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
762 }
763 
764 // -------------------------------------
765 
766 /**
767  * Verify the behavior of patterns in which digits for different fields run together
768  * without intervening separators.
769  */
770 void
TestRunTogetherPattern917()771 DateFormatTest::TestRunTogetherPattern917()
772 {
773     UErrorCode status = U_ZERO_ERROR;
774     SimpleDateFormat* fmt;
775     UnicodeString myDate;
776     fmt = new SimpleDateFormat((UnicodeString)"yyyy/MM/dd", status);
777     if (U_FAILURE(status)) {
778         dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
779         delete fmt;
780         return;
781     }
782     myDate = "1997/02/03";
783     testIt917(fmt, myDate, date(97, 2 - 1, 3));
784     delete fmt;
785     fmt = new SimpleDateFormat((UnicodeString)"yyyyMMdd", status);
786     myDate = "19970304";
787     testIt917(fmt, myDate, date(97, 3 - 1, 4));
788     delete fmt;
789     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
790 }
791 
792 // -------------------------------------
793 
794 void
testIt917(SimpleDateFormat * fmt,UnicodeString & str,UDate expected)795 DateFormatTest::testIt917(SimpleDateFormat* fmt, UnicodeString& str, UDate expected)
796 {
797     UErrorCode status = U_ZERO_ERROR;
798     UnicodeString pattern;
799     logln((UnicodeString)"pattern=" + fmt->toPattern(pattern) + "   string=" + str);
800     Formattable o;
801     //try {
802         ((Format*)fmt)->parseObject(str, o, status);
803     //}
804     if (U_FAILURE(status)) return;
805     //catch(ParseException e) {
806     //    e.printStackTrace();
807     //    return;
808     //}
809     logln((UnicodeString)"Parsed object: " + dateToString(o.getDate()));
810     if (!(o.getDate() == expected)) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
811     UnicodeString formatted; ((Format*)fmt)->format(o, formatted, status);
812     logln((UnicodeString)"Formatted string: " + formatted);
813     if (!(formatted == str)) errln((UnicodeString)"FAIL: Expected " + str);
814     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
815 }
816 
817 // -------------------------------------
818 
819 /**
820  * Verify the handling of Czech June and July, which have the unique attribute that
821  * one is a proper prefix substring of the other.
822  */
823 void
TestCzechMonths459()824 DateFormatTest::TestCzechMonths459()
825 {
826     UErrorCode status = U_ZERO_ERROR;
827     DateFormat* fmt = DateFormat::createDateInstance(DateFormat::FULL, Locale("cs", "", ""));
828     if (fmt == NULL){
829         dataerrln("Error calling DateFormat::createDateInstance()");
830         return;
831     }
832 
833     UnicodeString pattern;
834     logln((UnicodeString)"Pattern " + ((SimpleDateFormat*) fmt)->toPattern(pattern));
835     UDate june = date(97, UCAL_JUNE, 15);
836     UDate july = date(97, UCAL_JULY, 15);
837     UnicodeString juneStr; fmt->format(june, juneStr);
838     UnicodeString julyStr; fmt->format(july, julyStr);
839     //try {
840         logln((UnicodeString)"format(June 15 1997) = " + juneStr);
841         UDate d = fmt->parse(juneStr, status);
842         UnicodeString s; fmt->format(d, s);
843         int32_t month,yr,day,hr,min,sec; dateToFields(d,yr,month,day,hr,min,sec);
844         logln((UnicodeString)"  -> parse -> " + s + " (month = " + month + ")");
845         if (month != UCAL_JUNE) errln((UnicodeString)"FAIL: Month should be June");
846         logln((UnicodeString)"format(July 15 1997) = " + julyStr);
847         d = fmt->parse(julyStr, status);
848         fmt->format(d, s);
849         dateToFields(d,yr,month,day,hr,min,sec);
850         logln((UnicodeString)"  -> parse -> " + s + " (month = " + month + ")");
851         if (month != UCAL_JULY) errln((UnicodeString)"FAIL: Month should be July");
852     //}
853     //catch(ParseException e) {
854     if (U_FAILURE(status))
855         errln((UnicodeString)"Exception: " + (int32_t)status);
856     //}
857     delete fmt;
858 }
859 
860 // -------------------------------------
861 
862 /**
863  * Test the handling of 'D' in patterns.
864  */
865 void
TestLetterDPattern212()866 DateFormatTest::TestLetterDPattern212()
867 {
868     UErrorCode status = U_ZERO_ERROR;
869     UnicodeString dateString("1995-040.05:01:29");
870     UnicodeString bigD("yyyy-DDD.hh:mm:ss");
871     UnicodeString littleD("yyyy-ddd.hh:mm:ss");
872     UDate expLittleD = date(95, 0, 1, 5, 1, 29);
873     UDate expBigD = expLittleD + 39 * 24 * 3600000.0;
874     expLittleD = expBigD; // Expect the same, with default lenient parsing
875     logln((UnicodeString)"dateString= " + dateString);
876     SimpleDateFormat *formatter = new SimpleDateFormat(bigD, status);
877     if (U_FAILURE(status)) {
878         dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
879         delete formatter;
880         return;
881     }
882     ParsePosition pos(0);
883     UDate myDate = formatter->parse(dateString, pos);
884     logln((UnicodeString)"Using " + bigD + " -> " + myDate);
885     if (myDate != expBigD) errln((UnicodeString)"FAIL: bigD - Expected " + dateToString(expBigD));
886     delete formatter;
887     formatter = new SimpleDateFormat(littleD, status);
888     ASSERT_OK(status);
889     pos = ParsePosition(0);
890     myDate = formatter->parse(dateString, pos);
891     logln((UnicodeString)"Using " + littleD + " -> " + dateToString(myDate));
892     if (myDate != expLittleD) errln((UnicodeString)"FAIL: littleD - Expected " + dateToString(expLittleD));
893     delete formatter;
894     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
895 }
896 
897 // -------------------------------------
898 
899 /**
900  * Test the day of year pattern.
901  */
902 void
TestDayOfYearPattern195()903 DateFormatTest::TestDayOfYearPattern195()
904 {
905     UErrorCode status = U_ZERO_ERROR;
906     UDate today = Calendar::getNow();
907     int32_t year,month,day,hour,min,sec; dateToFields(today,year,month,day,hour,min,sec);
908     UDate expected = date(year, month, day);
909     logln((UnicodeString)"Test Date: " + dateToString(today));
910     SimpleDateFormat* sdf = (SimpleDateFormat*)DateFormat::createDateInstance();
911     if (sdf == NULL){
912         dataerrln("Error calling DateFormat::createDateInstance()");
913         return;
914     }
915     tryPattern(*sdf, today, 0, expected);
916     tryPattern(*sdf, today, "G yyyy DDD", expected);
917     delete sdf;
918     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
919 }
920 
921 // -------------------------------------
922 
923 void
tryPattern(SimpleDateFormat & sdf,UDate d,const char * pattern,UDate expected)924 DateFormatTest::tryPattern(SimpleDateFormat& sdf, UDate d, const char* pattern, UDate expected)
925 {
926     UErrorCode status = U_ZERO_ERROR;
927     if (pattern != 0) sdf.applyPattern(pattern);
928     UnicodeString thePat;
929     logln((UnicodeString)"pattern: " + sdf.toPattern(thePat));
930     UnicodeString formatResult; (*(DateFormat*)&sdf).format(d, formatResult);
931     logln((UnicodeString)" format -> " + formatResult);
932     // try {
933         UDate d2 = sdf.parse(formatResult, status);
934         logln((UnicodeString)" parse(" + formatResult + ") -> " + dateToString(d2));
935         if (d2 != expected) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
936         UnicodeString format2; (*(DateFormat*)&sdf).format(d2, format2);
937         logln((UnicodeString)" format -> " + format2);
938         if (!(formatResult == format2)) errln((UnicodeString)"FAIL: Round trip drift");
939     //}
940     //catch(Exception e) {
941     if (U_FAILURE(status))
942         errln((UnicodeString)"Error: " + (int32_t)status);
943     //}
944 }
945 
946 // -------------------------------------
947 
948 /**
949  * Test the handling of single quotes in patterns.
950  */
951 void
TestQuotePattern161()952 DateFormatTest::TestQuotePattern161()
953 {
954     UErrorCode status = U_ZERO_ERROR;
955     SimpleDateFormat* formatter = new SimpleDateFormat((UnicodeString)"MM/dd/yyyy 'at' hh:mm:ss a zzz", status);
956     if (U_FAILURE(status)) {
957         dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
958         delete formatter;
959         return;
960     }
961     UDate currentTime_1 = date(97, UCAL_AUGUST, 13, 10, 42, 28);
962     UnicodeString dateString; ((DateFormat*)formatter)->format(currentTime_1, dateString);
963     UnicodeString exp("08/13/1997 at 10:42:28 AM ");
964     logln((UnicodeString)"format(" + dateToString(currentTime_1) + ") = " + dateString);
965     if (0 != dateString.compareBetween(0, exp.length(), exp, 0, exp.length())) errln((UnicodeString)"FAIL: Expected " + exp);
966     delete formatter;
967     if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
968 }
969 
970 // -------------------------------------
971 
972 /**
973  * Verify the correct behavior when handling invalid input strings.
974  */
975 void
TestBadInput135()976 DateFormatTest::TestBadInput135()
977 {
978     UErrorCode status = U_ZERO_ERROR;
979     DateFormat::EStyle looks[] = {
980         DateFormat::SHORT, DateFormat::MEDIUM, DateFormat::LONG, DateFormat::FULL
981     };
982     int32_t looks_length = UPRV_LENGTHOF(looks);
983     const char* strings[] = {
984         "Mar 15", "Mar 15 1997", "asdf", "3/1/97 1:23:", "3/1/00 1:23:45 AM"
985     };
986     int32_t strings_length = UPRV_LENGTHOF(strings);
987     DateFormat *full = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::LONG);
988     if(full==NULL) {
989       dataerrln("could not create date time instance");
990       return;
991     }
992     UnicodeString expected("March 1, 2000 at 1:23:45 AM ");
993     for (int32_t i = 0; i < strings_length;++i) {
994         const char* text = strings[i];
995         for (int32_t j = 0; j < looks_length;++j) {
996             DateFormat::EStyle dateLook = looks[j];
997             for (int32_t k = 0; k < looks_length;++k) {
998                 DateFormat::EStyle timeLook = looks[k];
999                 DateFormat *df = DateFormat::createDateTimeInstance(dateLook, timeLook);
1000                 if (df == NULL){
1001                     dataerrln("Error calling DateFormat::createDateTimeInstance()");
1002                     continue;
1003                 }
1004                 UnicodeString prefix = UnicodeString(text) + ", " + dateLook + "/" + timeLook + ": ";
1005                 //try {
1006                     UDate when = df->parse(text, status);
1007                     if (when == 0 && U_SUCCESS(status)) {
1008                         errln(prefix + "SHOULD NOT HAPPEN: parse returned 0.");
1009                         continue;
1010                     }
1011                     if (U_SUCCESS(status))
1012                     {
1013                         UnicodeString format;
1014                         UnicodeString pattern;
1015                         SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
1016                         if (sdtfmt != NULL) {
1017                             sdtfmt->toPattern(pattern);
1018                         }
1019                         full->format(when, format);
1020                         logln(prefix + "OK: " + format);
1021                         if (0!=format.compareBetween(0, expected.length(), expected, 0, expected.length()))
1022                             errln((UnicodeString)"FAIL: Parse \"" + text + "\", pattern \"" + pattern + "\", expected " + expected + " got " + format);
1023                     }
1024                 //}
1025                 //catch(ParseException e) {
1026                     else
1027                         status = U_ZERO_ERROR;
1028                 //}
1029                 //catch(StringIndexOutOfBoundsException e) {
1030                 //    errln(prefix + "SHOULD NOT HAPPEN: " + (int)status);
1031                 //}
1032                 delete df;
1033             }
1034         }
1035     }
1036     delete full;
1037     if (U_FAILURE(status))
1038         errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1039 }
1040 
1041 static const char* const parseFormats[] = {
1042     "MMMM d, yyyy",
1043     "MMMM d yyyy",
1044     "M/d/yy",
1045     "d MMMM, yyyy",
1046     "d MMMM yyyy",
1047     "d MMMM",
1048     "MMMM d",
1049     "yyyy",
1050     "h:mm a MMMM d, yyyy"
1051 };
1052 
1053 #if 0
1054 // strict inputStrings
1055 static const char* const inputStrings[] = {
1056     "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1057     "April 1, 1997", "April 1, 1997", 0, 0, 0, 0, 0, "April 1", 0, 0,
1058     "Jan 1, 1970", "January 1, 1970", 0, 0, 0, 0, 0, "January 1", 0, 0,
1059     "Jan 1 2037", 0, "January 1 2037", 0, 0, 0, 0, "January 1", 0, 0,
1060     "1/1/70", 0, 0, "1/1/70", 0, 0, 0, 0, "0001", 0,
1061     "5 May 1997", 0, 0, 0, 0, "5 May 1997", "5 May", 0, "0005", 0,
1062     "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1063     "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1064     "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1065     "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1066     "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1067 };
1068 #else
1069 // lenient inputStrings
1070 static const char* const inputStrings[] = {
1071     "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1072     "April 1, 1997", "April 1, 1997", "April 1 1997", "4/1/97", 0, 0, 0, "April 1", 0, 0,
1073     "Jan 1, 1970", "January 1, 1970", "January 1 1970", "1/1/70", 0, 0, 0, "January 1", 0, 0,
1074     "Jan 1 2037", "January 1, 2037", "January 1 2037", "1/1/37", 0, 0, 0, "January 1", 0, 0,
1075     "1/1/70", "January 1, 0070", "January 1 0070", "1/1/70", "1 January, 0070", "1 January 0070", "1 January", "January 1", "0001", 0,
1076     "5 May 1997", 0, 0, 0, "5 May, 1997", "5 May 1997", "5 May", 0, "0005", 0,
1077     "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1078     "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1079     "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1080     "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1081     "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1082 };
1083 #endif
1084 
1085 // -------------------------------------
1086 
1087 /**
1088  * Verify the correct behavior when parsing an array of inputs against an
1089  * array of patterns, with known results.  The results are encoded after
1090  * the input strings in each row.
1091  */
1092 void
TestBadInput135a()1093 DateFormatTest::TestBadInput135a()
1094 {
1095   UErrorCode status = U_ZERO_ERROR;
1096   SimpleDateFormat* dateParse = new SimpleDateFormat(status);
1097   if(U_FAILURE(status)) {
1098     dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1099     delete dateParse;
1100     return;
1101   }
1102   const char* s;
1103   UDate date;
1104   const uint32_t PF_LENGTH = UPRV_LENGTHOF(parseFormats);
1105   const uint32_t INPUT_LENGTH = UPRV_LENGTHOF(inputStrings);
1106 
1107   dateParse->applyPattern("d MMMM, yyyy");
1108   dateParse->adoptTimeZone(TimeZone::createDefault());
1109   s = "not parseable";
1110   UnicodeString thePat;
1111   logln(UnicodeString("Trying to parse \"") + s + "\" with " + dateParse->toPattern(thePat));
1112   //try {
1113   date = dateParse->parse(s, status);
1114   if (U_SUCCESS(status))
1115     errln((UnicodeString)"FAIL: Expected exception during parse");
1116   //}
1117   //catch(Exception ex) {
1118   else
1119     logln((UnicodeString)"Exception during parse: " + (int32_t)status);
1120   status = U_ZERO_ERROR;
1121   //}
1122   for (uint32_t i = 0; i < INPUT_LENGTH; i += (PF_LENGTH + 1)) {
1123     ParsePosition parsePosition(0);
1124     UnicodeString s( inputStrings[i]);
1125     for (uint32_t index = 0; index < PF_LENGTH;++index) {
1126       const char* expected = inputStrings[i + 1 + index];
1127       dateParse->applyPattern(parseFormats[index]);
1128       dateParse->adoptTimeZone(TimeZone::createDefault());
1129       //try {
1130       parsePosition.setIndex(0);
1131       date = dateParse->parse(s, parsePosition);
1132       if (parsePosition.getIndex() != 0) {
1133         UnicodeString s1, s2;
1134         s.extract(0, parsePosition.getIndex(), s1);
1135         s.extract(parsePosition.getIndex(), s.length(), s2);
1136         if (date == 0) {
1137           errln((UnicodeString)"ERROR: null result fmt=\"" +
1138                      parseFormats[index] +
1139                      "\" pos=" + parsePosition.getIndex() + " " +
1140                      s1 + "|" + s2);
1141         }
1142         else {
1143           UnicodeString result;
1144           ((DateFormat*)dateParse)->format(date, result);
1145           logln((UnicodeString)"Parsed \"" + s + "\" using \"" + dateParse->toPattern(thePat) + "\" to: " + result);
1146           if (expected == 0)
1147             errln((UnicodeString)"FAIL: Expected parse failure, got " + result);
1148           else if (!(result == expected))
1149             errln(UnicodeString("FAIL: Parse \"") + s + UnicodeString("\", expected ") + expected + UnicodeString(", got ") + result);
1150         }
1151       }
1152       else if (expected != 0) {
1153         errln(UnicodeString("FAIL: Expected ") + expected + " from \"" +
1154                      s + "\" with \"" + dateParse->toPattern(thePat) + "\"");
1155       }
1156       //}
1157       //catch(Exception ex) {
1158       if (U_FAILURE(status))
1159         errln((UnicodeString)"An exception was thrown during parse: " + (int32_t)status);
1160       //}
1161     }
1162   }
1163   delete dateParse;
1164   if (U_FAILURE(status))
1165     errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1166 }
1167 
1168 // -------------------------------------
1169 
1170 /**
1171  * Test the parsing of two-digit years.
1172  */
1173 void
TestTwoDigitYear()1174 DateFormatTest::TestTwoDigitYear()
1175 {
1176     UErrorCode ec = U_ZERO_ERROR;
1177     SimpleDateFormat fmt("dd/MM/yy", Locale::getUK(), ec);
1178     if (U_FAILURE(ec)) {
1179         dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1180         return;
1181     }
1182     parse2DigitYear(fmt, "5/6/30", date(130, UCAL_JUNE, 5));
1183     parse2DigitYear(fmt, "4/6/50", date(50, UCAL_JUNE, 4));
1184 }
1185 
1186 // -------------------------------------
1187 
1188 void
parse2DigitYear(DateFormat & fmt,const char * str,UDate expected)1189 DateFormatTest::parse2DigitYear(DateFormat& fmt, const char* str, UDate expected)
1190 {
1191     UErrorCode status = U_ZERO_ERROR;
1192     //try {
1193         UDate d = fmt.parse(str, status);
1194         UnicodeString thePat;
1195         logln(UnicodeString("Parsing \"") + str + "\" with " + ((SimpleDateFormat*)&fmt)->toPattern(thePat) +
1196             "  => " + dateToString(d));
1197         if (d != expected) errln((UnicodeString)"FAIL: Expected " + expected);
1198     //}
1199     //catch(ParseException e) {
1200         if (U_FAILURE(status))
1201         errln((UnicodeString)"FAIL: Got exception");
1202     //}
1203 }
1204 
1205 // -------------------------------------
1206 
1207 /**
1208  * Test the formatting of time zones.
1209  */
1210 void
TestDateFormatZone061()1211 DateFormatTest::TestDateFormatZone061()
1212 {
1213     UErrorCode status = U_ZERO_ERROR;
1214     UDate date;
1215     DateFormat *formatter;
1216     date= 859248000000.0;
1217     logln((UnicodeString)"Date 1997/3/25 00:00 GMT: " + date);
1218     formatter = new SimpleDateFormat((UnicodeString)"dd-MMM-yyyyy HH:mm", Locale::getUK(), status);
1219     if(U_FAILURE(status)) {
1220       dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1221       delete formatter;
1222       return;
1223     }
1224     formatter->adoptTimeZone(TimeZone::createTimeZone("GMT"));
1225     UnicodeString temp; formatter->format(date, temp);
1226     logln((UnicodeString)"Formatted in GMT to: " + temp);
1227     //try {
1228         UDate tempDate = formatter->parse(temp, status);
1229         logln((UnicodeString)"Parsed to: " + dateToString(tempDate));
1230         if (tempDate != date) errln((UnicodeString)"FAIL: Expected " + dateToString(date));
1231     //}
1232     //catch(Throwable t) {
1233     if (U_FAILURE(status))
1234         errln((UnicodeString)"Date Formatter throws: " + (int32_t)status);
1235     //}
1236     delete formatter;
1237 }
1238 
1239 // -------------------------------------
1240 
1241 /**
1242  * Test the formatting of time zones.
1243  */
1244 void
TestDateFormatZone146()1245 DateFormatTest::TestDateFormatZone146()
1246 {
1247     TimeZone *saveDefault = TimeZone::createDefault();
1248 
1249         //try {
1250     TimeZone *thedefault = TimeZone::createTimeZone("GMT");
1251     TimeZone::setDefault(*thedefault);
1252             // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
1253 
1254             // check to be sure... its GMT all right
1255         TimeZone *testdefault = TimeZone::createDefault();
1256         UnicodeString testtimezone;
1257         testdefault->getID(testtimezone);
1258         if (testtimezone == "GMT")
1259             logln("Test timezone = " + testtimezone);
1260         else
1261             dataerrln("Test timezone should be GMT, not " + testtimezone);
1262 
1263         UErrorCode status = U_ZERO_ERROR;
1264         // now try to use the default GMT time zone
1265         GregorianCalendar *greenwichcalendar =
1266             new GregorianCalendar(1997, 3, 4, 23, 0, status);
1267         if (U_FAILURE(status)) {
1268             dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
1269         } else {
1270             //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
1271             //greenwichcalendar.set(1997, 3, 4, 23, 0);
1272             // try anything to set hour to 23:00 !!!
1273             greenwichcalendar->set(UCAL_HOUR_OF_DAY, 23);
1274             // get time
1275             UDate greenwichdate = greenwichcalendar->getTime(status);
1276             // format every way
1277             UnicodeString DATA [] = {
1278                 UnicodeString("simple format:  "), UnicodeString("04/04/97 23:00 GMT"),
1279                     UnicodeString("MM/dd/yy HH:mm z"),
1280                 UnicodeString("full format:    "), UnicodeString("Friday, April 4, 1997 11:00:00 o'clock PM GMT"),
1281                     UnicodeString("EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z"),
1282                 UnicodeString("long format:    "), UnicodeString("April 4, 1997 11:00:00 PM GMT"),
1283                     UnicodeString("MMMM d, yyyy h:mm:ss a z"),
1284                 UnicodeString("default format: "), UnicodeString("04-Apr-97 11:00:00 PM"),
1285                     UnicodeString("dd-MMM-yy h:mm:ss a"),
1286                 UnicodeString("short format:   "), UnicodeString("4/4/97 11:00 PM"),
1287                     UnicodeString("M/d/yy h:mm a")
1288             };
1289             int32_t DATA_length = UPRV_LENGTHOF(DATA);
1290 
1291             for (int32_t i=0; i<DATA_length; i+=3) {
1292                 DateFormat *fmt = new SimpleDateFormat(DATA[i+2], Locale::getEnglish(), status);
1293                 if (U_FAILURE(status)) {
1294                     dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
1295                     break;
1296                 }
1297                 fmt->setCalendar(*greenwichcalendar);
1298                 UnicodeString result;
1299                 result = fmt->format(greenwichdate, result);
1300                 logln(DATA[i] + result);
1301                 if (result != DATA[i+1])
1302                     errln("FAIL: Expected " + DATA[i+1] + ", got " + result);
1303                 delete fmt;
1304             }
1305         }
1306     //}
1307     //finally {
1308         TimeZone::adoptDefault(saveDefault);
1309     //}
1310         delete testdefault;
1311         delete greenwichcalendar;
1312         delete thedefault;
1313 
1314 
1315 }
1316 
1317 // -------------------------------------
1318 
1319 /**
1320  * Test the formatting of dates in different locales.
1321  */
1322 void
TestLocaleDateFormat()1323 DateFormatTest::TestLocaleDateFormat() // Bug 495
1324 {
1325     UDate testDate = date(97, UCAL_SEPTEMBER, 15);
1326     DateFormat *dfFrench = DateFormat::createDateTimeInstance(DateFormat::FULL,
1327         DateFormat::FULL, Locale::getFrench());
1328     DateFormat *dfUS = DateFormat::createDateTimeInstance(DateFormat::FULL,
1329         DateFormat::FULL, Locale::getUS());
1330     UnicodeString expectedFRENCH ( "lundi 15 septembre 1997 \\u00E0 00:00:00 heure d\\u2019\\u00E9t\\u00E9 du Pacifique", -1, US_INV );
1331     expectedFRENCH = expectedFRENCH.unescape();
1332     UnicodeString expectedUS ( "Monday, September 15, 1997 at 12:00:00 AM Pacific Daylight Time" );
1333     logln((UnicodeString)"Date set to : " + dateToString(testDate));
1334     UnicodeString out;
1335     if (dfUS == NULL || dfFrench == NULL){
1336         dataerrln("Error calling DateFormat::createDateTimeInstance)");
1337         delete dfUS;
1338         delete dfFrench;
1339         return;
1340     }
1341 
1342     dfFrench->format(testDate, out);
1343     logln((UnicodeString)"Date Formated with French Locale " + out);
1344     if (!(out == expectedFRENCH))
1345         errln((UnicodeString)"FAIL: Expected " + expectedFRENCH);
1346     out.truncate(0);
1347     dfUS->format(testDate, out);
1348     logln((UnicodeString)"Date Formated with US Locale " + out);
1349     if (!(out == expectedUS))
1350         errln((UnicodeString)"FAIL: Expected " + expectedUS);
1351     delete dfUS;
1352     delete dfFrench;
1353 }
1354 
1355 void
TestFormattingLocaleTimeSeparator()1356 DateFormatTest::TestFormattingLocaleTimeSeparator()
1357 {
1358     // This test not as useful is it once was, since timeSeparator
1359     // in the Arabic is changed back to ":" in CLDR 28.
1360     const UDate testDate = 874266720000.;  // Sun Sep 14 21:52:00 CET 1997
1361     logln((UnicodeString)"Date set to : " + dateToString(testDate));
1362 
1363     const LocalPointer<const TimeZone> tz(TimeZone::createTimeZone("CET"));
1364 
1365     const LocalPointer<DateFormat> dfArab(DateFormat::createTimeInstance(
1366             DateFormat::SHORT, Locale("ar")));
1367 
1368     const LocalPointer<DateFormat> dfLatn(DateFormat::createTimeInstance(
1369             DateFormat::SHORT, Locale("ar", NULL, NULL, "numbers=latn")));
1370 
1371     if (dfLatn.isNull() || dfArab.isNull()) {
1372         dataerrln("Error calling DateFormat::createTimeInstance()");
1373         return;
1374     }
1375 
1376     dfArab->setTimeZone(*tz);
1377     dfLatn->setTimeZone(*tz);
1378 
1379     const UnicodeString expectedArab = UnicodeString(
1380             "\\u0669:\\u0665\\u0662 \\u0645", -1, US_INV).unescape();
1381 
1382     const UnicodeString expectedLatn = UnicodeString(
1383             "9:52 \\u0645", -1, US_INV).unescape();
1384 
1385     UnicodeString actualArab;
1386     UnicodeString actualLatn;
1387 
1388     dfArab->format(testDate, actualArab);
1389     dfLatn->format(testDate, actualLatn);
1390 
1391     assertEquals("Arab", expectedArab, actualArab);
1392     assertEquals("Latn", expectedLatn, actualLatn);
1393 }
1394 
1395 /**
1396  * Test DateFormat(Calendar) API
1397  */
TestDateFormatCalendar()1398 void DateFormatTest::TestDateFormatCalendar() {
1399     DateFormat *date=0, *time=0, *full=0;
1400     Calendar *cal=0;
1401     UnicodeString str;
1402     ParsePosition pos;
1403     UDate when;
1404     UErrorCode ec = U_ZERO_ERROR;
1405 
1406     /* Create a formatter for date fields. */
1407     date = DateFormat::createDateInstance(DateFormat::kShort, Locale::getUS());
1408     if (date == NULL) {
1409         dataerrln("FAIL: createDateInstance failed");
1410         goto FAIL;
1411     }
1412 
1413     /* Create a formatter for time fields. */
1414     time = DateFormat::createTimeInstance(DateFormat::kShort, Locale::getUS());
1415     if (time == NULL) {
1416         errln("FAIL: createTimeInstance failed");
1417         goto FAIL;
1418     }
1419 
1420     /* Create a full format for output */
1421     full = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull,
1422                                               Locale::getUS());
1423     if (full == NULL) {
1424         errln("FAIL: createInstance failed");
1425         goto FAIL;
1426     }
1427 
1428     /* Create a calendar */
1429     cal = Calendar::createInstance(Locale::getUS(), ec);
1430     if (cal == NULL || U_FAILURE(ec)) {
1431         errln((UnicodeString)"FAIL: Calendar::createInstance failed with " +
1432               u_errorName(ec));
1433         goto FAIL;
1434     }
1435 
1436     /* Parse the date */
1437     cal->clear();
1438     str = UnicodeString("4/5/2001", "");
1439     pos.setIndex(0);
1440     date->parse(str, *cal, pos);
1441     if (pos.getIndex() != str.length()) {
1442         errln((UnicodeString)"FAIL: DateFormat::parse(4/5/2001) failed at " +
1443               pos.getIndex());
1444         goto FAIL;
1445     }
1446 
1447     /* Parse the time */
1448     str = UnicodeString("5:45 PM", "");
1449     pos.setIndex(0);
1450     time->parse(str, *cal, pos);
1451     if (pos.getIndex() != str.length()) {
1452         errln((UnicodeString)"FAIL: DateFormat::parse(17:45) failed at " +
1453               pos.getIndex());
1454         goto FAIL;
1455     }
1456 
1457     /* Check result */
1458     when = cal->getTime(ec);
1459     if (U_FAILURE(ec)) {
1460         errln((UnicodeString)"FAIL: cal->getTime() failed with " + u_errorName(ec));
1461         goto FAIL;
1462     }
1463     str.truncate(0);
1464     full->format(when, str);
1465     // Thursday, April 5, 2001 5:45:00 PM PDT 986517900000
1466     if (when == 986517900000.0) {
1467         logln("Ok: Parsed result: " + str);
1468     } else {
1469         errln("FAIL: Parsed result: " + str + ", exp 4/5/2001 5:45 PM");
1470     }
1471 
1472  FAIL:
1473     delete date;
1474     delete time;
1475     delete full;
1476     delete cal;
1477 }
1478 
1479 /**
1480  * Test DateFormat's parsing of space characters.  See jitterbug 1916.
1481  */
TestSpaceParsing()1482 void DateFormatTest::TestSpaceParsing() {
1483     const char* DATA[] = {
1484         "yyyy MM dd HH:mm:ss",
1485 
1486         // pattern, input, expected parse or NULL if expect parse failure
1487         "MMMM d yy", " 04 05 06",  "2006 04 05 00:00:00",
1488         NULL,        "04 05 06",   "2006 04 05 00:00:00",
1489 
1490         "MM d yy",   " 04 05 06",    "2006 04 05 00:00:00",
1491         NULL,        "04 05 06",     "2006 04 05 00:00:00",
1492         NULL,        "04/05/06",     "2006 04 05 00:00:00",
1493         NULL,        "04-05-06",     "2006 04 05 00:00:00",
1494         NULL,        "04.05.06",     "2006 04 05 00:00:00",
1495         NULL,        "04 / 05 / 06", "2006 04 05 00:00:00",
1496         NULL,        "Apr / 05/ 06", "2006 04 05 00:00:00",
1497         NULL,        "Apr-05-06",    "2006 04 05 00:00:00",
1498         NULL,        "Apr 05, 2006", "2006 04 05 00:00:00",
1499 
1500         "MMMM d yy", " Apr 05 06", "2006 04 05 00:00:00",
1501         NULL,        "Apr 05 06",  "2006 04 05 00:00:00",
1502         NULL,        "Apr05 06",   "2006 04 05 00:00:00",
1503 
1504         "hh:mm:ss a", "12:34:56 PM", "1970 01 01 12:34:56",
1505         NULL,         "12:34:56PM",  "1970 01 01 12:34:56",
1506         NULL,         "12.34.56PM",  "1970 01 01 12:34:56",
1507         NULL,         "12 : 34 : 56  PM", "1970 01 01 12:34:56",
1508 
1509         "MM d yy 'at' hh:mm:ss a", "04/05/06 12:34:56 PM", "2006 04 05 12:34:56",
1510 
1511         "MMMM dd yyyy hh:mm a", "September 27, 1964 21:56 PM", "1964 09 28 09:56:00",
1512         NULL,                   "November 4, 2008 0:13 AM",    "2008 11 04 00:13:00",
1513 
1514         "HH'h'mm'min'ss's'", "12h34min56s", "1970 01 01 12:34:56",
1515         NULL,                "12h34mi56s",  "1970 01 01 12:34:56",
1516         NULL,                "12h34m56s",   "1970 01 01 12:34:56",
1517         NULL,                "12:34:56",    "1970 01 01 12:34:56"
1518     };
1519     const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1520 
1521     expectParse(DATA, DATA_len, Locale("en"));
1522 }
1523 
1524 /**
1525  * Test handling of "HHmmss" pattern.
1526  */
TestExactCountFormat()1527 void DateFormatTest::TestExactCountFormat() {
1528     const char* DATA[] = {
1529         "yyyy MM dd HH:mm:ss",
1530 
1531         // pattern, input, expected parse or NULL if expect parse failure
1532         "HHmmss", "123456", "1970 01 01 12:34:56",
1533         NULL,     "12345",  "1970 01 01 01:23:45",
1534         NULL,     "1234",   NULL,
1535         NULL,     "00-05",  NULL,
1536         NULL,     "12-34",  NULL,
1537         NULL,     "00+05",  NULL,
1538         "ahhmm",  "PM730",  "1970 01 01 19:30:00",
1539     };
1540     const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1541 
1542     expectParse(DATA, DATA_len, Locale("en"));
1543 }
1544 
1545 /**
1546  * Test handling of white space.
1547  */
TestWhiteSpaceParsing()1548 void DateFormatTest::TestWhiteSpaceParsing() {
1549     const char* DATA[] = {
1550         "yyyy MM dd",
1551 
1552         // pattern, input, expected parse or null if expect parse failure
1553 
1554         // Pattern space run should parse input text space run
1555         "MM   d yy",   " 04 01 03",    "2003 04 01",
1556         NULL,          " 04  01   03 ", "2003 04 01",
1557     };
1558     const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1559 
1560     expectParse(DATA, DATA_len, Locale("en"));
1561 }
1562 
1563 
TestInvalidPattern()1564 void DateFormatTest::TestInvalidPattern() {
1565     UErrorCode ec = U_ZERO_ERROR;
1566     SimpleDateFormat f(UnicodeString("Yesterday"), ec);
1567     if (U_FAILURE(ec)) {
1568         dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1569         return;
1570     }
1571     UnicodeString out;
1572     FieldPosition pos;
1573     f.format((UDate)0, out, pos);
1574     logln(out);
1575     // The bug is that the call to format() will crash.  By not
1576     // crashing, the test passes.
1577 }
1578 
TestGreekMay()1579 void DateFormatTest::TestGreekMay() {
1580     UErrorCode ec = U_ZERO_ERROR;
1581     UDate date = -9896080848000.0;
1582     SimpleDateFormat fmt("EEEE, dd MMMM yyyy h:mm:ss a", Locale("el", "", ""), ec);
1583     if (U_FAILURE(ec)) {
1584         dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1585         return;
1586     }
1587     UnicodeString str;
1588     fmt.format(date, str);
1589     ParsePosition pos(0);
1590     UDate d2 = fmt.parse(str, pos);
1591     if (date != d2) {
1592         errln("FAIL: unable to parse strings where case-folding changes length");
1593     }
1594 }
1595 
TestStandAloneMonths()1596 void DateFormatTest::TestStandAloneMonths()
1597 {
1598     const char *EN_DATA[] = {
1599         "yyyy MM dd HH:mm:ss",
1600 
1601         "yyyy LLLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 March 10 16:36:31", "2004 03 10 16:36:31",
1602         "yyyy LLL dd H:mm:ss",  "fp", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31",   "2004 03 10 16:36:31",
1603         "yyyy LLLL dd H:mm:ss", "F",  "2004 03 10 16:36:31", "2004 March 10 16:36:31",
1604         "yyyy LLL dd H:mm:ss",  "pf", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31",
1605 
1606         "LLLL", "fp", "1970 01 01 0:00:00", "January",   "1970 01 01 0:00:00",
1607         "LLLL", "fp", "1970 02 01 0:00:00", "February",  "1970 02 01 0:00:00",
1608         "LLLL", "fp", "1970 03 01 0:00:00", "March",     "1970 03 01 0:00:00",
1609         "LLLL", "fp", "1970 04 01 0:00:00", "April",     "1970 04 01 0:00:00",
1610         "LLLL", "fp", "1970 05 01 0:00:00", "May",       "1970 05 01 0:00:00",
1611         "LLLL", "fp", "1970 06 01 0:00:00", "June",      "1970 06 01 0:00:00",
1612         "LLLL", "fp", "1970 07 01 0:00:00", "July",      "1970 07 01 0:00:00",
1613         "LLLL", "fp", "1970 08 01 0:00:00", "August",    "1970 08 01 0:00:00",
1614         "LLLL", "fp", "1970 09 01 0:00:00", "September", "1970 09 01 0:00:00",
1615         "LLLL", "fp", "1970 10 01 0:00:00", "October",   "1970 10 01 0:00:00",
1616         "LLLL", "fp", "1970 11 01 0:00:00", "November",  "1970 11 01 0:00:00",
1617         "LLLL", "fp", "1970 12 01 0:00:00", "December",  "1970 12 01 0:00:00",
1618 
1619         "LLL", "fp", "1970 01 01 0:00:00", "Jan", "1970 01 01 0:00:00",
1620         "LLL", "fp", "1970 02 01 0:00:00", "Feb", "1970 02 01 0:00:00",
1621         "LLL", "fp", "1970 03 01 0:00:00", "Mar", "1970 03 01 0:00:00",
1622         "LLL", "fp", "1970 04 01 0:00:00", "Apr", "1970 04 01 0:00:00",
1623         "LLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1624         "LLL", "fp", "1970 06 01 0:00:00", "Jun", "1970 06 01 0:00:00",
1625         "LLL", "fp", "1970 07 01 0:00:00", "Jul", "1970 07 01 0:00:00",
1626         "LLL", "fp", "1970 08 01 0:00:00", "Aug", "1970 08 01 0:00:00",
1627         "LLL", "fp", "1970 09 01 0:00:00", "Sep", "1970 09 01 0:00:00",
1628         "LLL", "fp", "1970 10 01 0:00:00", "Oct", "1970 10 01 0:00:00",
1629         "LLL", "fp", "1970 11 01 0:00:00", "Nov", "1970 11 01 0:00:00",
1630         "LLL", "fp", "1970 12 01 0:00:00", "Dec", "1970 12 01 0:00:00",
1631     };
1632 
1633     const char *CS_DATA[] = {
1634         "yyyy MM dd HH:mm:ss",
1635 
1636         "yyyy LLLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 duben 10 16:36:31", "2004 04 10 16:36:31",
1637         "yyyy MMMM dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31",
1638         "yyyy LLL dd H:mm:ss",  "fp", "2004 04 10 16:36:31", "2004 dub 10 16:36:31",   "2004 04 10 16:36:31",
1639         "yyyy LLLL dd H:mm:ss", "F",  "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1640         "yyyy MMMM dd H:mm:ss", "F",  "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1641         "yyyy LLLL dd H:mm:ss", "pf", "2004 duben 10 16:36:31", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1642         "yyyy MMMM dd H:mm:ss", "pf", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1643 
1644         "LLLL", "fp", "1970 01 01 0:00:00", "leden",               "1970 01 01 0:00:00",
1645         "LLLL", "fp", "1970 02 01 0:00:00", "\\u00FAnor",           "1970 02 01 0:00:00",
1646         "LLLL", "fp", "1970 03 01 0:00:00", "b\\u0159ezen",         "1970 03 01 0:00:00",
1647         "LLLL", "fp", "1970 04 01 0:00:00", "duben",               "1970 04 01 0:00:00",
1648         "LLLL", "fp", "1970 05 01 0:00:00", "kv\\u011Bten",         "1970 05 01 0:00:00",
1649         "LLLL", "fp", "1970 06 01 0:00:00", "\\u010Derven",         "1970 06 01 0:00:00",
1650         "LLLL", "fp", "1970 07 01 0:00:00", "\\u010Dervenec",       "1970 07 01 0:00:00",
1651         "LLLL", "fp", "1970 08 01 0:00:00", "srpen",               "1970 08 01 0:00:00",
1652         "LLLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159\\u00ED", "1970 09 01 0:00:00",
1653         "LLLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDjen",     "1970 10 01 0:00:00",
1654         "LLLL", "fp", "1970 11 01 0:00:00", "listopad",            "1970 11 01 0:00:00",
1655         "LLLL", "fp", "1970 12 01 0:00:00", "prosinec",            "1970 12 01 0:00:00",
1656 
1657         "LLL", "fp", "1970 01 01 0:00:00", "led",  "1970 01 01 0:00:00",
1658         "LLL", "fp", "1970 02 01 0:00:00", "\\u00FAno",  "1970 02 01 0:00:00",
1659         "LLL", "fp", "1970 03 01 0:00:00", "b\\u0159e",  "1970 03 01 0:00:00",
1660         "LLL", "fp", "1970 04 01 0:00:00", "dub",  "1970 04 01 0:00:00",
1661         "LLL", "fp", "1970 05 01 0:00:00", "kv\\u011B",  "1970 05 01 0:00:00",
1662         "LLL", "fp", "1970 06 01 0:00:00", "\\u010Dvn",  "1970 06 01 0:00:00",
1663         "LLL", "fp", "1970 07 01 0:00:00", "\\u010Dvc",  "1970 07 01 0:00:00",
1664         "LLL", "fp", "1970 08 01 0:00:00", "srp",  "1970 08 01 0:00:00",
1665         "LLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159",  "1970 09 01 0:00:00",
1666         "LLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDj", "1970 10 01 0:00:00",
1667         "LLL", "fp", "1970 11 01 0:00:00", "lis", "1970 11 01 0:00:00",
1668         "LLL", "fp", "1970 12 01 0:00:00", "pro", "1970 12 01 0:00:00",
1669     };
1670 
1671     expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1672     expect(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1673 }
1674 
TestStandAloneDays()1675 void DateFormatTest::TestStandAloneDays()
1676 {
1677     const char *EN_DATA[] = {
1678         "yyyy MM dd HH:mm:ss",
1679 
1680         "cccc", "fp", "1970 01 04 0:00:00", "Sunday",    "1970 01 04 0:00:00",
1681         "cccc", "fp", "1970 01 05 0:00:00", "Monday",    "1970 01 05 0:00:00",
1682         "cccc", "fp", "1970 01 06 0:00:00", "Tuesday",   "1970 01 06 0:00:00",
1683         "cccc", "fp", "1970 01 07 0:00:00", "Wednesday", "1970 01 07 0:00:00",
1684         "cccc", "fp", "1970 01 01 0:00:00", "Thursday",  "1970 01 01 0:00:00",
1685         "cccc", "fp", "1970 01 02 0:00:00", "Friday",    "1970 01 02 0:00:00",
1686         "cccc", "fp", "1970 01 03 0:00:00", "Saturday",  "1970 01 03 0:00:00",
1687 
1688         "ccc", "fp", "1970 01 04 0:00:00", "Sun", "1970 01 04 0:00:00",
1689         "ccc", "fp", "1970 01 05 0:00:00", "Mon", "1970 01 05 0:00:00",
1690         "ccc", "fp", "1970 01 06 0:00:00", "Tue", "1970 01 06 0:00:00",
1691         "ccc", "fp", "1970 01 07 0:00:00", "Wed", "1970 01 07 0:00:00",
1692         "ccc", "fp", "1970 01 01 0:00:00", "Thu", "1970 01 01 0:00:00",
1693         "ccc", "fp", "1970 01 02 0:00:00", "Fri", "1970 01 02 0:00:00",
1694         "ccc", "fp", "1970 01 03 0:00:00", "Sat", "1970 01 03 0:00:00",
1695     };
1696 
1697     const char *CS_DATA[] = {
1698         "yyyy MM dd HH:mm:ss",
1699 
1700         "cccc", "fp", "1970 01 04 0:00:00", "ned\\u011Ble",       "1970 01 04 0:00:00",
1701         "cccc", "fp", "1970 01 05 0:00:00", "pond\\u011Bl\\u00ED", "1970 01 05 0:00:00",
1702         "cccc", "fp", "1970 01 06 0:00:00", "\\u00FAter\\u00FD",   "1970 01 06 0:00:00",
1703         "cccc", "fp", "1970 01 07 0:00:00", "st\\u0159eda",       "1970 01 07 0:00:00",
1704         "cccc", "fp", "1970 01 01 0:00:00", "\\u010Dtvrtek",      "1970 01 01 0:00:00",
1705         "cccc", "fp", "1970 01 02 0:00:00", "p\\u00E1tek",        "1970 01 02 0:00:00",
1706         "cccc", "fp", "1970 01 03 0:00:00", "sobota",            "1970 01 03 0:00:00",
1707 
1708         "ccc", "fp", "1970 01 04 0:00:00", "ne",      "1970 01 04 0:00:00",
1709         "ccc", "fp", "1970 01 05 0:00:00", "po",      "1970 01 05 0:00:00",
1710         "ccc", "fp", "1970 01 06 0:00:00", "\\u00FAt", "1970 01 06 0:00:00",
1711         "ccc", "fp", "1970 01 07 0:00:00", "st",      "1970 01 07 0:00:00",
1712         "ccc", "fp", "1970 01 01 0:00:00", "\\u010Dt", "1970 01 01 0:00:00",
1713         "ccc", "fp", "1970 01 02 0:00:00", "p\\u00E1", "1970 01 02 0:00:00",
1714         "ccc", "fp", "1970 01 03 0:00:00", "so",      "1970 01 03 0:00:00",
1715     };
1716 
1717     expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1718     expect(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1719 }
1720 
TestShortDays()1721 void DateFormatTest::TestShortDays()
1722 {
1723     const char *EN_DATA[] = {
1724         "yyyy MM dd HH:mm:ss",
1725 
1726         "EEEEEE, MMM d y", "fp", "2013 01 13 0:00:00", "Su, Jan 13 2013", "2013 01 13 0:00:00",
1727         "EEEEEE, MMM d y", "fp", "2013 01 16 0:00:00", "We, Jan 16 2013", "2013 01 16 0:00:00",
1728         "EEEEEE d",        "fp", "1970 01 17 0:00:00", "Sa 17",           "1970 01 17 0:00:00",
1729         "cccccc d",        "fp", "1970 01 17 0:00:00", "Sa 17",           "1970 01 17 0:00:00",
1730         "cccccc",          "fp", "1970 01 03 0:00:00", "Sa",              "1970 01 03 0:00:00",
1731     };
1732     const char *SV_DATA[] = {
1733         "yyyy MM dd HH:mm:ss",
1734 
1735         "EEEEEE d MMM y",  "fp", "2013 01 13 0:00:00", "s\\u00F6 13 jan. 2013", "2013 01 13 0:00:00",
1736         "EEEEEE d MMM y",  "fp", "2013 01 16 0:00:00", "on 16 jan. 2013",       "2013 01 16 0:00:00",
1737         "EEEEEE d",        "fp", "1970 01 17 0:00:00", "l\\u00F6 17",          "1970 01 17 0:00:00",
1738         "cccccc d",        "fp", "1970 01 17 0:00:00", "l\\u00F6 17",          "1970 01 17 0:00:00",
1739         "cccccc",          "fp", "1970 01 03 0:00:00", "l\\u00F6",             "1970 01 03 0:00:00",
1740     };
1741     expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1742     expect(SV_DATA, UPRV_LENGTHOF(SV_DATA), Locale("sv", "", ""));
1743 }
1744 
TestNarrowNames()1745 void DateFormatTest::TestNarrowNames()
1746 {
1747     const char *EN_DATA[] = {
1748             "yyyy MM dd HH:mm:ss",
1749 
1750             "yyyy MMMMM dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1751             "yyyy LLLLL dd H:mm:ss",  "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1752 
1753             "MMMMM", "1970 01 01 0:00:00", "J",
1754             "MMMMM", "1970 02 01 0:00:00", "F",
1755             "MMMMM", "1970 03 01 0:00:00", "M",
1756             "MMMMM", "1970 04 01 0:00:00", "A",
1757             "MMMMM", "1970 05 01 0:00:00", "M",
1758             "MMMMM", "1970 06 01 0:00:00", "J",
1759             "MMMMM", "1970 07 01 0:00:00", "J",
1760             "MMMMM", "1970 08 01 0:00:00", "A",
1761             "MMMMM", "1970 09 01 0:00:00", "S",
1762             "MMMMM", "1970 10 01 0:00:00", "O",
1763             "MMMMM", "1970 11 01 0:00:00", "N",
1764             "MMMMM", "1970 12 01 0:00:00", "D",
1765 
1766             "LLLLL", "1970 01 01 0:00:00", "J",
1767             "LLLLL", "1970 02 01 0:00:00", "F",
1768             "LLLLL", "1970 03 01 0:00:00", "M",
1769             "LLLLL", "1970 04 01 0:00:00", "A",
1770             "LLLLL", "1970 05 01 0:00:00", "M",
1771             "LLLLL", "1970 06 01 0:00:00", "J",
1772             "LLLLL", "1970 07 01 0:00:00", "J",
1773             "LLLLL", "1970 08 01 0:00:00", "A",
1774             "LLLLL", "1970 09 01 0:00:00", "S",
1775             "LLLLL", "1970 10 01 0:00:00", "O",
1776             "LLLLL", "1970 11 01 0:00:00", "N",
1777             "LLLLL", "1970 12 01 0:00:00", "D",
1778 
1779             "EEEEE", "1970 01 04 0:00:00", "S",
1780             "EEEEE", "1970 01 05 0:00:00", "M",
1781             "EEEEE", "1970 01 06 0:00:00", "T",
1782             "EEEEE", "1970 01 07 0:00:00", "W",
1783             "EEEEE", "1970 01 01 0:00:00", "T",
1784             "EEEEE", "1970 01 02 0:00:00", "F",
1785             "EEEEE", "1970 01 03 0:00:00", "S",
1786 
1787             "ccccc", "1970 01 04 0:00:00", "S",
1788             "ccccc", "1970 01 05 0:00:00", "M",
1789             "ccccc", "1970 01 06 0:00:00", "T",
1790             "ccccc", "1970 01 07 0:00:00", "W",
1791             "ccccc", "1970 01 01 0:00:00", "T",
1792             "ccccc", "1970 01 02 0:00:00", "F",
1793             "ccccc", "1970 01 03 0:00:00", "S",
1794 
1795             "h:mm a",     "2015 01 01 10:00:00", "10:00 AM",
1796             "h:mm a",     "2015 01 01 22:00:00", "10:00 PM",
1797             "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a",
1798             "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p",
1799         };
1800 
1801         const char *CS_DATA[] = {
1802             "yyyy MM dd HH:mm:ss",
1803 
1804             "yyyy LLLLL dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1805             "yyyy MMMMM dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1806 
1807             "MMMMM", "1970 01 01 0:00:00", "1",
1808             "MMMMM", "1970 02 01 0:00:00", "2",
1809             "MMMMM", "1970 03 01 0:00:00", "3",
1810             "MMMMM", "1970 04 01 0:00:00", "4",
1811             "MMMMM", "1970 05 01 0:00:00", "5",
1812             "MMMMM", "1970 06 01 0:00:00", "6",
1813             "MMMMM", "1970 07 01 0:00:00", "7",
1814             "MMMMM", "1970 08 01 0:00:00", "8",
1815             "MMMMM", "1970 09 01 0:00:00", "9",
1816             "MMMMM", "1970 10 01 0:00:00", "10",
1817             "MMMMM", "1970 11 01 0:00:00", "11",
1818             "MMMMM", "1970 12 01 0:00:00", "12",
1819 
1820             "LLLLL", "1970 01 01 0:00:00", "1",
1821             "LLLLL", "1970 02 01 0:00:00", "2",
1822             "LLLLL", "1970 03 01 0:00:00", "3",
1823             "LLLLL", "1970 04 01 0:00:00", "4",
1824             "LLLLL", "1970 05 01 0:00:00", "5",
1825             "LLLLL", "1970 06 01 0:00:00", "6",
1826             "LLLLL", "1970 07 01 0:00:00", "7",
1827             "LLLLL", "1970 08 01 0:00:00", "8",
1828             "LLLLL", "1970 09 01 0:00:00", "9",
1829             "LLLLL", "1970 10 01 0:00:00", "10",
1830             "LLLLL", "1970 11 01 0:00:00", "11",
1831             "LLLLL", "1970 12 01 0:00:00", "12",
1832 
1833             "EEEEE", "1970 01 04 0:00:00", "N",
1834             "EEEEE", "1970 01 05 0:00:00", "P",
1835             "EEEEE", "1970 01 06 0:00:00", "\\u00DA",
1836             "EEEEE", "1970 01 07 0:00:00", "S",
1837             "EEEEE", "1970 01 01 0:00:00", "\\u010C",
1838             "EEEEE", "1970 01 02 0:00:00", "P",
1839             "EEEEE", "1970 01 03 0:00:00", "S",
1840 
1841             "ccccc", "1970 01 04 0:00:00", "N",
1842             "ccccc", "1970 01 05 0:00:00", "P",
1843             "ccccc", "1970 01 06 0:00:00", "\\u00DA",
1844             "ccccc", "1970 01 07 0:00:00", "S",
1845             "ccccc", "1970 01 01 0:00:00", "\\u010C",
1846             "ccccc", "1970 01 02 0:00:00", "P",
1847             "ccccc", "1970 01 03 0:00:00", "S",
1848 
1849             "h:mm a",     "2015 01 01 10:00:00", "10:00 dop.",
1850             "h:mm a",     "2015 01 01 22:00:00", "10:00 odp.",
1851             "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 dop.",
1852             "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 odp.",
1853         };
1854 
1855         const char *CA_DATA[] = {
1856             "yyyy MM dd HH:mm:ss",
1857 
1858             "h:mm a",     "2015 01 01 10:00:00", "10:00 a. m.",
1859             "h:mm a",     "2015 01 01 22:00:00", "10:00 p. m.",
1860             "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a. m.",
1861             "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p. m.",
1862         };
1863 
1864       expectFormat(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1865       expectFormat(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1866       expectFormat(CA_DATA, UPRV_LENGTHOF(CA_DATA), Locale("ca", "", ""));
1867 }
1868 
TestEras()1869 void DateFormatTest::TestEras()
1870 {
1871     const char *EN_DATA[] = {
1872         "yyyy MM dd",
1873 
1874         "MMMM dd yyyy G",    "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
1875         "MMMM dd yyyy GG",   "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
1876         "MMMM dd yyyy GGG",  "fp", "1951 07 17", "July 17 1951 AD",          "1951 07 17",
1877         "MMMM dd yyyy GGGG", "fp", "1951 07 17", "July 17 1951 Anno Domini", "1951 07 17",
1878 
1879         "MMMM dd yyyy G",    "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
1880         "MMMM dd yyyy GG",   "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
1881         "MMMM dd yyyy GGG",  "fp", "-438 07 17", "July 17 0439 BC",            "-438 07 17",
1882         "MMMM dd yyyy GGGG", "fp", "-438 07 17", "July 17 0439 Before Christ", "-438 07 17",
1883     };
1884 
1885     expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1886 }
1887 
TestQuarters()1888 void DateFormatTest::TestQuarters()
1889 {
1890     const char *EN_DATA[] = {
1891         "yyyy MM dd",
1892 
1893         "Q",    "fp", "1970 01 01", "1",           "1970 01 01",
1894         "QQ",   "fp", "1970 04 01", "02",          "1970 04 01",
1895         "QQQ",  "fp", "1970 07 01", "Q3",          "1970 07 01",
1896         "QQQQ", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1897 
1898         "q",    "fp", "1970 01 01", "1",           "1970 01 01",
1899         "qq",   "fp", "1970 04 01", "02",          "1970 04 01",
1900         "qqq",  "fp", "1970 07 01", "Q3",          "1970 07 01",
1901         "qqqq", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1902 
1903         "Qyy",  "fp", "2015 04 01", "215",         "2015 04 01",
1904         "QQyy", "fp", "2015 07 01", "0315",        "2015 07 01",
1905     };
1906 
1907     expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1908 }
1909 
1910 /**
1911  * Test parsing.  Input is an array that starts with the following
1912  * header:
1913  *
1914  * [0]   = pattern string to parse [i+2] with
1915  *
1916  * followed by test cases, each of which is 3 array elements:
1917  *
1918  * [i]   = pattern, or NULL to reuse prior pattern
1919  * [i+1] = input string
1920  * [i+2] = expected parse result (parsed with pattern [0])
1921  *
1922  * If expect parse failure, then [i+2] should be NULL.
1923  */
expectParse(const char ** data,int32_t data_length,const Locale & loc)1924 void DateFormatTest::expectParse(const char** data, int32_t data_length,
1925                                  const Locale& loc) {
1926     const UDate FAIL = (UDate) -1;
1927     const UnicodeString FAIL_STR("parse failure");
1928     int32_t i = 0;
1929 
1930     UErrorCode ec = U_ZERO_ERROR;
1931     SimpleDateFormat fmt("", loc, ec);
1932     SimpleDateFormat ref(data[i++], loc, ec);
1933     SimpleDateFormat gotfmt("G yyyy MM dd HH:mm:ss z", loc, ec);
1934     if (U_FAILURE(ec)) {
1935         dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1936         return;
1937     }
1938 
1939     const char* currentPat = NULL;
1940     while (i<data_length) {
1941         const char* pattern  = data[i++];
1942         const char* input    = data[i++];
1943         const char* expected = data[i++];
1944 
1945         ec = U_ZERO_ERROR;
1946         if (pattern != NULL) {
1947             fmt.applyPattern(pattern);
1948             currentPat = pattern;
1949         }
1950         UDate got = fmt.parse(input, ec);
1951         UnicodeString gotstr(FAIL_STR);
1952         if (U_FAILURE(ec)) {
1953             got = FAIL;
1954         } else {
1955             gotstr.remove();
1956             gotfmt.format(got, gotstr);
1957         }
1958 
1959         UErrorCode ec2 = U_ZERO_ERROR;
1960         UDate exp = FAIL;
1961         UnicodeString expstr(FAIL_STR);
1962         if (expected != NULL) {
1963             expstr = expected;
1964             exp = ref.parse(expstr, ec2);
1965             if (U_FAILURE(ec2)) {
1966                 // This only happens if expected is in wrong format --
1967                 // should never happen once test is debugged.
1968                 errln("FAIL: Internal test error");
1969                 return;
1970             }
1971         }
1972 
1973         if (got == exp) {
1974             logln((UnicodeString)"Ok: " + input + " x " +
1975                   currentPat + " => " + gotstr);
1976         } else {
1977             errln((UnicodeString)"FAIL: " + input + " x " +
1978                   currentPat + " => " + gotstr + ", expected " +
1979                   expstr);
1980         }
1981     }
1982 }
1983 
1984 /**
1985  * Test formatting and parsing.  Input is an array that starts
1986  * with the following header:
1987  *
1988  * [0]   = pattern string to parse [i+2] with
1989  *
1990  * followed by test cases, each of which is 3 array elements:
1991  *
1992  * [i]   = pattern, or null to reuse prior pattern
1993  * [i+1] = control string, either "fp", "pf", or "F".
1994  * [i+2..] = data strings
1995  *
1996  * The number of data strings depends on the control string.
1997  * Examples:
1998  * 1. "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.56", "2004 03 10 16:36:31.560",
1999  * 'f': Format date [i+2] (as parsed using pattern [0]) and expect string [i+3].
2000  * 'p': Parse string [i+3] and expect date [i+4].
2001  *
2002  * 2. "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567"
2003  * 'F': Format date [i+2] and expect string [i+3],
2004  *      then parse string [i+3] and expect date [i+2].
2005  *
2006  * 3. "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5670",
2007  * 'p': Parse string [i+2] and expect date [i+3].
2008  * 'f': Format date [i+3] and expect string [i+4].
2009  */
expect(const char ** data,int32_t data_length,const Locale & loc)2010 void DateFormatTest::expect(const char** data, int32_t data_length,
2011                             const Locale& loc) {
2012     int32_t i = 0;
2013     UErrorCode ec = U_ZERO_ERROR;
2014     UnicodeString str, str2;
2015     SimpleDateFormat fmt("", loc, ec);
2016     SimpleDateFormat ref(data[i++], loc, ec);
2017     SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2018     if (U_FAILURE(ec)) {
2019         dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2020         return;
2021     }
2022 
2023     UnicodeString currentPat;
2024     while (i<data_length) {
2025         const char* pattern  = data[i++];
2026         if (pattern != NULL) {
2027             fmt.applyPattern(pattern);
2028             currentPat = pattern;
2029         }
2030 
2031         const char* control = data[i++];
2032 
2033         if (uprv_strcmp(control, "fp") == 0) {
2034             // 'f'
2035             const char* datestr = data[i++];
2036             const char* string = data[i++];
2037             UDate date = ref.parse(ctou(datestr), ec);
2038             if (!assertSuccess("parse", ec)) return;
2039             assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2040                          ctou(string),
2041                          fmt.format(date, str.remove()));
2042             // 'p'
2043             datestr = data[i++];
2044             date = ref.parse(ctou(datestr), ec);
2045             if (!assertSuccess("parse", ec)) return;
2046             UDate parsedate = fmt.parse(ctou(string), ec);
2047             if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2048                 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2049                              univ.format(date, str.remove()),
2050                              univ.format(parsedate, str2.remove()));
2051             }
2052         }
2053 
2054         else if (uprv_strcmp(control, "pf") == 0) {
2055             // 'p'
2056             const char* string = data[i++];
2057             const char* datestr = data[i++];
2058             UDate date = ref.parse(ctou(datestr), ec);
2059             if (!assertSuccess("parse", ec)) return;
2060             UDate parsedate = fmt.parse(ctou(string), ec);
2061             if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2062                 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2063                              univ.format(date, str.remove()),
2064                              univ.format(parsedate, str2.remove()));
2065             }
2066             // 'f'
2067             string = data[i++];
2068             assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2069                          ctou(string),
2070                          fmt.format(date, str.remove()));
2071         }
2072 
2073         else if (uprv_strcmp(control, "F") == 0) {
2074             const char* datestr  = data[i++];
2075             const char* string   = data[i++];
2076             UDate date = ref.parse(ctou(datestr), ec);
2077             if (!assertSuccess("parse", ec)) return;
2078             assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2079                          ctou(string),
2080                          fmt.format(date, str.remove()));
2081 
2082             UDate parsedate = fmt.parse(string, ec);
2083             if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2084                 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2085                              univ.format(date, str.remove()),
2086                              univ.format(parsedate, str2.remove()));
2087             }
2088         }
2089 
2090         else {
2091             errln((UnicodeString)"FAIL: Invalid control string " + control);
2092             return;
2093         }
2094     }
2095 }
2096 
2097 /**
2098  * Test formatting.  Input is an array that starts
2099  * with the following header:
2100  *
2101  * [0]   = pattern string to parse [i+2] with
2102  *
2103  * followed by test cases, each of which is 3 array elements:
2104  *
2105  * [i]   = pattern, or null to reuse prior pattern
2106  * [i+1] = data string a
2107  * [i+2] = data string b
2108  *
2109  * Examples:
2110  * Format date [i+1] and expect string [i+2].
2111  *
2112  * "y/M/d H:mm:ss.SSSS", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567"
2113  */
expectFormat(const char ** data,int32_t data_length,const Locale & loc)2114 void DateFormatTest::expectFormat(const char** data, int32_t data_length,
2115                             const Locale& loc) {
2116     int32_t i = 0;
2117     UErrorCode ec = U_ZERO_ERROR;
2118     UnicodeString str, str2;
2119     SimpleDateFormat fmt("", loc, ec);
2120     SimpleDateFormat ref(data[i++], loc, ec);
2121     SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2122     if (U_FAILURE(ec)) {
2123         dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2124         return;
2125     }
2126 
2127     UnicodeString currentPat;
2128 
2129     while (i<data_length) {
2130         const char* pattern  = data[i++];
2131         if (pattern != NULL) {
2132             fmt.applyPattern(pattern);
2133             currentPat = pattern;
2134         }
2135 
2136         const char* datestr = data[i++];
2137         const char* string = data[i++];
2138         UDate date = ref.parse(ctou(datestr), ec);
2139         if (!assertSuccess("parse", ec)) return;
2140         assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2141                         ctou(string),
2142                         fmt.format(date, str.remove()));
2143     }
2144 }
2145 
TestGenericTime()2146 void DateFormatTest::TestGenericTime() {
2147   const Locale en("en");
2148   // Note: We no longer parse strings in different styles.
2149 /*
2150   const char* ZDATA[] = {
2151         "yyyy MM dd HH:mm zzz",
2152         // round trip
2153         "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2154         "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2155         "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2156         "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2157         // non-generic timezone string influences dst offset even if wrong for date/time
2158         "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
2159         "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 Pacific Time",
2160         "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
2161         "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 Pacific Time",
2162         // generic timezone generates dst offset appropriate for local time
2163         "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2164         "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2165         "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2166         "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2167         // daylight savings time transition edge cases.
2168         // time to parse does not really exist, PT interpreted as earlier time
2169         "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2170         "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2171         "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
2172         "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2173         "y/M/d H:mm v", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2174         "y/M/d H:mm v", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT",
2175         "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2176         // time to parse is ambiguous, PT interpreted as later time
2177         "y/M/d H:mm zzz", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PST",
2178         "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30  01:30 PST", "2005/10/30 1:30 PT",
2179         "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2180 
2181         "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2182         "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2183         "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
2184         "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2185         "y/M/d H:mm v", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2186         "y/M/d H:mm v", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PT",
2187         "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2188   };
2189 */
2190   const char* ZDATA[] = {
2191         "yyyy MM dd HH:mm zzz",
2192         // round trip
2193         "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2194         "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2195         "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2196         "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2197         // non-generic timezone string influences dst offset even if wrong for date/time
2198         "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
2199         "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
2200         // generic timezone generates dst offset appropriate for local time
2201         "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PST", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2202         "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 Pacific Time", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2203         "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2204         "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 Pacific Time", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2205         // daylight savings time transition edge cases.
2206         // time to parse does not really exist, PT interpreted as earlier time
2207         "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2208         "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
2209         "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2210         "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2211         // time to parse is ambiguous, PT interpreted as later time
2212         "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30  01:30 PST", "2005/10/30 1:30 PT",
2213         "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2214 
2215         "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2216         "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
2217         "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2218         "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2219   };
2220 
2221   const int32_t ZDATA_length = UPRV_LENGTHOF(ZDATA);
2222   expect(ZDATA, ZDATA_length, en);
2223 
2224   UErrorCode status = U_ZERO_ERROR;
2225 
2226   logln("cross format/parse tests");    // Note: We no longer support cross format/parse
2227   UnicodeString basepat("yy/MM/dd H:mm ");
2228   SimpleDateFormat formats[] = {
2229     SimpleDateFormat(basepat + "vvv", en, status),
2230     SimpleDateFormat(basepat + "vvvv", en, status),
2231     SimpleDateFormat(basepat + "zzz", en, status),
2232     SimpleDateFormat(basepat + "zzzz", en, status)
2233   };
2234   if (U_FAILURE(status)) {
2235     dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(status));
2236     return;
2237   }
2238   const int32_t formats_length = UPRV_LENGTHOF(formats);
2239 
2240   UnicodeString test;
2241   SimpleDateFormat univ("yyyy MM dd HH:mm zzz", en, status);
2242   ASSERT_OK(status);
2243   const UnicodeString times[] = {
2244     "2004 01 02 03:04 PST",
2245     "2004 07 08 09:10 PDT"
2246   };
2247   int32_t times_length = UPRV_LENGTHOF(times);
2248   for (int i = 0; i < times_length; ++i) {
2249     UDate d = univ.parse(times[i], status);
2250     logln(UnicodeString("\ntime: ") + d);
2251     for (int j = 0; j < formats_length; ++j) {
2252       test.remove();
2253       formats[j].format(d, test);
2254       logln("\ntest: '" + test + "'");
2255       for (int k = 0; k < formats_length; ++k) {
2256         UDate t = formats[k].parse(test, status);
2257         if (U_SUCCESS(status)) {
2258           if (d != t) {
2259             errln((UnicodeString)"FAIL: format " + k +
2260                   " incorrectly parsed output of format " + j +
2261                   " (" + test + "), returned " +
2262                   dateToString(t) + " instead of " + dateToString(d));
2263           } else {
2264             logln((UnicodeString)"OK: format " + k + " parsed ok");
2265           }
2266         } else if (status == U_PARSE_ERROR) {
2267           errln((UnicodeString)"FAIL: format " + k +
2268                 " could not parse output of format " + j +
2269                 " (" + test + ")");
2270         }
2271       }
2272     }
2273   }
2274 }
2275 
TestGenericTimeZoneOrder()2276 void DateFormatTest::TestGenericTimeZoneOrder() {
2277   // generic times should parse the same no matter what the placement of the time zone string
2278 
2279   // Note: We no longer support cross style format/parse
2280 
2281   //const char* XDATA[] = {
2282   //  "yyyy MM dd HH:mm zzz",
2283   //  // standard time, explicit daylight/standard
2284   //  "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2285   //  "y/M/d zzz H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
2286   //  "zzz y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
2287 
2288   //  // standard time, generic
2289   //  "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2290   //  "y/M/d vvvv H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
2291   //  "vvvv y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
2292 
2293   //  // dahylight time, explicit daylight/standard
2294   //  "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2295   //  "y/M/d zzz H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
2296   //  "zzz y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
2297 
2298   //  // daylight time, generic
2299   //  "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2300   //  "y/M/d vvvv H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 Pacific Time 1:00",
2301   //  "vvvv y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "Pacific Time 2004/7/1 1:00",
2302   //};
2303   const char* XDATA[] = {
2304     "yyyy MM dd HH:mm zzz",
2305     // standard time, explicit daylight/standard
2306     "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PST", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2307     "y/M/d zzz H:mm", "pf", "2004/1/1 PST 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
2308     "zzz y/M/d H:mm", "pf", "PST 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
2309 
2310     // standard time, generic
2311     "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 Pacific Time", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2312     "y/M/d vvvv H:mm", "pf", "2004/1/1 Pacific Time 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
2313     "vvvv y/M/d H:mm", "pf", "Pacific Time 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
2314 
2315     // dahylight time, explicit daylight/standard
2316     "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2317     "y/M/d zzz H:mm", "pf", "2004/7/1 PDT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
2318     "zzz y/M/d H:mm", "pf", "PDT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
2319 
2320     // daylight time, generic
2321     "y/M/d H:mm v", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PT",
2322     "y/M/d v H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PT 1:00",
2323     "v y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PT 2004/7/1 1:00",
2324   };
2325   const int32_t XDATA_length = UPRV_LENGTHOF(XDATA);
2326   Locale en("en");
2327   expect(XDATA, XDATA_length, en);
2328 }
2329 
TestZTimeZoneParsing(void)2330 void DateFormatTest::TestZTimeZoneParsing(void) {
2331     UErrorCode status = U_ZERO_ERROR;
2332     const Locale en("en");
2333     UnicodeString test;
2334     //SimpleDateFormat univ("yyyy-MM-dd'T'HH:mm Z", en, status);
2335     SimpleDateFormat univ("HH:mm Z", en, status);
2336     if (failure(status, "construct SimpleDateFormat", TRUE)) return;
2337     const TimeZone *t = TimeZone::getGMT();
2338     univ.setTimeZone(*t);
2339 
2340     univ.setLenient(false);
2341     ParsePosition pp(0);
2342     struct {
2343         UnicodeString input;
2344         UnicodeString expected_result;
2345     } tests[] = {
2346         { "11:00 -0200", "13:00 +0000" },
2347         { "11:00 +0200", "09:00 +0000" },
2348         { "11:00 +0400", "07:00 +0000" },
2349         { "11:00 +0530", "05:30 +0000" }
2350     };
2351 
2352     UnicodeString result;
2353     int32_t tests_length = UPRV_LENGTHOF(tests);
2354     for (int i = 0; i < tests_length; ++i) {
2355         pp.setIndex(0);
2356         UDate d = univ.parse(tests[i].input, pp);
2357         if(pp.getIndex() != tests[i].input.length()){
2358             errln("Test %i: setZoneString() did not succeed. Consumed: %i instead of %i",
2359                   i, pp.getIndex(), tests[i].input.length());
2360             return;
2361         }
2362         result.remove();
2363         univ.format(d, result);
2364         if(result != tests[i].expected_result) {
2365             errln("Expected " + tests[i].expected_result
2366                   + " got " + result);
2367             return;
2368         }
2369         logln("SUCCESS: Parsed " + tests[i].input
2370               + " got " + result
2371               + " expected " + tests[i].expected_result);
2372     }
2373 }
2374 
TestHost(void)2375 void DateFormatTest::TestHost(void)
2376 {
2377 #if U_PLATFORM_HAS_WIN32_API
2378     Win32DateTimeTest::testLocales(this);
2379 #endif
2380 }
2381 
2382 // Relative Date Tests
2383 
TestRelative(int daysdelta,const Locale & loc,const char * expectChars)2384 void DateFormatTest::TestRelative(int daysdelta,
2385                                   const Locale& loc,
2386                                   const char *expectChars) {
2387     char banner[25];
2388     sprintf(banner, "%d", daysdelta);
2389     UnicodeString bannerStr(banner, "");
2390 
2391     UErrorCode status = U_ZERO_ERROR;
2392 
2393     FieldPosition pos(FieldPosition::DONT_CARE);
2394     UnicodeString test;
2395     Locale en("en");
2396     DateFormat *fullrelative = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2397 
2398     if (fullrelative == NULL) {
2399         dataerrln("DateFormat::createDateInstance(DateFormat::kFullRelative, %s) returned NULL", loc.getName());
2400         return;
2401     }
2402 
2403     DateFormat *full         = DateFormat::createDateInstance(DateFormat::kFull        , loc);
2404 
2405     if (full == NULL) {
2406         errln("DateFormat::createDateInstance(DateFormat::kFull, %s) returned NULL", loc.getName());
2407         return;
2408     }
2409 
2410     DateFormat *en_full =         DateFormat::createDateInstance(DateFormat::kFull,         en);
2411 
2412     if (en_full == NULL) {
2413         errln("DateFormat::createDateInstance(DateFormat::kFull, en) returned NULL");
2414         return;
2415     }
2416 
2417     DateFormat *en_fulltime =         DateFormat::createDateTimeInstance(DateFormat::kFull,DateFormat::kFull,en);
2418 
2419     if (en_fulltime == NULL) {
2420         errln("DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, en) returned NULL");
2421         return;
2422     }
2423 
2424     UnicodeString result;
2425     UnicodeString normalResult;
2426     UnicodeString expect;
2427     UnicodeString parseResult;
2428 
2429     Calendar *c = Calendar::createInstance(status);
2430 
2431     // Today = Today
2432     c->setTime(Calendar::getNow(), status);
2433     if(daysdelta != 0) {
2434         c->add(Calendar::DATE,daysdelta,status);
2435     }
2436     ASSERT_OK(status);
2437 
2438     // calculate the expected string
2439     if(expectChars != NULL) {
2440         expect = expectChars;
2441     } else {
2442         full->format(*c, expect, pos); // expected = normal full
2443     }
2444 
2445     fullrelative   ->format(*c, result, pos);
2446     en_full        ->format(*c, normalResult, pos);
2447 
2448     if(result != expect) {
2449         errln("FAIL: Relative Format ["+bannerStr+"] of "+normalResult+" failed, expected "+expect+" but got " + result);
2450     } else {
2451         logln("PASS: Relative Format ["+bannerStr+"] of "+normalResult+" got " + result);
2452     }
2453 
2454 
2455     //verify
2456     UDate d = fullrelative->parse(result, status);
2457     ASSERT_OK(status);
2458 
2459     UnicodeString parseFormat; // parse rel->format full
2460     en_full->format(d, parseFormat, status);
2461 
2462     UnicodeString origFormat;
2463     en_full->format(*c, origFormat, pos);
2464 
2465     if(parseFormat!=origFormat) {
2466         errln("FAIL: Relative Parse ["+bannerStr+"] of "+result+" failed, expected "+parseFormat+" but got "+origFormat);
2467     } else {
2468         logln("PASS: Relative Parse ["+bannerStr+"] of "+result+" passed, got "+parseFormat);
2469     }
2470 
2471     delete full;
2472     delete fullrelative;
2473     delete en_fulltime;
2474     delete en_full;
2475     delete c;
2476 }
2477 
2478 
TestRelative(void)2479 void DateFormatTest::TestRelative(void)
2480 {
2481     Locale en("en");
2482     TestRelative( 0, en, "today");
2483     TestRelative(-1, en, "yesterday");
2484     TestRelative( 1, en, "tomorrow");
2485     TestRelative( 2, en, NULL);
2486     TestRelative( -2, en, NULL);
2487     TestRelative( 3, en, NULL);
2488     TestRelative( -3, en, NULL);
2489     TestRelative( 300, en, NULL);
2490     TestRelative( -300, en, NULL);
2491 }
2492 
TestRelativeClone(void)2493 void DateFormatTest::TestRelativeClone(void)
2494 {
2495     /*
2496     Verify that a cloned formatter gives the same results
2497     and is useable after the original has been deleted.
2498     */
2499     UErrorCode status = U_ZERO_ERROR;
2500     Locale loc("en");
2501     UDate now = Calendar::getNow();
2502     DateFormat *full = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2503     if (full == NULL) {
2504         dataerrln("FAIL: Can't create Relative date instance");
2505         return;
2506     }
2507     UnicodeString result1;
2508     full->format(now, result1, status);
2509     Format *fullClone = full->clone();
2510     delete full;
2511     full = NULL;
2512 
2513     UnicodeString result2;
2514     fullClone->format(now, result2, status);
2515     ASSERT_OK(status);
2516     if (result1 != result2) {
2517         errln("FAIL: Clone returned different result from non-clone.");
2518     }
2519     delete fullClone;
2520 }
2521 
TestHostClone(void)2522 void DateFormatTest::TestHostClone(void)
2523 {
2524     /*
2525     Verify that a cloned formatter gives the same results
2526     and is useable after the original has been deleted.
2527     */
2528     // This is mainly important on Windows.
2529     UErrorCode status = U_ZERO_ERROR;
2530     Locale loc("en_US@compat=host");
2531     UDate now = Calendar::getNow();
2532     DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull, loc);
2533     if (full == NULL) {
2534         dataerrln("FAIL: Can't create host date instance");
2535         return;
2536     }
2537     UnicodeString result1;
2538     full->format(now, result1, status);
2539     Format *fullClone = full->clone();
2540     delete full;
2541     full = NULL;
2542 
2543     UnicodeString result2;
2544     fullClone->format(now, result2, status);
2545     ASSERT_OK(status);
2546     if (result1 != result2) {
2547         errln("FAIL: Clone returned different result from non-clone.");
2548     }
2549     delete fullClone;
2550 }
2551 
TestHebrewClone(void)2552 void DateFormatTest::TestHebrewClone(void)
2553 {
2554     /*
2555     Verify that a cloned formatter gives the same results
2556     and is useable after the original has been deleted.
2557     */
2558     UErrorCode status = U_ZERO_ERROR;
2559     Locale loc("he@calendar=hebrew");
2560     UDate now = Calendar::getNow();
2561     LocalPointer<DateFormat> fmt(
2562             DateFormat::createDateInstance(DateFormat::kLong, loc));
2563     if (fmt.isNull()) {
2564         dataerrln("FAIL: Can't create Hebrew date instance");
2565         return;
2566     }
2567     UnicodeString result1;
2568     fmt->format(now, result1, status);
2569     LocalPointer<Format> fmtClone(fmt->clone());
2570 
2571     // free fmt to be sure that fmtClone is independent of fmt.
2572     fmt.adoptInstead(NULL);
2573 
2574     UnicodeString result2;
2575     fmtClone->format(now, result2, status);
2576     ASSERT_OK(status);
2577     if (result1 != result2) {
2578         errln("FAIL: Clone returned different result from non-clone.");
2579     }
2580 }
2581 
getActualAndValidLocales(const Format & fmt,Locale & valid,Locale & actual)2582 static UBool getActualAndValidLocales(
2583         const Format &fmt, Locale &valid, Locale &actual) {
2584     const SimpleDateFormat* dat = dynamic_cast<const SimpleDateFormat*>(&fmt);
2585     if (dat == NULL) {
2586         return FALSE;
2587     }
2588     const DateFormatSymbols *sym = dat->getDateFormatSymbols();
2589     if (sym == NULL) {
2590         return FALSE;
2591     }
2592     UErrorCode status = U_ZERO_ERROR;
2593     valid = sym->getLocale(ULOC_VALID_LOCALE, status);
2594     actual = sym->getLocale(ULOC_ACTUAL_LOCALE, status);
2595     return U_SUCCESS(status);
2596 }
2597 
TestDateFormatSymbolsClone(void)2598 void DateFormatTest::TestDateFormatSymbolsClone(void)
2599 {
2600     /*
2601     Verify that a cloned formatter gives the same results
2602     and is useable after the original has been deleted.
2603     */
2604     Locale loc("de_CH_LUCERNE");
2605     LocalPointer<DateFormat> fmt(
2606             DateFormat::createDateInstance(DateFormat::kDefault, loc));
2607     Locale valid1;
2608     Locale actual1;
2609     if (!getActualAndValidLocales(*fmt, valid1, actual1)) {
2610         dataerrln("FAIL: Could not fetch valid + actual locales");
2611         return;
2612     }
2613     LocalPointer<Format> fmtClone(fmt->clone());
2614 
2615     // Free fmt to be sure that fmtClone is really independent of fmt.
2616     fmt.adoptInstead(NULL);
2617     Locale valid2;
2618     Locale actual2;
2619     if (!getActualAndValidLocales(*fmtClone, valid2, actual2)) {
2620         errln("FAIL: Could not fetch valid + actual locales");
2621         return;
2622     }
2623     if (valid1 != valid2 || actual1 != actual2) {
2624         errln("Date format symbol locales of clone don't match original");
2625     }
2626 }
2627 
TestTimeZoneDisplayName()2628 void DateFormatTest::TestTimeZoneDisplayName()
2629 {
2630     // This test data was ported from ICU4J.  Don't know why the 6th column in there because it's not being
2631     // used currently.
2632     const char *fallbackTests[][6]  = {
2633         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2634         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2635         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZZ", "-08:00", "-8:00" },
2636         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "PST", "America/Los_Angeles" },
2637         { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Pacific Standard Time", "America/Los_Angeles" },
2638         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2639         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2640         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "PDT", "America/Los_Angeles" },
2641         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Pacific Daylight Time", "America/Los_Angeles" },
2642         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "PT", "America/Los_Angeles" },
2643         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Pacific Time", "America/Los_Angeles" },
2644         { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "Los Angeles Time", "America/Los_Angeles" },
2645         { "en_GB", "America/Los_Angeles", "2004-01-15T12:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2646         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "Z", "-0700", "-7:00" },
2647         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2648         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2649         { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2650         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2651         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2652         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2653         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2654         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "v", "MST", "America/Phoenix" },
2655         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "vvvv", "Mountain Standard Time", "America/Phoenix" },
2656         { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "VVVV", "Phoenix Time", "America/Phoenix" },
2657 
2658         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2659         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2660         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2661         { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2662         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2663         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2664         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2665         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2666         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2667         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2668         { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2669 
2670         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2671         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2672         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2673         { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2674         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2675         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2676         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2677         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2678         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2679         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2680         { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2681 
2682         { "en", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2683         { "en", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2684         { "en", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2685         { "en", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Cuba Standard Time", "-5:00" },
2686         { "en", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2687         { "en", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2688         { "en", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2689         { "en", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Cuba Daylight Time", "-4:00" },
2690         { "en", "America/Havana", "2004-07-15T00:00:00Z", "v", "Cuba Time", "America/Havana" },
2691         { "en", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Cuba Time", "America/Havana" },
2692         { "en", "America/Havana", "2004-07-15T00:00:00Z", "VVVV", "Cuba Time", "America/Havana" },
2693 
2694         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2695         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2696         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2697         { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2698         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2699         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2700         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2701         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2702         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2703         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2704         { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2705 
2706         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2707         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2708         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2709         { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2710         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2711         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2712         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2713         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2714         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2715         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2716         { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2717 
2718         { "en", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2719         { "en", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2720         { "en", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2721         { "en", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Greenwich Mean Time", "+0:00" },
2722         { "en", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2723         { "en", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2724         { "en", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "Europe/London" },
2725         { "en", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "British Summer Time", "Europe/London" },
2726     // icu en.txt has exemplar city for this time zone
2727         { "en", "Europe/London", "2004-07-15T00:00:00Z", "v", "United Kingdom Time", "Europe/London" },
2728         { "en", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "United Kingdom Time", "Europe/London" },
2729         { "en", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "United Kingdom Time", "Europe/London" },
2730 
2731         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2732         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2733         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2734         { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2735         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2736         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2737         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2738         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2739         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2740         { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2741 
2742         // JB#5150
2743         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2744         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2745         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2746         { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2747         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2748         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2749         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2750         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2751         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "India Time", "Asia/Calcutta" },
2752         { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "India Standard Time", "Asia/Calcutta" },
2753 
2754         // Proper CLDR primary zone support #9733
2755         { "en", "America/Santiago", "2013-01-01T00:00:00Z", "VVVV", "Chile Time", "America/Santiago" },
2756         { "en", "Pacific/Easter", "2013-01-01T00:00:00Z", "VVVV", "Easter Time", "Pacific/Easter" },
2757 
2758         // ==========
2759 
2760         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2761         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2762         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2763         { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Normalzeit", "-8:00" },
2764         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2765         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2766         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2767         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Sommerzeit", "-7:00" },
2768         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles Zeit", "America/Los_Angeles" },
2769         { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Nordamerikanische Westk\\u00fcstenzeit", "America/Los_Angeles" },
2770 
2771         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2772         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2773         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2774         { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2775         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2776         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2777         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2778         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2779         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2780         { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2781 
2782         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2783         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2784         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2785         { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2786         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2787         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2788         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2789         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2790         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2791         { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2792 
2793         { "de", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2794         { "de", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2795         { "de", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2796         { "de", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Kubanische Normalzeit", "-5:00" },
2797         { "de", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2798         { "de", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2799         { "de", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2800         { "de", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Kubanische Sommerzeit", "-4:00" },
2801         { "de", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2802         { "de", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2803         // added to test proper fallback of country name
2804         { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2805         { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2806 
2807         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2808         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2809         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2810         { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2811         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2812         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2813         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2814         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2815         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2816         { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2817 
2818         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2819         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2820         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2821         { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2822         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2823         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2824         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2825         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2826         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2827         { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2828 
2829         { "de", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2830         { "de", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2831         { "de", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2832         { "de", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Mittlere Greenwich-Zeit", "+0:00" },
2833         { "de", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2834         { "de", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2835         { "de", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2836         { "de", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "Britische Sommerzeit", "+1:00" },
2837         { "de", "Europe/London", "2004-07-15T00:00:00Z", "v", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2838         { "de", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2839 
2840         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2841         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2842         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2843         { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2844         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2845         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2846         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2847         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2848         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2849         { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2850 
2851         // JB#5150
2852         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2853         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2854         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2855         { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2856         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2857         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2858         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2859         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2860         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "Indien Zeit", "Asia/Calcutta" },
2861         { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "Indische Zeit", "Asia/Calcutta" },
2862 
2863         // ==========
2864 
2865         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2866         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2867         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2868         { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u6807\\u51c6\\u65f6\\u95f4", "America/Los_Angeles" },
2869         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2870         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2871         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
2872         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u590f\\u4ee4\\u65f6\\u95f4", "America/Los_Angeles" },
2873     // icu zh.txt has exemplar city for this time zone
2874         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4", "America/Los_Angeles" },
2875         { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u65f6\\u95f4", "America/Los_Angeles" },
2876 
2877         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2878         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2879         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2880         { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2881         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2882         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2883         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2884         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2885         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2886         { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2887 
2888         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2889         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2890         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2891         { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2892         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2893         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2894         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2895         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2896         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2897         { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2898 
2899         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2900         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2901         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2902         { "zh", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u6807\\u51c6\\u65f6\\u95f4", "-5:00" },
2903         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2904         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2905         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2906         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u590f\\u4ee4\\u65f6\\u95f4", "-4:00" },
2907         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2908         { "zh", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2909 
2910         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2911         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2912         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2913         { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2914         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2915         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2916         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2917         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2918     // icu zh.txt does not have info for this time zone
2919         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2920         { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2921 
2922         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2923         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2924         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2925         { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2926         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2927         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2928         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2929         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2930         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2931         { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2932 
2933         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2934         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2935         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2936         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2937         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2938         { "zh", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u683C\\u6797\\u5C3C\\u6CBB\\u6807\\u51C6\\u65F6\\u95F4", "+0:00" },
2939         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2940         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2941         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2942         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u4ee4\\u65f6\\u95f4", "+1:00" },
2943         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2944         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2945         { "zh", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2946 
2947         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2948         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2949         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2950         { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2951         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2952         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2953         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2954         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2955         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2956         { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2957 
2958         // JB#5150
2959         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2960         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2961         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2962         { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2963         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2964         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2965         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2966         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2967         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2968         { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2969 
2970         // ==========
2971 
2972         { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2973         { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2974         { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2975         { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-8:00" },
2976         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2977         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2978         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2979         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "-7:00" },
2980         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v",  "\\u0932\\u0949\\u0938 \\u090f\\u0902\\u091c\\u093f\\u0932\\u094d\\u0938 \\u0938\\u092e\\u092f", "America/Los_Angeles" },
2981         { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u0938\\u092e\\u092f", "America/Los_Angeles" },
2982 
2983         { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2984         { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2985         { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2986         { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2987         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2988         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2989         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2990         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2991         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u092C\\u094D\\u092F\\u0942\\u0928\\u0938 \\u0906\\u092F\\u0930\\u0938 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2992         { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2993 
2994         { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2995         { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2996         { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2997         { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2998         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2999         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3000         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3001         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
3002         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u092C\\u094D\\u092F\\u0942\\u0928\\u0938 \\u0906\\u092F\\u0930\\u0938 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
3003         { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
3004 
3005         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3006         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3007         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3008         { "hi", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-5:00" },
3009         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3010         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3011         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3012         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "-4:00" },
3013         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092E\\u092F", "America/Havana" },
3014         { "hi", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092e\\u092f", "America/Havana" },
3015 
3016         { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3017         { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3018         { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3019         { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "+11:00" },
3020         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3021         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3022         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3023         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "+10:00" },
3024         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3025         { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0911\\u0938\\u094d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e \\u0938\\u092e\\u092f", "Australia/Sydney" },
3026 
3027         { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3028         { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3029         { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3030         { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "+11:00" },
3031         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3032         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3033         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3034         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "+10:00" },
3035         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3036         { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0911\\u0938\\u094d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e \\u0938\\u092e\\u092f", "Australia/Sydney" },
3037 
3038         { "hi", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3039         { "hi", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3040         { "hi", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3041         { "hi", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u0917\\u094d\\u0930\\u0940\\u0928\\u0935\\u093f\\u091a \\u092e\\u0940\\u0928 \\u091f\\u093e\\u0907\\u092e", "+0:00" },
3042         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3043         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3044         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3045         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u092c\\u094d\\u0930\\u093f\\u091f\\u093f\\u0936 \\u0917\\u094d\\u0930\\u0940\\u0937\\u094d\\u092e\\u0915\\u093e\\u0932\\u0940\\u0928 \\u0938\\u092e\\u092f", "+1:00" },
3046         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u092f\\u0942\\u0928\\u093e\\u0907\\u091f\\u0947\\u0921 \\u0915\\u093f\\u0902\\u0917\\u0921\\u092e \\u0938\\u092e\\u092f", "Europe/London" },
3047         { "hi", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u092f\\u0942\\u0928\\u093e\\u0907\\u091f\\u0947\\u0921 \\u0915\\u093f\\u0902\\u0917\\u0921\\u092e \\u0938\\u092e\\u092f", "Europe/London" },
3048 
3049         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3050         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3051         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3052         { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3053         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3054         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3055         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3056         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3057         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3058         { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3059 
3060         { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3061         { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3062         { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "IST", "+5:30" },
3063         { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3064         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3065         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3066         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "IST", "+05:30" },
3067         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3068         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IST", "Asia/Calcutta" },
3069         { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "Asia/Calcutta" },
3070 
3071         // ==========
3072 
3073         { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3074         { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-08:00", "-8:00" },
3075         { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-8", "America/Los_Angeles" },
3076         { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3077         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3078         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-07:00", "-7:00" },
3079         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-7", "America/Los_Angeles" },
3080         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3081     // icu bg.txt has exemplar city for this time zone
3082         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3083         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3084         { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3085 
3086         { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3087         { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3088         { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3089         { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3090         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3091         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3092         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3093         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3094         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
3095         { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Buenos_Aires" },
3096 
3097         { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3098         { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3099         { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3100         { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3101         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3102         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3103         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3104         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3105     // icu bg.txt does not have info for this time zone
3106         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
3107         { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Buenos_Aires" },
3108 
3109         { "bg", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3110         { "bg", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-05:00", "-5:00" },
3111         { "bg", "America/Havana", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-5", "-5:00" },
3112         { "bg", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-5:00" },
3113         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3114         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-04:00", "-4:00" },
3115         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-4", "-4:00" },
3116         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-4:00" },
3117         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u041a\\u0443\\u0431\\u0430", "America/Havana" },
3118         { "bg", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043C\\u0435", "America/Havana" },
3119 
3120         { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3121         { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3122         { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3123         { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u043B\\u044F\\u0442\\u043D\\u043E \\u0447\\u0430\\u0441\\u043E\\u0432\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+11:00" },
3124         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3125         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3126         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3127         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+10:00" },
3128         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3129         { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "Australia/Sydney" },
3130 
3131         { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3132         { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3133         { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3134         { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u043B\\u044F\\u0442\\u043D\\u043E \\u0447\\u0430\\u0441\\u043E\\u0432\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+11:00" },
3135         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3136         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3137         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3138         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+10:00" },
3139         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3140         { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u044F \\u2013 \\u0438\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "Australia/Sydney" },
3141 
3142         { "bg", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3143         { "bg", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3144         { "bg", "Europe/London", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3145         { "bg", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u0421\\u0440\\u0435\\u0434\\u043d\\u043e \\u0433\\u0440\\u0438\\u043d\\u0443\\u0438\\u0447\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+0:00" },
3146         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3147         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+01:00", "+1:00" },
3148         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+1", "+1:00" },
3149         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u0411\\u0440\\u0438\\u0442\\u0430\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+1:00" },
3150         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u041E\\u0431\\u0435\\u0434\\u0438\\u043D\\u0435\\u043D\\u043E\\u0442\\u043E \\u043A\\u0440\\u0430\\u043B\\u0441\\u0442\\u0432\\u043E", "Europe/London" },
3151         { "bg", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u041E\\u0431\\u0435\\u0434\\u0438\\u043D\\u0435\\u043D\\u043E\\u0442\\u043E \\u043A\\u0440\\u0430\\u043B\\u0441\\u0442\\u0432\\u043E", "Europe/London" },
3152 
3153         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3154         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3155         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3156         { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3157         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3158         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3159         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3160         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3161         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3162         { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3163 
3164         // JB#5150
3165         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3166         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3167         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+5:30" },
3168         { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u043d\\u0434\\u0438\\u0439\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
3169         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3170         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3171         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+05:30" },
3172         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u043d\\u0434\\u0438\\u0439\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
3173         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u0418\\u043D\\u0434\\u0438\\u044F", "Asia/Calcutta" },
3174         { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u043d\\u0434\\u0438\\u0439\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "Asia/Calcutta" },
3175     // ==========
3176 
3177         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3178         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3179         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
3180         { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u6a19\\u6e96\\u6642", "America/Los_Angeles" },
3181         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-700" },
3182         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3183         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
3184         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u590f\\u6642\\u9593", "America/Los_Angeles" },
3185     // icu ja.txt has exemplar city for this time zone
3186         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3187         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30E1\\u30EA\\u30AB\\u592A\\u5e73\\u6D0B\\u6642\\u9593", "America/Los_Angeles" },
3188         { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3189 
3190         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3191         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3192         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3193         { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3194         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3195         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3196         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3197         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3198     // icu ja.txt does not have info for this time zone
3199         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3200         { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3201 
3202         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3203         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3204         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3205         { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3206         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3207         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3208         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3209         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3210         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3211         { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3212 
3213         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3214         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3215         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3216         { "ja", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u6A19\\u6E96\\u6642", "-5:00" },
3217         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3218         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3219         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3220         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u590F\\u6642\\u9593", "-4:00" },
3221         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3222         { "ja", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3223 
3224         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3225         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3226         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3227         { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3228         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3229         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3230         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3231         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3232     // icu ja.txt does not have info for this time zone
3233         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3234         { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3235 
3236         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3237         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3238         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3239         { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3240         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3241         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3242         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3243         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3244         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3245         { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3246 
3247         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3248         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3249         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3250         { "ja", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u30B0\\u30EA\\u30CB\\u30C3\\u30B8\\u6A19\\u6E96\\u6642", "+0:00" },
3251         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3252         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3253         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3254         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u6642\\u9593", "+1:00" },
3255         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3256         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3257         { "ja", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3258 
3259         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3260         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3261         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3262         { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3263         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3264         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3265         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3266         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3267         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3268         { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3269 
3270         // JB#5150
3271         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3272         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3273         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3274         { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3275         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3276         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3277         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3278         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3279         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u30A4\\u30F3\\u30C9\\u6642\\u9593", "Asia/Calcutta" },
3280         { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "Asia/Calcutta" },
3281 
3282     // ==========
3283 
3284         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3285         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3286         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
3287         { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "GMT-08:00", "-8:00" },
3288         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3289         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3290         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
3291         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "GMT-07:00", "-7:00" },
3292         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles", "America/Los_Angeles" },
3293         { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Los Angeles", "America/Los_Angeles" },
3294 
3295         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3296         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3297         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3298         { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3299         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3300         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3301         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3302         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3303         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3304         { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3305 
3306         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3307         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3308         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3309         { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3310         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3311         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3312         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3313         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3314         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3315         { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3316 
3317         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3318         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3319         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3320         { "ti", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "GMT-05:00", "-5:00" },
3321         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3322         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3323         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3324         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "GMT-04:00", "-4:00" },
3325         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "v", "CU", "America/Havana" },
3326         { "ti", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "CU", "America/Havana" },
3327 
3328         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3329         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3330         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3331         { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3332         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3333         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3334         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3335         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3336         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3337         { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3338 
3339         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3340         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3341         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3342         { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3343         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3344         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3345         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3346         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3347         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3348         { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3349 
3350         { "ti", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3351         { "ti", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3352         { "ti", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3353         { "ti", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "GMT", "+0:00" },
3354         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3355         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3356         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3357         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "GMT+01:00", "+1:00" },
3358         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "v", "GB", "Europe/London" },
3359         { "ti", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "GB", "Europe/London" },
3360 
3361         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3362         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3363         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3364         { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3365         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3366         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3367         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3368         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3369         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3370         { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3371 
3372         // JB#5150
3373         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3374         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3375         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3376         { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3377         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3378         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3379         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3380         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3381         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IN", "Alna/Calcutta" },
3382         { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "IN", "Asia/Calcutta" },
3383 
3384         // Ticket#8589 Partial location name to use country name if the zone is the golden
3385         // zone for the time zone's country.
3386         { "en_MX", "America/Chicago", "1995-07-15T00:00:00Z", "vvvv", "Central Time (United States)", "America/Chicago"},
3387 
3388         // Tests proper handling of time zones that should have empty sets when inherited from the parent.
3389         // For example, en_GB understands CET as Central European Time, but en_HK, which inherits from en_GB
3390         // does not
3391         { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3392         { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3393         { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "CET", "+1:00"},
3394         { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "CEST", "+2:00"},
3395         { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3396         { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3397         { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "GMT+1", "+1:00"},
3398         { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "GMT+2", "+2:00"},
3399 
3400         { NULL, NULL, NULL, NULL, NULL, NULL },
3401     };
3402 
3403     UErrorCode status = U_ZERO_ERROR;
3404     Calendar *cal = GregorianCalendar::createInstance(status);
3405     if (failure(status, "GregorianCalendar::createInstance", TRUE)) return;
3406     SimpleDateFormat testfmt(UnicodeString("yyyy-MM-dd'T'HH:mm:ss'Z'"), status);
3407     if (failure(status, "SimpleDateFormat constructor", TRUE)) return;
3408     testfmt.setTimeZone(*TimeZone::getGMT());
3409 
3410     for (int i = 0; fallbackTests[i][0]; i++) {
3411         const char **testLine = fallbackTests[i];
3412         UnicodeString info[5];
3413         for ( int j = 0 ; j < 5 ; j++ ) {
3414             info[j] = UnicodeString(testLine[j], -1, US_INV);
3415         }
3416         info[4] = info[4].unescape();
3417         logln("%s;%s;%s;%s", testLine[0], testLine[1], testLine[2], testLine[3]);
3418 
3419         TimeZone *tz = TimeZone::createTimeZone(info[1]);
3420 
3421         UDate d = testfmt.parse(testLine[2], status);
3422         cal->setTime(d, status);
3423         if (U_FAILURE(status)) {
3424             errln(UnicodeString("Failed to set date: ") + testLine[2]);
3425         }
3426 
3427         SimpleDateFormat fmt(info[3], Locale(testLine[0]),status);
3428         ASSERT_OK(status);
3429         cal->adoptTimeZone(tz);
3430         UnicodeString result;
3431         FieldPosition pos(FieldPosition::DONT_CARE);
3432         fmt.format(*cal,result,pos);
3433         if (result != info[4]) {
3434             errln(info[0] + ";" + info[1] + ";" + info[2] + ";" + info[3] + " expected: '" +
3435                   info[4] + "' but got: '" + result + "'");
3436         }
3437     }
3438     delete cal;
3439 }
3440 
TestRoundtripWithCalendar(void)3441 void DateFormatTest::TestRoundtripWithCalendar(void) {
3442     UErrorCode status = U_ZERO_ERROR;
3443 
3444     TimeZone *tz = TimeZone::createTimeZone("Europe/Paris");
3445     TimeZone *gmt = TimeZone::createTimeZone("Etc/GMT");
3446 
3447     Calendar *calendars[] = {
3448         Calendar::createInstance(*tz, Locale("und@calendar=gregorian"), status),
3449         Calendar::createInstance(*tz, Locale("und@calendar=buddhist"), status),
3450 //        Calendar::createInstance(*tz, Locale("und@calendar=hebrew"), status),
3451         Calendar::createInstance(*tz, Locale("und@calendar=islamic"), status),
3452         Calendar::createInstance(*tz, Locale("und@calendar=japanese"), status),
3453         NULL
3454     };
3455     if (U_FAILURE(status)) {
3456         dataerrln("Failed to initialize calendars: %s", u_errorName(status));
3457         for (int i = 0; calendars[i] != NULL; i++) {
3458             delete calendars[i];
3459         }
3460         return;
3461     }
3462 
3463     //FIXME The formatters commented out below are currently failing because of
3464     // the calendar calculation problem reported by #6691
3465 
3466     // The order of test formatters must match the order of calendars above.
3467     DateFormat *formatters[] = {
3468         DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("en_US")), //calendar=gregorian
3469         DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("th_TH")), //calendar=buddhist
3470 //        DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("he_IL@calendar=hebrew")),
3471         DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ar_EG@calendar=islamic")),
3472 //        DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ja_JP@calendar=japanese")),
3473         NULL
3474     };
3475 
3476     UDate d = Calendar::getNow();
3477     UnicodeString buf;
3478     FieldPosition fpos;
3479     ParsePosition ppos;
3480 
3481     for (int i = 0; formatters[i] != NULL; i++) {
3482         buf.remove();
3483         fpos.setBeginIndex(0);
3484         fpos.setEndIndex(0);
3485         calendars[i]->setTime(d, status);
3486 
3487         // Normal case output - the given calendar matches the calendar
3488         // used by the formatter
3489         formatters[i]->format(*calendars[i], buf, fpos);
3490         UnicodeString refStr(buf);
3491 
3492         for (int j = 0; calendars[j] != NULL; j++) {
3493             if (j == i) {
3494                 continue;
3495             }
3496             buf.remove();
3497             fpos.setBeginIndex(0);
3498             fpos.setEndIndex(0);
3499             calendars[j]->setTime(d, status);
3500 
3501             // Even the different calendar type is specified,
3502             // we should get the same result.
3503             formatters[i]->format(*calendars[j], buf, fpos);
3504             if (refStr != buf) {
3505                 errln((UnicodeString)"FAIL: Different format result with a different calendar for the same time -"
3506                         + "\n Reference calendar type=" + calendars[i]->getType()
3507                         + "\n Another calendar type=" + calendars[j]->getType()
3508                         + "\n Expected result=" + refStr
3509                         + "\n Actual result=" + buf);
3510             }
3511         }
3512 
3513         calendars[i]->setTimeZone(*gmt);
3514         calendars[i]->clear();
3515         ppos.setErrorIndex(-1);
3516         ppos.setIndex(0);
3517 
3518         // Normal case parse result - the given calendar matches the calendar
3519         // used by the formatter
3520         formatters[i]->parse(refStr, *calendars[i], ppos);
3521 
3522         for (int j = 0; calendars[j] != NULL; j++) {
3523             if (j == i) {
3524                 continue;
3525             }
3526             calendars[j]->setTimeZone(*gmt);
3527             calendars[j]->clear();
3528             ppos.setErrorIndex(-1);
3529             ppos.setIndex(0);
3530 
3531             // Even the different calendar type is specified,
3532             // we should get the same time and time zone.
3533             formatters[i]->parse(refStr, *calendars[j], ppos);
3534             if (calendars[i]->getTime(status) != calendars[j]->getTime(status)
3535                 || calendars[i]->getTimeZone() != calendars[j]->getTimeZone()) {
3536                 UnicodeString tzid;
3537                 errln((UnicodeString)"FAIL: Different parse result with a different calendar for the same string -"
3538                         + "\n Reference calendar type=" + calendars[i]->getType()
3539                         + "\n Another calendar type=" + calendars[j]->getType()
3540                         + "\n Date string=" + refStr
3541                         + "\n Expected time=" + calendars[i]->getTime(status)
3542                         + "\n Expected time zone=" + calendars[i]->getTimeZone().getID(tzid)
3543                         + "\n Actual time=" + calendars[j]->getTime(status)
3544                         + "\n Actual time zone=" + calendars[j]->getTimeZone().getID(tzid));
3545             }
3546         }
3547         if (U_FAILURE(status)) {
3548             errln((UnicodeString)"FAIL: " + u_errorName(status));
3549             break;
3550         }
3551     }
3552 
3553     delete tz;
3554     delete gmt;
3555     for (int i = 0; calendars[i] != NULL; i++) {
3556         delete calendars[i];
3557     }
3558     for (int i = 0; formatters[i] != NULL; i++) {
3559         delete formatters[i];
3560     }
3561 }
3562 
3563 /*
3564 void DateFormatTest::TestRelativeError(void)
3565 {
3566     UErrorCode status;
3567     Locale en("en");
3568 
3569     DateFormat *en_reltime_reldate =         DateFormat::createDateTimeInstance(DateFormat::kFullRelative,DateFormat::kFullRelative,en);
3570     if(en_reltime_reldate == NULL) {
3571         logln("PASS: rel date/rel time failed");
3572     } else {
3573         errln("FAIL: rel date/rel time created, should have failed.");
3574         delete en_reltime_reldate;
3575     }
3576 }
3577 
3578 void DateFormatTest::TestRelativeOther(void)
3579 {
3580     logln("Nothing in this test. When we get more data from CLDR, put in some tests of -2, +2, etc. ");
3581 }
3582 */
3583 
Test6338(void)3584 void DateFormatTest::Test6338(void)
3585 {
3586     UErrorCode status = U_ZERO_ERROR;
3587 
3588     SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("ar"), status);
3589     if (failure(status, "new SimpleDateFormat", TRUE)) return;
3590 
3591     UDate dt1 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3592     UnicodeString str1;
3593     str1 = fmt1->format(dt1, str1);
3594     logln(str1);
3595 
3596     UDate dt11 = fmt1->parse(str1, status);
3597     failure(status, "fmt->parse");
3598 
3599     UnicodeString str11;
3600     str11 = fmt1->format(dt11, str11);
3601     logln(str11);
3602 
3603     if (str1 != str11) {
3604         errln((UnicodeString)"FAIL: Different dates str1:" + str1
3605             + " str2:" + str11);
3606     }
3607     delete fmt1;
3608 
3609     /////////////////
3610 
3611     status = U_ZERO_ERROR;
3612     SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("y M d"), Locale("ar"), status);
3613     failure(status, "new SimpleDateFormat");
3614 
3615     UDate dt2 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3616     UnicodeString str2;
3617     str2 = fmt2->format(dt2, str2);
3618     logln(str2);
3619 
3620     UDate dt22 = fmt2->parse(str2, status);
3621     failure(status, "fmt->parse");
3622 
3623     UnicodeString str22;
3624     str22 = fmt2->format(dt22, str22);
3625     logln(str22);
3626 
3627     if (str2 != str22) {
3628         errln((UnicodeString)"FAIL: Different dates str1:" + str2
3629             + " str2:" + str22);
3630     }
3631     delete fmt2;
3632 
3633     /////////////////
3634 
3635     status = U_ZERO_ERROR;
3636     SimpleDateFormat *fmt3 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("en-us"), status);
3637     failure(status, "new SimpleDateFormat");
3638 
3639     UDate dt3 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3640     UnicodeString str3;
3641     str3 = fmt3->format(dt3, str3);
3642     logln(str3);
3643 
3644     UDate dt33 = fmt3->parse(str3, status);
3645     failure(status, "fmt->parse");
3646 
3647     UnicodeString str33;
3648     str33 = fmt3->format(dt33, str33);
3649     logln(str33);
3650 
3651     if (str3 != str33) {
3652         errln((UnicodeString)"FAIL: Different dates str1:" + str3
3653             + " str2:" + str33);
3654     }
3655     delete fmt3;
3656 
3657     /////////////////
3658 
3659     status = U_ZERO_ERROR;
3660     SimpleDateFormat *fmt4 = new SimpleDateFormat(UnicodeString("y M  d"), Locale("en-us"), status);
3661     failure(status, "new SimpleDateFormat");
3662 
3663     UDate dt4 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3664     UnicodeString str4;
3665     str4 = fmt4->format(dt4, str4);
3666     logln(str4);
3667 
3668     UDate dt44 = fmt4->parse(str4, status);
3669     failure(status, "fmt->parse");
3670 
3671     UnicodeString str44;
3672     str44 = fmt4->format(dt44, str44);
3673     logln(str44);
3674 
3675     if (str4 != str44) {
3676         errln((UnicodeString)"FAIL: Different dates str1:" + str4
3677             + " str2:" + str44);
3678     }
3679     delete fmt4;
3680 
3681 }
3682 
Test6726(void)3683 void DateFormatTest::Test6726(void)
3684 {
3685     // status
3686 //    UErrorCode status = U_ZERO_ERROR;
3687 
3688     // fmtf, fmtl, fmtm, fmts;
3689     UnicodeString strf, strl, strm, strs;
3690     UDate dt = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3691 
3692     Locale loc("ja");
3693     DateFormat* fmtf = DateFormat::createDateTimeInstance(DateFormat::FULL, DateFormat::FULL, loc);
3694     DateFormat* fmtl = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::FULL, loc);
3695     DateFormat* fmtm = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, loc);
3696     DateFormat* fmts = DateFormat::createDateTimeInstance(DateFormat::SHORT, DateFormat::FULL, loc);
3697     if (fmtf == NULL || fmtl == NULL || fmtm == NULL || fmts == NULL) {
3698         dataerrln("Unable to create DateFormat. got NULL.");
3699         /* It may not be true that if one is NULL all is NULL.  Just to be safe. */
3700         delete fmtf;
3701         delete fmtl;
3702         delete fmtm;
3703         delete fmts;
3704 
3705         return;
3706     }
3707     strf = fmtf->format(dt, strf);
3708     strl = fmtl->format(dt, strl);
3709     strm = fmtm->format(dt, strm);
3710     strs = fmts->format(dt, strs);
3711 
3712 
3713     logln("strm.charAt(10)=%04X wanted 0x20\n", strm.charAt(10));
3714     if (strm.charAt(10) != UChar(0x0020)) {
3715       errln((UnicodeString)"FAIL: Improper formatted date: " + strm );
3716     }
3717     logln("strs.charAt(10)=%04X wanted 0x20\n", strs.charAt(8));
3718     if (strs.charAt(10)  != UChar(0x0020)) {
3719         errln((UnicodeString)"FAIL: Improper formatted date: " + strs);
3720     }
3721 
3722     delete fmtf;
3723     delete fmtl;
3724     delete fmtm;
3725     delete fmts;
3726 
3727     return;
3728 }
3729 
3730 /**
3731  * Test DateFormat's parsing of default GMT variants.  See ticket#6135
3732  */
TestGMTParsing()3733 void DateFormatTest::TestGMTParsing() {
3734     const char* DATA[] = {
3735         "HH:mm:ss Z",
3736 
3737         // pattern, input, expected output (in quotes)
3738         "HH:mm:ss Z",       "10:20:30 GMT+03:00",   "10:20:30 +0300",
3739         "HH:mm:ss Z",       "10:20:30 UT-02:00",    "10:20:30 -0200",
3740         "HH:mm:ss Z",       "10:20:30 GMT",         "10:20:30 +0000",
3741         "HH:mm:ss vvvv",    "10:20:30 UT+10:00",    "10:20:30 +1000",
3742         "HH:mm:ss zzzz",    "10:20:30 UTC",         "10:20:30 +0000",   // standalone "UTC"
3743         "ZZZZ HH:mm:ss",    "UT 10:20:30",          "10:20:30 +0000",
3744         "z HH:mm:ss",       "UT+0130 10:20:30",     "10:20:30 +0130",
3745         "z HH:mm:ss",       "UTC+0130 10:20:30",    "10:20:30 +0130",
3746         // Note: GMT-1100 no longer works because of the introduction of the short
3747         // localized GMT support. Previous implementation support this level of
3748         // leniency (no separator char in localized GMT format), but the new
3749         // implementation handles GMT-11 as the legitimate short localized GMT format
3750         // and stop at there. Otherwise, roundtrip would be broken.
3751         //"HH mm Z ss",       "10 20 GMT-1100 30",    "10:20:30 -1100",
3752         "HH mm Z ss",       "10 20 GMT-11 30",    "10:20:30 -1100",
3753         "HH:mm:ssZZZZZ",    "14:25:45Z",            "14:25:45 +0000",
3754         "HH:mm:ssZZZZZ",    "15:00:00-08:00",       "15:00:00 -0800",
3755     };
3756     const int32_t DATA_len = UPRV_LENGTHOF(DATA);
3757     expectParse(DATA, DATA_len, Locale("en"));
3758 }
3759 
3760 // Test case for localized GMT format parsing
3761 // with no delimitters in offset format (Chinese locale)
Test6880()3762 void DateFormatTest::Test6880() {
3763     UErrorCode status = U_ZERO_ERROR;
3764     UDate d1, d2, dp1, dp2, dexp1, dexp2;
3765     UnicodeString s1, s2;
3766 
3767     TimeZone *tz = TimeZone::createTimeZone("Asia/Shanghai");
3768     GregorianCalendar gcal(*tz, status);
3769     if (failure(status, "construct GregorianCalendar", TRUE)) return;
3770 
3771     gcal.clear();
3772     gcal.set(1900, UCAL_JULY, 1, 12, 00);   // offset 8:05:43
3773     d1 = gcal.getTime(status);
3774 
3775     gcal.clear();
3776     gcal.set(1950, UCAL_JULY, 1, 12, 00);   // offset 8:00
3777     d2 = gcal.getTime(status);
3778 
3779     gcal.clear();
3780     gcal.set(1970, UCAL_JANUARY, 1, 12, 00);
3781     dexp2 = gcal.getTime(status);
3782     dexp1 = dexp2 - (5*60 + 43)*1000;   // subtract 5m43s
3783 
3784     if (U_FAILURE(status)) {
3785         errln("FAIL: Gregorian calendar error");
3786     }
3787 
3788     DateFormat *fmt = DateFormat::createTimeInstance(DateFormat::kFull, Locale("zh"));
3789     if (fmt == NULL) {
3790         dataerrln("Unable to create DateFormat. Got NULL.");
3791         return;
3792     }
3793     fmt->adoptTimeZone(tz);
3794 
3795     fmt->format(d1, s1);
3796     fmt->format(d2, s2);
3797 
3798     dp1 = fmt->parse(s1, status);
3799     dp2 = fmt->parse(s2, status);
3800 
3801     if (U_FAILURE(status)) {
3802         errln("FAIL: Parse failure");
3803     }
3804 
3805     if (dp1 != dexp1) {
3806         errln("FAIL: Failed to parse " + s1 + " parsed: " + dp1 + " expected: " + dexp1);
3807     }
3808     if (dp2 != dexp2) {
3809         errln("FAIL: Failed to parse " + s2 + " parsed: " + dp2 + " expected: " + dexp2);
3810     }
3811 
3812     delete fmt;
3813 }
3814 
3815 typedef struct {
3816     const char * localeStr;
3817     UBool        lenient;
3818     UBool        expectFail;
3819     UnicodeString datePattern;
3820     UnicodeString dateString;
3821 } NumAsStringItem;
3822 
TestNumberAsStringParsing()3823 void DateFormatTest::TestNumberAsStringParsing()
3824 {
3825     const NumAsStringItem items[] = {
3826         // loc lenient fail?  datePattern                                         dateString
3827         { "",   FALSE, TRUE,  UnicodeString("y MMMM d HH:mm:ss"),                 UnicodeString("2009 7 14 08:43:57") },
3828         { "",   TRUE,  FALSE, UnicodeString("y MMMM d HH:mm:ss"),                 UnicodeString("2009 7 14 08:43:57") },
3829         { "en", FALSE, FALSE, UnicodeString("MMM d, y"),                          UnicodeString("Jul 14, 2009") },
3830         { "en", TRUE,  FALSE, UnicodeString("MMM d, y"),                          UnicodeString("Jul 14, 2009") },
3831         { "en", FALSE, TRUE,  UnicodeString("MMM d, y"),                          UnicodeString("7 14, 2009") },
3832         { "en", TRUE,  FALSE, UnicodeString("MMM d, y"),                          UnicodeString("7 14, 2009") },
3833         { "ja", FALSE, FALSE, UnicodeString("yyyy/MM/dd"),                        UnicodeString("2009/07/14")         },
3834         { "ja", TRUE,  FALSE, UnicodeString("yyyy/MM/dd"),                        UnicodeString("2009/07/14")         },
3835       //{ "ja", FALSE, FALSE, UnicodeString("yyyy/MMMMM/d"),                      UnicodeString("2009/7/14")          }, // #8860 covers test failure
3836         { "ja", TRUE,  FALSE, UnicodeString("yyyy/MMMMM/d"),                      UnicodeString("2009/7/14")          },
3837         { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"),   CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   },
3838         { "ja", TRUE,  FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"),   CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   },
3839         { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"),        CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   },
3840         { "ja", TRUE,  FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"),        CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5")   }, // #8820 fixes test failure
3841         { "ko", FALSE, FALSE, UnicodeString("yyyy. M. d."),                       UnicodeString("2009. 7. 14.")       },
3842         { "ko", TRUE,  FALSE, UnicodeString("yyyy. M. d."),                       UnicodeString("2009. 7. 14.")       },
3843         { "ko", FALSE, FALSE, UnicodeString("yyyy. MMMMM d."),                    CharsToUnicodeString("2009. 7\\uC6D4 14.")             },
3844         { "ko", TRUE,  FALSE, UnicodeString("yyyy. MMMMM d."),                    CharsToUnicodeString("2009. 7\\uC6D4 14.")             }, // #8820 fixes test failure
3845         { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3846         { "ko", TRUE,  FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3847         { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"),      CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3848         { "ko", TRUE,  FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"),      CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") }, // #8820 fixes test failure
3849         { NULL, FALSE, FALSE, UnicodeString(""),                                  UnicodeString("")                   }
3850     };
3851     const NumAsStringItem * itemPtr;
3852     for (itemPtr = items; itemPtr->localeStr != NULL; itemPtr++ ) {
3853         Locale locale = Locale::createFromName(itemPtr->localeStr);
3854         UErrorCode status = U_ZERO_ERROR;
3855         SimpleDateFormat *formatter = new SimpleDateFormat(itemPtr->datePattern, locale, status);
3856         if (formatter == NULL || U_FAILURE(status)) {
3857             dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3858             return;
3859         }
3860 
3861         formatter->setLenient(itemPtr->lenient);
3862         formatter->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->lenient, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->lenient, status);
3863         UDate date1 = formatter->parse(itemPtr->dateString, status);
3864         if (U_FAILURE(status)) {
3865             if (!itemPtr->expectFail) {
3866                 errln("FAIL, err when expected success: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3867                         ": using pattern \"" + itemPtr->datePattern + "\", could not parse \"" + itemPtr->dateString + "\"; err: " + u_errorName(status) );
3868             }
3869         } else if (itemPtr->expectFail) {
3870                 errln("FAIL, expected err but got none: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3871                         ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\"." );
3872         } else if (!itemPtr->lenient) {
3873             UnicodeString formatted;
3874             formatter->format(date1, formatted);
3875             if (formatted != itemPtr->dateString) {
3876                 errln("FAIL, mismatch formatting parsed date: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3877                         ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\", formatted result \"" + formatted + "\".");
3878             }
3879         }
3880 
3881         delete formatter;
3882     }
3883 }
3884 
TestISOEra()3885 void DateFormatTest::TestISOEra() {
3886 
3887     const char* data[] = {
3888     // input, output
3889     "BC 4004-10-23T07:00:00Z", "BC 4004-10-23T07:00:00Z",
3890     "AD 4004-10-23T07:00:00Z", "AD 4004-10-23T07:00:00Z",
3891     "-4004-10-23T07:00:00Z"  , "BC 4005-10-23T07:00:00Z",
3892     "4004-10-23T07:00:00Z"   , "AD 4004-10-23T07:00:00Z",
3893     };
3894 
3895     int32_t numData = 8;
3896 
3897     UErrorCode status = U_ZERO_ERROR;
3898 
3899     // create formatter
3900     SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("GGG yyyy-MM-dd'T'HH:mm:ss'Z"), status);
3901     failure(status, "new SimpleDateFormat", TRUE);
3902     if (status == U_MISSING_RESOURCE_ERROR) {
3903         if (fmt1 != NULL) {
3904             delete fmt1;
3905         }
3906         return;
3907     }
3908     for(int i=0; i < numData; i+=2) {
3909         // create input string
3910         UnicodeString in = data[i];
3911 
3912         // parse string to date
3913         UDate dt1 = fmt1->parse(in, status);
3914         failure(status, "fmt->parse", TRUE);
3915 
3916         // format date back to string
3917         UnicodeString out;
3918         out = fmt1->format(dt1, out);
3919         logln(out);
3920 
3921         // check that roundtrip worked as expected
3922         UnicodeString expected = data[i+1];
3923         if (out != expected) {
3924             dataerrln((UnicodeString)"FAIL: " + in + " -> " + out + " expected -> " + expected);
3925         }
3926     }
3927 
3928     delete fmt1;
3929 }
TestFormalChineseDate()3930 void DateFormatTest::TestFormalChineseDate() {
3931 
3932     UErrorCode status = U_ZERO_ERROR;
3933     UnicodeString pattern ("y\\u5e74M\\u6708d\\u65e5", -1, US_INV );
3934     pattern = pattern.unescape();
3935     UnicodeString override ("y=hanidec;M=hans;d=hans", -1, US_INV );
3936 
3937     // create formatter
3938     SimpleDateFormat *sdf = new SimpleDateFormat(pattern,override,Locale::getChina(),status);
3939     if (failure(status, "new SimpleDateFormat with override", TRUE)) {
3940         return;
3941     }
3942 
3943     UDate thedate = date(2009-1900, UCAL_JULY, 28);
3944     FieldPosition pos(FieldPosition::DONT_CARE);
3945     UnicodeString result;
3946     sdf->format(thedate,result,pos);
3947 
3948     UnicodeString expected = "\\u4e8c\\u3007\\u3007\\u4e5d\\u5e74\\u4e03\\u6708\\u4e8c\\u5341\\u516b\\u65e5";
3949     expected = expected.unescape();
3950     if (result != expected) {
3951         dataerrln((UnicodeString)"FAIL: -> " + result + " expected -> " + expected);
3952     }
3953 
3954     UDate parsedate = sdf->parse(expected,status);
3955     if ( parsedate != thedate ) {
3956         UnicodeString pat1 ("yyyy-MM-dd'T'HH:mm:ss'Z'", -1, US_INV );
3957         SimpleDateFormat *usf = new SimpleDateFormat(pat1,Locale::getEnglish(),status);
3958         UnicodeString parsedres,expres;
3959         usf->format(parsedate,parsedres,pos);
3960         usf->format(thedate,expres,pos);
3961         dataerrln((UnicodeString)"FAIL: parsed -> " + parsedres + " expected -> " + expres);
3962         delete usf;
3963     }
3964     delete sdf;
3965 }
3966 
3967 // Test case for #8675
3968 // Incorrect parse offset with stand alone GMT string on 2nd or later iteration.
TestStandAloneGMTParse()3969 void DateFormatTest::TestStandAloneGMTParse() {
3970     UErrorCode status = U_ZERO_ERROR;
3971     SimpleDateFormat *sdf = new SimpleDateFormat("ZZZZ", Locale(""), status);
3972 
3973     if (U_SUCCESS(status)) {
3974 
3975         UnicodeString inText("GMT$$$");
3976         for (int32_t i = 0; i < 10; i++) {
3977             ParsePosition pos(0);
3978             sdf->parse(inText, pos);
3979             if (pos.getIndex() != 3) {
3980                 errln((UnicodeString)"FAIL: Incorrect output parse position: actual=" + pos.getIndex() + " expected=3");
3981             }
3982         }
3983 
3984         delete sdf;
3985     } else {
3986         dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3987     }
3988 }
3989 
TestParsePosition()3990 void DateFormatTest::TestParsePosition() {
3991     const char* TestData[][4] = {
3992         // {<pattern>, <lead>, <date string>, <trail>}
3993         {"yyyy-MM-dd HH:mm:ssZ", "", "2010-01-10 12:30:00+0500", ""},
3994         {"yyyy-MM-dd HH:mm:ss ZZZZ", "", "2010-01-10 12:30:00 GMT+05:00", ""},
3995         {"Z HH:mm:ss", "", "-0100 13:20:30", ""},
3996         {"y-M-d Z", "", "2011-8-25 -0400", " Foo"},
3997         {"y/M/d H:mm:ss z", "", "2011/7/1 12:34:00 PDT", ""},
3998         {"y/M/d H:mm:ss z", "+123", "2011/7/1 12:34:00 PDT", " PST"},
3999         {"vvvv a h:mm:ss", "", "Pacific Time AM 10:21:45", ""},
4000         {"HH:mm v M/d", "111", "14:15 PT 8/10", " 12345"},
4001         {"'time zone:' VVVV 'date:' yyyy-MM-dd", "xxxx", "time zone: Los Angeles Time date: 2010-02-25", "xxxx"},
4002         {"yG", "", "2012AD", ""},
4003         {"yG", "", "2012", "x"},
4004         {0, 0, 0, 0},
4005     };
4006 
4007     for (int32_t i = 0; TestData[i][0]; i++) {
4008         UErrorCode status = U_ZERO_ERROR;
4009         SimpleDateFormat *sdf = new SimpleDateFormat(UnicodeString(TestData[i][0]), status);
4010         if (failure(status, "new SimpleDateFormat", TRUE)) return;
4011 
4012         int32_t startPos, resPos;
4013 
4014         // lead text
4015         UnicodeString input(TestData[i][1]);
4016         startPos = input.length();
4017 
4018         // date string
4019         input += TestData[i][2];
4020         resPos = input.length();
4021 
4022         // trail text
4023         input += TestData[i][3];
4024 
4025         ParsePosition pos(startPos);
4026         //UDate d = sdf->parse(input, pos);
4027         (void)sdf->parse(input, pos);
4028 
4029         if (pos.getIndex() != resPos) {
4030             errln(UnicodeString("FAIL: Parsing [") + input + "] with pattern [" + TestData[i][0] + "] returns position - "
4031                 + pos.getIndex() + ", expected - " + resPos);
4032         }
4033 
4034         delete sdf;
4035     }
4036 }
4037 
4038 
4039 typedef struct {
4040     int32_t era;
4041     int32_t year;
4042     int32_t month; // 1-based
4043     int32_t isLeapMonth;
4044     int32_t day;
4045 } ChineseCalTestDate;
4046 
4047 #define NUM_TEST_DATES 3
4048 
4049 typedef struct {
4050     const char *   locale;
4051     int32_t        style; // <0 => custom
4052     UnicodeString  dateString[NUM_TEST_DATES];
4053 } MonthPatternItem;
4054 
TestMonthPatterns()4055 void DateFormatTest::TestMonthPatterns()
4056 {
4057     const ChineseCalTestDate dates[NUM_TEST_DATES] = {
4058         // era yr mo lp da
4059         {  78, 29, 4, 0, 2 }, // (in chinese era 78) gregorian 2012-4-22
4060         {  78, 29, 4, 1, 2 }, // (in chinese era 78) gregorian 2012-5-22
4061         {  78, 29, 5, 0, 2 }, // (in chinese era 78) gregorian 2012-6-20
4062     };
4063 
4064     const MonthPatternItem items[] = {
4065         // locale                     date style;           expected formats for the 3 dates above
4066         { "root@calendar=chinese",    DateFormat::kLong,  { UnicodeString("2012(ren-chen) M04 2"),  UnicodeString("2012(ren-chen) M04bis 2"),  UnicodeString("2012(ren-chen) M05 2") } },
4067         { "root@calendar=chinese",    DateFormat::kShort, { UnicodeString("2012-04-02"),    UnicodeString("2012-04bis-02"),         UnicodeString("2012-05-02") } },
4068         { "root@calendar=chinese",    -1,                 { UnicodeString("29-4-2"),        UnicodeString("29-4bis-2"),             UnicodeString("29-5-2") } },
4069         { "root@calendar=chinese",    -2,                 { UnicodeString("78x29-4-2"),     UnicodeString("78x29-4bis-2"),          UnicodeString("78x29-5-2") } },
4070         { "root@calendar=chinese",    -3,                 { UnicodeString("ren-chen-4-2"),  UnicodeString("ren-chen-4bis-2"),       UnicodeString("ren-chen-5-2") } },
4071         { "root@calendar=chinese",    -4,                 { UnicodeString("ren-chen M04 2"),  UnicodeString("ren-chen M04bis 2"),   UnicodeString("ren-chen M05 2") } },
4072         { "en@calendar=gregorian",    -3,                 { UnicodeString("2012-4-22"),     UnicodeString("2012-5-22"),             UnicodeString("2012-6-20") } },
4073         { "en@calendar=chinese",      DateFormat::kLong,  { UnicodeString("Fourth Month 2, 2012(ren-chen)"), UnicodeString("Fourth Monthbis 2, 2012(ren-chen)"), UnicodeString("Fifth Month 2, 2012(ren-chen)") } },
4074         { "en@calendar=chinese",      DateFormat::kShort, { UnicodeString("4/2/2012"),      UnicodeString("4bis/2/2012"),           UnicodeString("5/2/2012") } },
4075         { "zh@calendar=chinese",      DateFormat::kLong,  { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4076                                                             CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u95F0\\u56DB\\u6708\\u521D\\u4E8C"),
4077                                                             CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4078         { "zh@calendar=chinese",      DateFormat::kShort, { CharsToUnicodeString("2012/4/2"),
4079                                                             CharsToUnicodeString("2012/\\u95F04/2"),
4080                                                             CharsToUnicodeString("2012/5/2") } },
4081         { "zh@calendar=chinese",      -3,                 { CharsToUnicodeString("\\u58EC\\u8FB0-4-2"),
4082                                                             CharsToUnicodeString("\\u58EC\\u8FB0-\\u95F04-2"),
4083                                                             CharsToUnicodeString("\\u58EC\\u8FB0-5-2") } },
4084         { "zh@calendar=chinese",      -4,                 { CharsToUnicodeString("\\u58EC\\u8FB0 \\u56DB\\u6708 2"),
4085                                                             CharsToUnicodeString("\\u58EC\\u8FB0 \\u95F0\\u56DB\\u6708 2"),
4086                                                             CharsToUnicodeString("\\u58EC\\u8FB0 \\u4E94\\u6708 2") } },
4087         { "zh_Hant@calendar=chinese", DateFormat::kLong,  { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4088                                                             CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u958F\\u56DB\\u6708\\u521D\\u4E8C"),
4089                                                             CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4090         { "zh_Hant@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("2012/4/2"),
4091                                                             CharsToUnicodeString("2012/\\u958F4/2"),
4092                                                             CharsToUnicodeString("2012/5/2") } },
4093         { "fr@calendar=chinese",      DateFormat::kLong,  { CharsToUnicodeString("2 s\\u00ECyu\\u00E8 ren-chen"),
4094                                                             CharsToUnicodeString("2 s\\u00ECyu\\u00E8bis ren-chen"),
4095                                                             CharsToUnicodeString("2 w\\u01D4yu\\u00E8 ren-chen") } },
4096         { "fr@calendar=chinese",      DateFormat::kShort, { UnicodeString("2/4/29"),        UnicodeString("2/4bis/29"),             UnicodeString("2/5/29") } },
4097         { "en@calendar=dangi",        DateFormat::kLong,  { UnicodeString("Third Monthbis 2, 2012(ren-chen)"),  UnicodeString("Fourth Month 2, 2012(ren-chen)"),       UnicodeString("Fifth Month 1, 2012(ren-chen)") } },
4098         { "en@calendar=dangi",        DateFormat::kShort, { UnicodeString("3bis/2/2012"),   UnicodeString("4/2/2012"),              UnicodeString("5/1/2012") } },
4099         { "en@calendar=dangi",        -2,                 { UnicodeString("78x29-3bis-2"),  UnicodeString("78x29-4-2"),             UnicodeString("78x29-5-1") } },
4100         { "ko@calendar=dangi",        DateFormat::kLong,  { CharsToUnicodeString("\\uC784\\uC9C4\\uB144 \\uC7243\\uC6D4 2\\uC77C"),
4101                                                             CharsToUnicodeString("\\uC784\\uC9C4\\uB144 4\\uC6D4 2\\uC77C"),
4102                                                             CharsToUnicodeString("\\uC784\\uC9C4\\uB144 5\\uC6D4 1\\uC77C") } },
4103         { "ko@calendar=dangi",        DateFormat::kShort, { CharsToUnicodeString("29. \\uC7243. 2."),
4104                                                             CharsToUnicodeString("29. 4. 2."),
4105                                                             CharsToUnicodeString("29. 5. 1.") } },
4106         // terminator
4107         { NULL,                       0,                  { UnicodeString(""), UnicodeString(""), UnicodeString("") } }
4108     };
4109 
4110     //.                               style: -1        -2            -3       -4
4111     const UnicodeString customPatterns[] = { "y-Ml-d", "G'x'y-Ml-d", "U-M-d", "U MMM d" }; // like old root pattern, using 'l'
4112 
4113     UErrorCode status = U_ZERO_ERROR;
4114     Locale rootChineseCalLocale = Locale::createFromName("root@calendar=chinese");
4115     Calendar * rootChineseCalendar = Calendar::createInstance(rootChineseCalLocale, status);
4116     if (U_SUCCESS(status)) {
4117         const MonthPatternItem * itemPtr;
4118         for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4119             Locale locale = Locale::createFromName(itemPtr->locale);
4120             DateFormat * dmft = (itemPtr->style >= 0)?
4121                     DateFormat::createDateInstance((DateFormat::EStyle)itemPtr->style, locale):
4122                     new SimpleDateFormat(customPatterns[-itemPtr->style - 1], locale, status);
4123             if ( dmft != NULL ) {
4124                 if (U_SUCCESS(status)) {
4125                     const ChineseCalTestDate * datePtr = dates;
4126                     int32_t idate;
4127                     for (idate = 0; idate < NUM_TEST_DATES; idate++, datePtr++) {
4128                         rootChineseCalendar->clear();
4129                         rootChineseCalendar->set(UCAL_ERA, datePtr->era);
4130                         rootChineseCalendar->set(datePtr->year, datePtr->month-1, datePtr->day);
4131                         rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, datePtr->isLeapMonth);
4132                         UnicodeString result;
4133                         FieldPosition fpos(FieldPosition::DONT_CARE);
4134                         dmft->format(*rootChineseCalendar, result, fpos);
4135                         if ( result.compare(itemPtr->dateString[idate]) != 0 ) {
4136                             errln( UnicodeString("FAIL: Chinese calendar format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4137                                     ", expected \"" + itemPtr->dateString[idate] + "\", got \"" + result + "\"");
4138                         } else {
4139                             // formatted OK, try parse
4140                             ParsePosition ppos(0);
4141                             // ensure we are really parsing the fields we should be
4142                             rootChineseCalendar->set(UCAL_YEAR, 1);
4143                             rootChineseCalendar->set(UCAL_MONTH, 0);
4144                             rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, 0);
4145                             rootChineseCalendar->set(UCAL_DATE, 1);
4146                             //
4147                             dmft->parse(result, *rootChineseCalendar, ppos);
4148                             int32_t year = rootChineseCalendar->get(UCAL_YEAR, status);
4149                             int32_t month = rootChineseCalendar->get(UCAL_MONTH, status) + 1;
4150                             int32_t isLeapMonth = rootChineseCalendar->get(UCAL_IS_LEAP_MONTH, status);
4151                             int32_t day = rootChineseCalendar->get(UCAL_DATE, status);
4152                             if ( ppos.getIndex() < result.length() || year != datePtr->year || month != datePtr->month || isLeapMonth != datePtr->isLeapMonth || day != datePtr->day ) {
4153                                 errln( UnicodeString("FAIL: Chinese calendar parse for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4154                                     ", string \"" + result + "\", expected " + datePtr->year +"-"+datePtr->month+"("+datePtr->isLeapMonth+")-"+datePtr->day + ", got pos " +
4155                                     ppos.getIndex() + " " + year +"-"+month+"("+isLeapMonth+")-"+day);
4156                             }
4157                         }
4158                     }
4159                 } else {
4160                     dataerrln("Error creating SimpleDateFormat for Chinese calendar- %s", u_errorName(status));
4161                 }
4162                 delete dmft;
4163             } else {
4164                 dataerrln("FAIL: Unable to create DateFormat for Chinese calendar- %s", u_errorName(status));
4165             }
4166         }
4167         delete rootChineseCalendar;
4168     } else {
4169         errln(UnicodeString("FAIL: Unable to create Calendar for root@calendar=chinese"));
4170     }
4171 }
4172 
4173 typedef struct {
4174     const char * locale;
4175     UnicodeString pattern;
4176     UDisplayContext capitalizationContext;
4177     UnicodeString expectedFormat;
4178 } TestContextItem;
4179 
TestContext()4180 void DateFormatTest::TestContext()
4181 {
4182     const UDate july022008 = 1215000001979.0;
4183     const TestContextItem items[] = {
4184         //locale              pattern    capitalizationContext                              expected formatted date
4185         { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_NONE,                      UnicodeString("juillet 2008") },
4186 #if !UCONFIG_NO_BREAK_ITERATION
4187         { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    UnicodeString("juillet 2008") },
4188         { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, UnicodeString("Juillet 2008") },
4189         { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU,       UnicodeString("juillet 2008") },
4190         { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE,            UnicodeString("Juillet 2008") },
4191 #endif
4192         { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_NONE,                      CharsToUnicodeString("\\u010Dervenec 2008") },
4193 #if !UCONFIG_NO_BREAK_ITERATION
4194         { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE,    CharsToUnicodeString("\\u010Dervenec 2008") },
4195         { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, CharsToUnicodeString("\\u010Cervenec 2008") },
4196         { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU,       CharsToUnicodeString("\\u010Cervenec 2008") },
4197         { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE,            CharsToUnicodeString("\\u010Dervenec 2008") },
4198 #endif
4199         // terminator
4200         { NULL, UnicodeString(""),       (UDisplayContext)0, UnicodeString("") }
4201     };
4202     UErrorCode status = U_ZERO_ERROR;
4203     Calendar* cal = Calendar::createInstance(status);
4204     if (U_FAILURE(status)) {
4205         dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4206     } else {
4207         cal->setTime(july022008, status);
4208         const TestContextItem * itemPtr;
4209         for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4210            Locale locale = Locale::createFromName(itemPtr->locale);
4211            status = U_ZERO_ERROR;
4212            SimpleDateFormat * sdmft = new SimpleDateFormat(itemPtr->pattern, locale, status);
4213            if (U_FAILURE(status)) {
4214                 dataerrln(UnicodeString("FAIL: Unable to create SimpleDateFormat for specified pattern with locale ") + UnicodeString(itemPtr->locale));
4215            } else {
4216                sdmft->setContext(itemPtr->capitalizationContext, status);
4217                UnicodeString result;
4218                FieldPosition pos(FieldPosition::DONT_CARE);
4219                sdmft->format(*cal, result, pos);
4220                if (result.compare(itemPtr->expectedFormat) != 0) {
4221                    errln(UnicodeString("FAIL: format for locale ") + UnicodeString(itemPtr->locale) +
4222                            ", status " + (int)status +
4223                            ", capitalizationContext " + (int)itemPtr->capitalizationContext +
4224                            ", expected " + itemPtr->expectedFormat + ", got " + result);
4225                }
4226            }
4227            if (sdmft) {
4228                delete sdmft;
4229            }
4230         }
4231     }
4232     if (cal) {
4233         delete cal;
4234     }
4235 }
4236 
4237 // test item for a particular locale + calendar and date format
4238 typedef struct {
4239     int32_t era;
4240     int32_t year;
4241     int32_t month;
4242     int32_t day;
4243     int32_t hour;
4244     int32_t minute;
4245     UnicodeString formattedDate;
4246 } CalAndFmtTestItem;
4247 
4248 // test item giving locale + calendar, date format, and CalAndFmtTestItems
4249 typedef struct {
4250     const char * locale; // with calendar
4251     DateFormat::EStyle style;
4252     UnicodeString pattern; // ignored unless style == DateFormat::kNone
4253     const CalAndFmtTestItem *caftItems;
4254 } TestNonGregoItem;
4255 
TestNonGregoFmtParse()4256 void DateFormatTest::TestNonGregoFmtParse()
4257 {
4258     // test items for he@calendar=hebrew, long date format
4259     const CalAndFmtTestItem cafti_he_hebrew_long[] = {
4260         {  0, 4999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05D3\\u05F3\\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4261         {  0, 5100,  0,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05E7\\u05F3") },
4262         {  0, 5774,  5,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05D0\\u05D3\\u05E8 \\u05D0\\u05F3 \\u05EA\\u05E9\\u05E2\\u05F4\\u05D3") },
4263         {  0, 5999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4264         {  0, 6100,  0,  1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05D5\\u05F3\\u05E7\\u05F3") },
4265         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4266     };
4267     const CalAndFmtTestItem cafti_zh_chinese_custU[] = {
4268         { 78,   31,  0,  1, 12, 0, CharsToUnicodeString("2014\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4269         { 77,   31,  0,  1, 12, 0, CharsToUnicodeString("1954\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4270         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4271     };
4272     const CalAndFmtTestItem cafti_zh_chinese_custNoU[] = {
4273         { 78,   31,  0,  1, 12, 0, CharsToUnicodeString("2014\\u5E74\\u6B63\\u67081") },
4274         { 77,   31,  0,  1, 12, 0, CharsToUnicodeString("1954\\u5E74\\u6B63\\u67081") },
4275         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4276     };
4277     const CalAndFmtTestItem cafti_ja_japanese_custGy[] = {
4278         {235,   26,  2,  5, 12, 0, CharsToUnicodeString("2014(\\u5E73\\u621026)\\u5E743\\u67085\\u65E5") },
4279         {234,   60,  2,  5, 12, 0, CharsToUnicodeString("1985(\\u662D\\u548C60)\\u5E743\\u67085\\u65E5") },
4280         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4281     };
4282     const CalAndFmtTestItem cafti_ja_japanese_custNoGy[] = {
4283         {235,   26,  2,  5, 12, 0, CharsToUnicodeString("2014\\u5E743\\u67085\\u65E5") },
4284         {234,   60,  2,  5, 12, 0, CharsToUnicodeString("1985\\u5E743\\u67085\\u65E5") },
4285         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4286     };
4287     const CalAndFmtTestItem cafti_en_islamic_cust[] = {
4288         {  0, 1384,  0,  1, 12, 0, UnicodeString("1 Muh. 1384 AH, 1964") },
4289         {  0, 1436,  0,  1, 12, 0, UnicodeString("1 Muh. 1436 AH, 2014") },
4290         {  0, 1487,  0,  1, 12, 0, UnicodeString("1 Muh. 1487 AH, 2064") },
4291         {  0,    0,  0,  0,  0, 0, UnicodeString("") } // terminator
4292     };
4293     // overal test items
4294     const TestNonGregoItem items[] = {
4295         { "he@calendar=hebrew",   DateFormat::kLong, UnicodeString(""),                 cafti_he_hebrew_long },
4296         { "zh@calendar=chinese",  DateFormat::kNone, CharsToUnicodeString("rU\\u5E74MMMd"),                cafti_zh_chinese_custU },
4297         { "zh@calendar=chinese",  DateFormat::kNone, CharsToUnicodeString("r\\u5E74MMMd"),                 cafti_zh_chinese_custNoU },
4298         { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r(Gy)\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custGy },
4299         { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74M\\u6708d\\u65E5"),     cafti_ja_japanese_custNoGy },
4300         { "en@calendar=islamic",  DateFormat::kNone, UnicodeString("d MMM y G, r"),     cafti_en_islamic_cust },
4301         { NULL, DateFormat::kNone, UnicodeString(""), NULL } // terminator
4302     };
4303     const TestNonGregoItem * itemPtr;
4304     for (itemPtr = items; itemPtr->locale != NULL; itemPtr++) {
4305         Locale locale = Locale::createFromName(itemPtr->locale);
4306         DateFormat * dfmt = NULL;
4307         UErrorCode status = U_ZERO_ERROR;
4308         if (itemPtr->style != DateFormat::kNone) {
4309             dfmt = DateFormat::createDateInstance(itemPtr->style, locale);
4310         } else {
4311             dfmt = new SimpleDateFormat(itemPtr->pattern, locale, status);
4312         }
4313         if (U_FAILURE(status)) {
4314             dataerrln("new SimpleDateFormat fails for locale %s", itemPtr->locale);
4315         } else  if (dfmt == NULL) {
4316             dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->locale);
4317         } else {
4318             Calendar * cal = (dfmt->getCalendar())->clone();
4319             if (cal == NULL) {
4320                 dataerrln("(DateFormat::getCalendar)->clone() fails for locale %s", itemPtr->locale);
4321             } else {
4322                 const CalAndFmtTestItem * caftItemPtr;
4323                 for (caftItemPtr = itemPtr->caftItems; caftItemPtr->year != 0; caftItemPtr++) {
4324                     cal->clear();
4325                     cal->set(UCAL_ERA,    caftItemPtr->era);
4326                     cal->set(UCAL_YEAR,   caftItemPtr->year);
4327                     cal->set(UCAL_MONTH,  caftItemPtr->month);
4328                     cal->set(UCAL_DATE,   caftItemPtr->day);
4329                     cal->set(UCAL_HOUR_OF_DAY, caftItemPtr->hour);
4330                     cal->set(UCAL_MINUTE, caftItemPtr->minute);
4331                     UnicodeString result;
4332                     FieldPosition fpos(FieldPosition::DONT_CARE);
4333                     dfmt->format(*cal, result, fpos);
4334                     if ( result.compare(caftItemPtr->formattedDate) != 0 ) {
4335                         errln( UnicodeString("FAIL: date format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4336                                 ", expected \"" + caftItemPtr->formattedDate + "\", got \"" + result + "\"");
4337                     } else {
4338                         // formatted OK, try parse
4339                         ParsePosition ppos(0);
4340                         dfmt->parse(result, *cal, ppos);
4341                         status = U_ZERO_ERROR;
4342                         int32_t era = cal->get(UCAL_ERA, status);
4343                         int32_t year = cal->get(UCAL_YEAR, status);
4344                         int32_t month = cal->get(UCAL_MONTH, status);
4345                         int32_t day = cal->get(UCAL_DATE, status);
4346                         if ( U_FAILURE(status) || ppos.getIndex() < result.length() || era != caftItemPtr->era ||
4347                                 year != caftItemPtr->year || month != caftItemPtr->month || day != caftItemPtr->day ) {
4348                             errln( UnicodeString("FAIL: date parse for locale ") + UnicodeString(itemPtr->locale) +
4349                                 ", style " + itemPtr->style + ", string \"" + result + "\", expected " +
4350                                 caftItemPtr->era +":"+caftItemPtr->year +"-"+caftItemPtr->month+"-"+caftItemPtr->day + ", got pos " +
4351                                 ppos.getIndex() + " " + year +"-"+month+"-"+day + " status " + UnicodeString(u_errorName(status)) );
4352                         }
4353                     }
4354                 }
4355                 delete cal;
4356             }
4357             delete dfmt;
4358         }
4359     }
4360 }
4361 
4362 typedef struct {
4363     const char*         localeID;
4364     DateFormat::EStyle  style;
4365     UnicodeString       expectPattern;
4366     UnicodeString       expectFormat;
4367 } TestFmtWithNumSysItem;
4368 enum { kBBufMax = 128 };
TestFormatsWithNumberSystems()4369 void DateFormatTest::TestFormatsWithNumberSystems()
4370 {
4371     LocalPointer<TimeZone> zone(TimeZone::createTimeZone(UnicodeString("UTC")));
4372     const UDate date = 1451556000000.0; // for UTC: grego 31-Dec-2015 10 AM, hebrew 19 tevet 5776, chinese yi-wei 11mo 21day
4373     const TestFmtWithNumSysItem items[] = {
4374         { "haw@calendar=gregorian", DateFormat::kShort, UnicodeString("d/M/yy"),               UnicodeString("31/xii/15") },
4375         { "he@calendar=hebrew",     DateFormat::kLong, CharsToUnicodeString("d \\u05D1MMMM y"), CharsToUnicodeString("\\u05D9\\u05F4\\u05D8 \\u05D1\\u05D8\\u05D1\\u05EA \\u05EA\\u05E9\\u05E2\\u05F4\\u05D5") },
4376         { "zh@calendar=chinese",      DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u5341\\u4E00\\u6708\\u5EFF\\u4E00") },
4377         { "zh_Hant@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u51AC\\u6708\\u5EFF\\u4E00") },
4378         { "ja@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("U\\u5E74MMMd\\u65E5"), CharsToUnicodeString("\\u4E59\\u672A\\u5E74\\u5341\\u4E00\\u6708\\u4E8C\\u4E00\\u65E5") },
4379         { NULL, DateFormat::kNone, UnicodeString(""), UnicodeString("") },
4380     };
4381     const TestFmtWithNumSysItem * itemPtr;
4382     for (itemPtr = items; itemPtr->localeID != NULL; itemPtr++) {
4383         char bExpected[kBBufMax];
4384         char bResult[kBBufMax];
4385         UErrorCode status = U_ZERO_ERROR;
4386         Locale locale = Locale::createFromName(itemPtr->localeID);
4387         LocalPointer<Calendar> cal(Calendar::createInstance(zone.orphan(), locale, status));
4388         if (U_FAILURE(status)) {
4389             dataerrln("Calendar::createInstance fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4390             continue;
4391         }
4392         cal->setTime(date, status);
4393         if (U_FAILURE(status)) {
4394             dataerrln("Calendar::setTime fails for locale %s, date %.1f, status %s", itemPtr->localeID, date, u_errorName(status));
4395             continue;
4396         }
4397         LocalPointer<SimpleDateFormat> sdfmt(static_cast<SimpleDateFormat *>(DateFormat::createDateInstance(itemPtr->style, locale)));
4398         if (sdfmt.isNull()) {
4399             dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->localeID);
4400             continue;
4401         }
4402         UnicodeString getFormat;
4403         sdfmt->format(*(cal.getAlias()), getFormat, NULL, status);
4404         if (U_FAILURE(status)) {
4405             errln("DateFormat::format fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4406             continue;
4407         }
4408         if (getFormat.compare(itemPtr->expectFormat) != 0) {
4409             itemPtr->expectFormat.extract(0, itemPtr->expectFormat.length(), bExpected, kBBufMax);
4410             getFormat.extract(0, getFormat.length(), bResult, kBBufMax);
4411             errln("DateFormat::format for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4412         }
4413         UnicodeString getPattern;
4414         sdfmt->toPattern(getPattern);
4415         if (getPattern.compare(itemPtr->expectPattern) != 0) {
4416             itemPtr->expectPattern.extract(0, itemPtr->expectPattern.length(), bExpected, kBBufMax);
4417             getPattern.extract(0, getPattern.length(), bResult, kBBufMax);
4418             errln("DateFormat::toPattern() for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4419         }
4420     }
4421 }
4422 
4423 static const UDate TEST_DATE = 1326585600000.;  // 2012-jan-15
4424 
TestDotAndAtLeniency()4425 void DateFormatTest::TestDotAndAtLeniency() {
4426     // Test for date/time parsing regression with CLDR 22.1/ICU 50 pattern strings.
4427     // For details see http://bugs.icu-project.org/trac/ticket/9789
4428     static const char *locales[] = { "en", "fr" };
4429     for (int32_t i = 0; i < UPRV_LENGTHOF(locales); ++i) {
4430         Locale locale(locales[i]);
4431 
4432         for (DateFormat::EStyle dateStyle = DateFormat::FULL; dateStyle <= DateFormat::SHORT;
4433                   dateStyle = static_cast<DateFormat::EStyle>(dateStyle + 1)) {
4434             LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance(dateStyle, locale));
4435 
4436             for (DateFormat::EStyle timeStyle = DateFormat::FULL; timeStyle <= DateFormat::SHORT;
4437                       timeStyle = static_cast<DateFormat::EStyle>(timeStyle + 1)) {
4438                 LocalPointer<DateFormat> format(DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale));
4439                 LocalPointer<DateFormat> timeFormat(DateFormat::createTimeInstance(timeStyle, locale));
4440                 UnicodeString formattedString;
4441                 if (format.isNull()) {
4442                     dataerrln("Unable to create DateFormat");
4443                     continue;
4444                 }
4445                 format->format(TEST_DATE, formattedString);
4446 
4447                 if (!showParse(*format, formattedString)) {
4448                     errln(UnicodeString("    with date-time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4449                 }
4450 
4451                 UnicodeString ds, ts;
4452                 formattedString = dateFormat->format(TEST_DATE, ds) + "  " + timeFormat->format(TEST_DATE, ts);
4453                 if (!showParse(*format, formattedString)) {
4454                     errln(UnicodeString("    with date sp sp time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4455                 }
4456                 if (formattedString.indexOf("n ") >= 0) { // will add "." after the end of text ending in 'n', like Jan.
4457                     UnicodeString plusDot(formattedString);
4458                     plusDot.findAndReplace("n ", "n. ").append(".");
4459                     if (!showParse(*format, plusDot)) {
4460                         errln(UnicodeString("    with date plus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4461                     }
4462                 }
4463                 if (formattedString.indexOf(". ") >= 0) { // will subtract "." at the end of strings.
4464                     UnicodeString minusDot(formattedString);
4465                     minusDot.findAndReplace(". ", " ");
4466                     if (!showParse(*format, minusDot)) {
4467                         errln(UnicodeString("    with date minus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4468                     }
4469                 }
4470             }
4471         }
4472     }
4473 }
4474 
showParse(DateFormat & format,const UnicodeString & formattedString)4475 UBool DateFormatTest::showParse(DateFormat &format, const UnicodeString &formattedString) {
4476     ParsePosition parsePosition;
4477     UDate parsed = format.parse(formattedString, parsePosition);
4478     UBool ok = TEST_DATE == parsed && parsePosition.getIndex() == formattedString.length();
4479     UnicodeString pattern;
4480     static_cast<SimpleDateFormat &>(format).toPattern(pattern);
4481     if (ok) {
4482         logln(pattern + "  parsed: " + formattedString);
4483     } else {
4484         errln(pattern + "  fails to parse: " + formattedString);
4485     }
4486     return ok;
4487 }
4488 
4489 
4490 typedef struct {
4491     const char * locale;
4492     UBool leniency;
4493     UnicodeString parseString;
4494     UnicodeString pattern;
4495     UnicodeString expectedResult;       // empty string indicates expected error
4496 } TestDateFormatLeniencyItem;
4497 
TestDateFormatLeniency()4498 void DateFormatTest::TestDateFormatLeniency() {
4499     // For details see http://bugs.icu-project.org/trac/ticket/10261
4500 
4501     const UDate july022008 = 1215000001979.0;
4502     const TestDateFormatLeniencyItem items[] = {
4503         //locale    leniency    parse String                    pattern                             expected result
4504         { "en",     true,       UnicodeString("2008-07 02"),    UnicodeString("yyyy-LLLL dd"),      UnicodeString("2008-July 02") },
4505         { "en",     false,      UnicodeString("2008-07 02"),    UnicodeString("yyyy-LLLL dd"),      UnicodeString("") },
4506         { "en",     true,       UnicodeString("2008-Jan 02"),   UnicodeString("yyyy-LLL. dd"),      UnicodeString("2008-Jan. 02") },
4507         { "en",     false,      UnicodeString("2008-Jan 02"),   UnicodeString("yyyy-LLL. dd"),      UnicodeString("") },
4508         { "en",     true,       UnicodeString("2008-Jan--02"),  UnicodeString("yyyy-MMM' -- 'dd"),  UnicodeString("2008-Jan -- 02") },
4509         { "en",     false,      UnicodeString("2008-Jan--02"),  UnicodeString("yyyy-MMM' -- 'dd"),  UnicodeString("") },
4510         // terminator
4511         { NULL,     true,       UnicodeString(""),              UnicodeString(""),                  UnicodeString("") }
4512     };
4513     UErrorCode status = U_ZERO_ERROR;
4514     LocalPointer<Calendar> cal(Calendar::createInstance(status));
4515     if (U_FAILURE(status)) {
4516         dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4517         return;
4518     }
4519     cal->setTime(july022008, status);
4520     const TestDateFormatLeniencyItem * itemPtr;
4521     LocalPointer<SimpleDateFormat> sdmft;
4522     for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4523 
4524        Locale locale = Locale::createFromName(itemPtr->locale);
4525        status = U_ZERO_ERROR;
4526        ParsePosition pos(0);
4527        sdmft.adoptInsteadAndCheckErrorCode(new SimpleDateFormat(itemPtr->pattern, locale, status), status);
4528        if (U_FAILURE(status)) {
4529            dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4530            continue;
4531        }
4532        sdmft->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->leniency, status).
4533               setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->leniency, status).
4534               setBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, itemPtr->leniency, status);
4535        UDate d = sdmft->parse(itemPtr->parseString, pos);
4536 
4537        if(itemPtr->expectedResult.length() == 0) {
4538            if(pos.getErrorIndex() != -1) {
4539                continue;
4540            } else {
4541                 errln("error: unexpected parse success - " + itemPtr->parseString +
4542                     " - pattern " + itemPtr->pattern +
4543                     " - error index " + pos.getErrorIndex() +
4544                     " - leniency " + itemPtr->leniency);
4545                 continue;
4546            }
4547        }
4548        if(pos.getErrorIndex() != -1) {
4549            errln("error: parse error for string - "  + itemPtr->parseString +
4550                  " - pattern " + itemPtr->pattern +
4551                  " - idx " + pos.getIndex() +
4552                  " - error index "+pos.getErrorIndex() +
4553                  " - leniency " + itemPtr->leniency);
4554             continue;
4555         }
4556 
4557        UnicodeString formatResult("");
4558        sdmft->format(d, formatResult);
4559        if(formatResult.compare(itemPtr->expectedResult) != 0) {
4560            errln("error: unexpected format result. pattern["+itemPtr->pattern+"] expected[" + itemPtr->expectedResult + "]  but result was[" + formatResult + "]");
4561            continue;
4562         } else {
4563             logln("formatted results match! - " + formatResult);
4564         }
4565 
4566     }
4567 }
4568 
4569 
4570 typedef struct {
4571     UBool leniency;
4572     UnicodeString parseString;
4573     UnicodeString pattern;
4574     UnicodeString expectedResult;       // empty string indicates expected error
4575 } TestMultiPatternMatchItem;
4576 
TestParseMultiPatternMatch()4577 void DateFormatTest::TestParseMultiPatternMatch() {
4578         // For details see http://bugs.icu-project.org/trac/ticket/10336
4579     const TestMultiPatternMatchItem items[] = {
4580           // leniency    parse String                                 pattern                               expected result
4581             {true,       UnicodeString("2013-Sep 13"),                UnicodeString("yyyy-MMM dd"),         UnicodeString("2013-Sep 13")},
4582             {true,       UnicodeString("2013-September 14"),          UnicodeString("yyyy-MMM dd"),         UnicodeString("2013-Sep 14")},
4583             {false,      UnicodeString("2013-September 15"),          UnicodeString("yyyy-MMM dd"),         UnicodeString("")},
4584             {false,      UnicodeString("2013-September 16"),          UnicodeString("yyyy-MMMM dd"),        UnicodeString("2013-September 16")},
4585             {true,       UnicodeString("2013-Sep 17"),                UnicodeString("yyyy-LLL dd"),         UnicodeString("2013-Sep 17")},
4586             {true,       UnicodeString("2013-September 18"),          UnicodeString("yyyy-LLL dd"),         UnicodeString("2013-Sep 18")},
4587             {false,      UnicodeString("2013-September 19"),          UnicodeString("yyyy-LLL dd"),         UnicodeString("")},
4588             {false,      UnicodeString("2013-September 20"),          UnicodeString("yyyy-LLLL dd"),        UnicodeString("2013-September 20")},
4589             {true,       UnicodeString("2013 Sat Sep 21"),            UnicodeString("yyyy EEE MMM dd"),     UnicodeString("2013 Sat Sep 21")},
4590             {true,       UnicodeString("2013 Sunday Sep 22"),         UnicodeString("yyyy EEE MMM dd"),     UnicodeString("2013 Sun Sep 22")},
4591             {false,      UnicodeString("2013 Monday Sep 23"),         UnicodeString("yyyy EEE MMM dd"),     UnicodeString("")},
4592             {false,      UnicodeString("2013 Tuesday Sep 24"),        UnicodeString("yyyy EEEE MMM dd"),    UnicodeString("2013 Tuesday Sep 24")},
4593             {true,       UnicodeString("2013 Wed Sep 25"),            UnicodeString("yyyy eee MMM dd"),     UnicodeString("2013 Wed Sep 25")},
4594             {true,       UnicodeString("2013 Thu Sep 26"),            UnicodeString("yyyy eee MMM dd"),     UnicodeString("2013 Thu Sep 26")},
4595             {false,      UnicodeString("2013 Friday Sep 27"),         UnicodeString("yyyy eee MMM dd"),     UnicodeString("")},
4596             {false,      UnicodeString("2013 Saturday Sep 28"),       UnicodeString("yyyy eeee MMM dd"),    UnicodeString("2013 Saturday Sep 28")},
4597             {true,       UnicodeString("2013 Sun Sep 29"),            UnicodeString("yyyy ccc MMM dd"),     UnicodeString("2013 Sun Sep 29")},
4598             {true,       UnicodeString("2013 Monday Sep 30"),         UnicodeString("yyyy ccc MMM dd"),     UnicodeString("2013 Mon Sep 30")},
4599             {false,      UnicodeString("2013 Sunday Oct 13"),         UnicodeString("yyyy ccc MMM dd"),     UnicodeString("")},
4600             {false,      UnicodeString("2013 Monday Oct 14"),         UnicodeString("yyyy cccc MMM dd"),    UnicodeString("2013 Monday Oct 14")},
4601             {true,       UnicodeString("2013 Oct 15 Q4"),             UnicodeString("yyyy MMM dd QQQ"),     UnicodeString("2013 Oct 15 Q4")},
4602             {true,       UnicodeString("2013 Oct 16 4th quarter"),    UnicodeString("yyyy MMM dd QQQ"),     UnicodeString("2013 Oct 16 Q4")},
4603             {false,      UnicodeString("2013 Oct 17 4th quarter"),    UnicodeString("yyyy MMM dd QQQ"),     UnicodeString("")},
4604             {false,      UnicodeString("2013 Oct 18 Q4"),             UnicodeString("yyyy MMM dd QQQ"),     UnicodeString("2013 Oct 18 Q4")},
4605             {true,       UnicodeString("2013 Oct 19 Q4"),             UnicodeString("yyyy MMM dd qqqq"),    UnicodeString("2013 Oct 19 4th quarter")},
4606             {true,       UnicodeString("2013 Oct 20 4th quarter"),    UnicodeString("yyyy MMM dd qqqq"),    UnicodeString("2013 Oct 20 4th quarter")},
4607             {false,      UnicodeString("2013 Oct 21 Q4"),             UnicodeString("yyyy MMM dd qqqq"),    UnicodeString("")},
4608             {false,      UnicodeString("2013 Oct 22 4th quarter"),    UnicodeString("yyyy MMM dd qqqq"),    UnicodeString("2013 Oct 22 4th quarter")},
4609             {false,      UnicodeString("--end--"),                    UnicodeString(""),                    UnicodeString("")},
4610     };
4611 
4612     UErrorCode status = U_ZERO_ERROR;
4613     LocalPointer<Calendar> cal(Calendar::createInstance(status));
4614     if (U_FAILURE(status)) {
4615         dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4616         return;
4617     }
4618     const TestMultiPatternMatchItem * itemPtr;
4619     DateFormat* sdmft = DateFormat::createDateInstance();
4620     if (sdmft == NULL) {
4621         dataerrln(UnicodeString("FAIL: Unable to create DateFormat"));
4622         return;
4623     }
4624     for (itemPtr = items; itemPtr->parseString != "--end--"; itemPtr++ ) {
4625        status = U_ZERO_ERROR;
4626        ParsePosition pos(0);
4627        ((SimpleDateFormat*) sdmft)->applyPattern(itemPtr->pattern);
4628        if (U_FAILURE(status)) {
4629            dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4630            continue;
4631        }
4632        sdmft->setBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, itemPtr->leniency, status);
4633        UDate d = sdmft->parse(itemPtr->parseString, pos);
4634 
4635        if(itemPtr->expectedResult.length() == 0) {
4636            if(pos.getErrorIndex() != -1) {
4637                continue;
4638            } else {
4639                 errln("error: unexpected parse success - " + itemPtr->parseString +
4640                     " - error index " + pos.getErrorIndex() +
4641                     " - leniency " + itemPtr->leniency);
4642                 continue;
4643            }
4644         }
4645         if(pos.getErrorIndex() != -1) {
4646             errln("error: parse error for string - " +itemPtr->parseString + " -- idx["+pos.getIndex()+"] errIdx["+pos.getErrorIndex()+"]");
4647             continue;
4648         }
4649 
4650         UnicodeString formatResult("");
4651         sdmft->format(d, formatResult);
4652         if(formatResult.compare(itemPtr->expectedResult) != 0) {
4653             errln("error: unexpected format result. expected[" + itemPtr->expectedResult + "]  but result was[" + formatResult + "]");
4654         } else {
4655             logln("formatted results match! - " + formatResult);
4656         }
4657     }
4658     delete sdmft;
4659 }
4660 
TestParseLeniencyAPIs()4661 void DateFormatTest::TestParseLeniencyAPIs() {
4662     UErrorCode status = U_ZERO_ERROR;
4663     LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance());
4664     DateFormat *fmt = dateFormat.getAlias();
4665     if (fmt == NULL) {
4666         dataerrln("Failed calling dateFormat.getAlias()");
4667         return;
4668     }
4669 
4670     assertTrue("isLenient default", fmt->isLenient());
4671     assertTrue("isCalendarLenient default", fmt->isCalendarLenient());
4672     assertTrue("ALLOW_WHITESPACE default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4673     assertTrue("ALLOW_NUMERIC default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4674     assertTrue("PARTIAL_MATCH default", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4675     assertTrue("MULTIPLE_PATTERNS default", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4676 
4677     // Set calendar to strict
4678     fmt->setCalendarLenient(FALSE);
4679 
4680     assertFalse("isLeninent after setCalendarLenient(FALSE)", fmt->isLenient());
4681     assertFalse("isCalendarLenient after setCalendarLenient(FALSE)", fmt->isCalendarLenient());
4682     assertTrue("ALLOW_WHITESPACE after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4683     assertTrue("ALLOW_NUMERIC  after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4684 
4685     // Set to strict
4686     fmt->setLenient(FALSE);
4687 
4688     assertFalse("isLeninent after setLenient(FALSE)", fmt->isLenient());
4689     assertFalse("isCalendarLenient after setLenient(FALSE)", fmt->isCalendarLenient());
4690     assertFalse("ALLOW_WHITESPACE after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4691     assertFalse("ALLOW_NUMERIC  after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4692     // These two boolean attributes are NOT affected according to the API specification
4693     assertTrue("PARTIAL_MATCH after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4694     assertTrue("MULTIPLE_PATTERNS after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4695 
4696     // Allow white space leniency
4697     fmt->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, TRUE, status);
4698 
4699     assertFalse("isLeninent after ALLOW_WHITESPACE/TRUE", fmt->isLenient());
4700     assertFalse("isCalendarLenient after ALLOW_WHITESPACE/TRUE", fmt->isCalendarLenient());
4701     assertTrue("ALLOW_WHITESPACE after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4702     assertFalse("ALLOW_NUMERIC  after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4703 
4704     // Set to lenient
4705     fmt->setLenient(TRUE);
4706 
4707     assertTrue("isLenient after setLenient(TRUE)", fmt->isLenient());
4708     assertTrue("isCalendarLenient after setLenient(TRUE)", fmt->isCalendarLenient());
4709     assertTrue("ALLOW_WHITESPACE after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4710     assertTrue("ALLOW_NUMERIC after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4711 }
4712 
TestNumberFormatOverride()4713 void DateFormatTest::TestNumberFormatOverride() {
4714     UErrorCode status = U_ZERO_ERROR;
4715     UnicodeString fields = (UnicodeString) "M";
4716 
4717     LocalPointer<SimpleDateFormat> fmt;
4718     fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4719     if (!assertSuccess("SimpleDateFormat with pattern MM d", status)) {
4720         return;
4721     }
4722 
4723 
4724     for(int i=0; i<3; i++){
4725         NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4726         assertSuccess("NumberFormat en_US", status);
4727         fmt->adoptNumberFormat(fields, check_nf, status);
4728         assertSuccess("adoptNumberFormat check_nf", status);
4729 
4730         const NumberFormat* get_nf = fmt->getNumberFormatForField((UChar)0x004D /*'M'*/);
4731         if (get_nf != check_nf) errln("FAIL: getter and setter do not work");
4732     }
4733     NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4734     assertSuccess("NumberFormat en_US", status);
4735     fmt->adoptNumberFormat(check_nf); // make sure using the same NF will not crash
4736 
4737     const char * DATA [][2] = {
4738         { "", "\\u521D\\u516D \\u5341\\u4E94"},
4739         { "M", "\\u521D\\u516D 15"},
4740         { "Mo", "\\u521D\\u516D 15"},
4741         { "Md", "\\u521D\\u516D \\u5341\\u4E94"},
4742         { "MdMMd", "\\u521D\\u516D \\u5341\\u4E94"},
4743         { "mixed", "\\u521D\\u516D \\u5341\\u4E94"}
4744     };
4745 
4746     UDate test_date = date(97, 6 - 1, 15);
4747 
4748     for(int i=0; i < UPRV_LENGTHOF(DATA); i++){
4749         fields = DATA[i][0];
4750 
4751         LocalPointer<SimpleDateFormat> fmt;
4752         fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4753         assertSuccess("SimpleDateFormat with pattern MM d", status);
4754         NumberFormat* overrideNF = NumberFormat::createInstance(Locale::createFromName("zh@numbers=hanidays"),status);
4755         assertSuccess("NumberFormat zh@numbers=hanidays", status);
4756 
4757         if (fields == (UnicodeString) "") { // use the one w/o fields
4758             fmt->adoptNumberFormat(overrideNF);
4759         } else if (fields == (UnicodeString) "mixed") { // set 1 field at first but then full override, both(M & d) should be override
4760             NumberFormat* singleOverrideNF = NumberFormat::createInstance(Locale::createFromName("en@numbers=hebr"),status);
4761             assertSuccess("NumberFormat en@numbers=hebr", status);
4762 
4763             fields = (UnicodeString) "M";
4764             fmt->adoptNumberFormat(fields, singleOverrideNF, status);
4765             assertSuccess("adoptNumberFormat singleOverrideNF", status);
4766 
4767             fmt->adoptNumberFormat(overrideNF);
4768         } else if (fields == (UnicodeString) "Mo"){ // o is invlid field
4769             fmt->adoptNumberFormat(fields, overrideNF, status);
4770             if(status == U_INVALID_FORMAT_ERROR) {
4771                 status = U_ZERO_ERROR;
4772                 continue;
4773             }
4774         } else {
4775             fmt->adoptNumberFormat(fields, overrideNF, status);
4776             assertSuccess("adoptNumberFormat overrideNF", status);
4777         }
4778 
4779         UnicodeString result;
4780         FieldPosition pos(FieldPosition::DONT_CARE);
4781         fmt->format(test_date,result, pos);
4782 
4783         UnicodeString expected = ((UnicodeString)DATA[i][1]).unescape();;
4784 
4785         if (result != expected)
4786             errln("FAIL: Expected " + expected + " get: " + result);
4787     }
4788 }
4789 
TestCreateInstanceForSkeleton()4790 void DateFormatTest::TestCreateInstanceForSkeleton() {
4791     UErrorCode status = U_ZERO_ERROR;
4792     LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4793             "yMMMMd", "en", status));
4794     if (!assertSuccess("Create with pattern yMMMMd", status)) {
4795         return;
4796     }
4797     UnicodeString result;
4798     FieldPosition pos(FieldPosition::DONT_CARE);
4799     fmt->format(date(98, 5-1, 25), result, pos);
4800     assertEquals("format yMMMMd", "May 25, 1998", result);
4801     fmt.adoptInstead(DateFormat::createInstanceForSkeleton(
4802             "yMd", "en", status));
4803     if (!assertSuccess("Create with pattern yMd", status)) {
4804         return;
4805     }
4806     result.remove();
4807     fmt->format(date(98, 5-1, 25), result, pos);
4808     assertEquals("format yMd", "5/25/1998", result);
4809 }
4810 
TestCreateInstanceForSkeletonDefault()4811 void DateFormatTest::TestCreateInstanceForSkeletonDefault() {
4812     UErrorCode status = U_ZERO_ERROR;
4813     Locale savedLocale;
4814     Locale::setDefault(Locale::getUS(), status);
4815     LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4816             "yMMMd", status));
4817     Locale::setDefault(savedLocale, status);
4818     if (!assertSuccess("Create with pattern yMMMd", status)) {
4819         return;
4820     }
4821     UnicodeString result;
4822     FieldPosition pos(FieldPosition::DONT_CARE);
4823     fmt->format(date(98, 5-1, 25), result, pos);
4824     assertEquals("format yMMMd", "May 25, 1998", result);
4825 }
4826 
TestCreateInstanceForSkeletonWithCalendar()4827 void DateFormatTest::TestCreateInstanceForSkeletonWithCalendar() {
4828     UErrorCode status = U_ZERO_ERROR;
4829     LocalPointer<DateFormat> fmt(
4830             DateFormat::createInstanceForSkeleton(
4831                     Calendar::createInstance(
4832                             TimeZone::createTimeZone("GMT-3:00"),
4833                             status),
4834                     "yMdHm", "en", status));
4835     if (!assertSuccess("Create with pattern yMMMMd", status)) {
4836         return;
4837     }
4838     UnicodeString result;
4839     FieldPosition pos(FieldPosition::DONT_CARE);
4840 
4841     LocalPointer<Calendar> cal(Calendar::createInstance(
4842         TimeZone::createTimeZone("GMT-7:00"),
4843         status));
4844     if (!assertSuccess("Creating GMT-7 time zone failed", status)) {
4845         return;
4846     }
4847     cal->clear();
4848     cal->set(1998, 5-1, 25, 0, 0, 0);
4849 
4850     // date format time zone should be 4 hours ahead.
4851     fmt->format(cal->getTime(status), result, pos);
4852     assertEquals("format yMdHm", "5/25/1998, 04:00", result);
4853     assertSuccess("", status);
4854 }
4855 
TestDFSCreateForLocaleNonGregorianLocale()4856 void DateFormatTest::TestDFSCreateForLocaleNonGregorianLocale() {
4857     UErrorCode status = U_ZERO_ERROR;
4858     Locale fa("fa");
4859     LocalPointer<DateFormatSymbols> sym(
4860             DateFormatSymbols::createForLocale(fa, status));
4861     if (!assertSuccess("", status)) {
4862         return;
4863     }
4864 
4865     // Android: All locales default to Gregorian calendar:
4866     int32_t count;
4867     const UnicodeString *months = sym->getShortMonths(count);
4868 
4869     // First persian month.
4870     UnicodeString expected("\\u0698\\u0627\\u0646\\u0648\\u06CC\\u0647\\u0654");  // Android-changed
4871     assertEquals("", expected.unescape(), months[0]);
4872 }
4873 
TestDFSCreateForLocaleWithCalendarInLocale()4874 void DateFormatTest::TestDFSCreateForLocaleWithCalendarInLocale() {
4875     UErrorCode status = U_ZERO_ERROR;
4876     Locale en_heb("en@calendar=hebrew");
4877     LocalPointer<DateFormatSymbols> sym(
4878             DateFormatSymbols::createForLocale(en_heb, status));
4879     if (!assertSuccess("", status)) {
4880         return;
4881     }
4882 
4883     // We should get the months of the hebrew calendar, not the gregorian
4884     // calendar.
4885     int32_t count;
4886     const UnicodeString *months = sym->getShortMonths(count);
4887 
4888     // First hebrew month.
4889     UnicodeString expected("Tishri");
4890     assertEquals("", expected, months[0]);
4891 }
4892 
TestChangeCalendar()4893 void DateFormatTest::TestChangeCalendar() {
4894     UErrorCode status = U_ZERO_ERROR;
4895     Locale en("en");
4896     Locale en_heb("en@calendar=hebrew");
4897     LocalPointer<DateFormat> fmt(
4898             DateFormat::createInstanceForSkeleton("yMMMd", en, status));
4899     if (!assertSuccess("", status)) {
4900         return;
4901     }
4902     fmt->adoptCalendar(Calendar::createInstance(en_heb, status));
4903     if (!assertSuccess("", status)) {
4904         return;
4905     }
4906     UnicodeString result;
4907     FieldPosition pos(FieldPosition::DONT_CARE);
4908     fmt->format(date(98, 5-1, 25), result, pos);
4909     assertEquals("format yMMMd", "Iyar 29, 5758", result);
4910 }
4911 
TestPatternFromSkeleton()4912 void DateFormatTest::TestPatternFromSkeleton() {
4913     static const struct {
4914         const Locale& locale;
4915         const char* const skeleton;
4916         const char* const pattern;
4917     } TESTDATA[] = {
4918         // Ticket #11985
4919         {Locale::getEnglish(), "jjmm", "h:mm a"},
4920         {Locale::getEnglish(), "JJmm", "hh:mm"},
4921         {Locale::getGerman(), "jjmm", "HH:mm"},
4922         {Locale::getGerman(), "JJmm", "HH:mm"}
4923     };
4924 
4925     for (size_t i = 0; i < UPRV_LENGTHOF(TESTDATA); i++) {
4926         UErrorCode status = U_ZERO_ERROR;
4927         LocalPointer<DateFormat> fmt(
4928                 DateFormat::createInstanceForSkeleton(
4929                         TESTDATA[i].skeleton, TESTDATA[i].locale, status));
4930         if (!assertSuccess("createInstanceForSkeleton", status)) {
4931             return;
4932         }
4933         UnicodeString pattern;
4934         static_cast<const SimpleDateFormat*>(fmt.getAlias())->toPattern(pattern);
4935         assertEquals("Format pattern", TESTDATA[i].pattern, pattern);
4936     }
4937 }
4938 
TestAmPmMidnightNoon()4939 void DateFormatTest::TestAmPmMidnightNoon() {
4940     // Some times on 2015-11-13 (UTC+0).
4941     UDate k000000 = 1447372800000.0;
4942     UDate k000030 = 1447372830000.0;
4943     UDate k003000 = 1447374600000.0;
4944     UDate k060000 = 1447394400000.0;
4945     UDate k120000 = 1447416000000.0;
4946     UDate k180000 = 1447437600000.0;
4947 
4948     UErrorCode errorCode = U_ZERO_ERROR;
4949     SimpleDateFormat sdf(UnicodeString(), errorCode);
4950     if (U_FAILURE(errorCode)) {
4951         dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
4952         return;
4953     }
4954     const TimeZone *tz = TimeZone::getGMT();
4955     sdf.setTimeZone(*tz);
4956     UnicodeString out;
4957 
4958     // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
4959     // For ICU 57 output of "midnight" is temporarily suppressed.
4960 
4961     // Short.
4962     sdf.applyPattern(UnicodeString("hh:mm:ss bbb"));
4963 
4964     // assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4965     assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4966     assertEquals("hh:mm:ss bbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
4967     assertEquals("hh:mm:ss bbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
4968     assertEquals("hh:mm:ss bbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
4969     assertEquals("hh:mm:ss bbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
4970     assertEquals("hh:mm:ss bbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
4971 
4972     sdf.applyPattern(UnicodeString("hh:mm bbb"));
4973 
4974     // assertEquals("hh:mm bbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
4975     assertEquals("hh:mm bbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
4976     // assertEquals("hh:mm bbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
4977     assertEquals("hh:mm bbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
4978     assertEquals("hh:mm bbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
4979 
4980     sdf.applyPattern(UnicodeString("hh bbb"));
4981 
4982     // assertEquals("hh bbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
4983     assertEquals("hh bbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
4984     // assertEquals("hh bbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
4985     assertEquals("hh bbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
4986     // assertEquals("hh bbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
4987     assertEquals("hh bbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
4988 
4989     // Wide.
4990     sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
4991 
4992     // assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4993     assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4994     assertEquals("hh:mm:ss bbbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
4995     assertEquals("hh:mm:ss bbbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
4996     assertEquals("hh:mm:ss bbbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
4997     assertEquals("hh:mm:ss bbbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
4998     assertEquals("hh:mm:ss bbbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
4999 
5000     sdf.applyPattern(UnicodeString("hh:mm bbbb"));
5001 
5002     // assertEquals("hh:mm bbbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5003     assertEquals("hh:mm bbbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
5004     // assertEquals("hh:mm bbbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5005     assertEquals("hh:mm bbbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
5006     assertEquals("hh:mm bbbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
5007 
5008     sdf.applyPattern(UnicodeString("hh bbbb"));
5009 
5010     // assertEquals("hh bbbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5011     assertEquals("hh bbbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
5012     // assertEquals("hh bbbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5013     assertEquals("hh bbbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
5014     // assertEquals("hh bbbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5015     assertEquals("hh bbbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
5016 
5017     // Narrow.
5018     sdf.applyPattern(UnicodeString("hh:mm:ss bbbbb"));
5019 
5020     // assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5021     assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 a", sdf.format(k000000, out.remove()));
5022     assertEquals("hh:mm:ss bbbbb | 00:00:30", "12:00:30 a", sdf.format(k000030, out.remove()));
5023     assertEquals("hh:mm:ss bbbbb | 00:30:00", "12:30:00 a", sdf.format(k003000, out.remove()));
5024     assertEquals("hh:mm:ss bbbbb | 06:00:00", "06:00:00 a", sdf.format(k060000, out.remove()));
5025     assertEquals("hh:mm:ss bbbbb | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5026     assertEquals("hh:mm:ss bbbbb | 18:00:00", "06:00:00 p", sdf.format(k180000, out.remove()));
5027 
5028     sdf.applyPattern(UnicodeString("hh:mm bbbbb"));
5029 
5030     // assertEquals("hh:mm bbbbb | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5031     assertEquals("hh:mm bbbbb | 00:00:00", "12:00 a", sdf.format(k000000, out.remove()));
5032     // assertEquals("hh:mm bbbbb | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5033     assertEquals("hh:mm bbbbb | 00:00:30", "12:00 a", sdf.format(k000030, out.remove()));
5034     assertEquals("hh:mm bbbbb | 00:30:00", "12:30 a", sdf.format(k003000, out.remove()));
5035 
5036     sdf.applyPattern(UnicodeString("hh bbbbb"));
5037 
5038     // assertEquals("hh bbbbb | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5039     assertEquals("hh bbbbb | 00:00:00", "12 a", sdf.format(k000000, out.remove()));
5040     // assertEquals("hh bbbbb | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5041     assertEquals("hh bbbbb | 00:00:30", "12 a", sdf.format(k000030, out.remove()));
5042     // assertEquals("hh bbbbb | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5043     assertEquals("hh bbbbb | 00:30:00", "12 a", sdf.format(k003000, out.remove()));
5044 }
5045 
TestFlexibleDayPeriod()5046 void DateFormatTest::TestFlexibleDayPeriod() {
5047     // Some times on 2015-11-13 (UTC+0).
5048     UDate k000000 = 1447372800000.0;
5049     UDate k000030 = 1447372830000.0;
5050     UDate k003000 = 1447374600000.0;
5051     UDate k060000 = 1447394400000.0;
5052     UDate k120000 = 1447416000000.0;
5053     UDate k180000 = 1447437600000.0;
5054 
5055     UErrorCode errorCode = U_ZERO_ERROR;
5056     SimpleDateFormat sdf(UnicodeString(), errorCode);
5057     if (U_FAILURE(errorCode)) {
5058         dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5059         return;
5060     }
5061     const TimeZone *tz = TimeZone::getGMT();
5062     sdf.setTimeZone(*tz);
5063     UnicodeString out;
5064 
5065     // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5066     // For ICU 57 output of "midnight" is temporarily suppressed.
5067 
5068     // Short.
5069     sdf.applyPattern(UnicodeString("hh:mm:ss BBB"));
5070 
5071     // assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5072     assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5073     assertEquals("hh:mm:ss BBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5074     assertEquals("hh:mm:ss BBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5075     assertEquals("hh:mm:ss BBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5076     assertEquals("hh:mm:ss BBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5077     assertEquals("hh:mm:ss BBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5078 
5079     sdf.applyPattern(UnicodeString("hh:mm BBB"));
5080 
5081     // assertEquals("hh:mm BBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5082     assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5083     // assertEquals("hh:mm BBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5084     assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5085     assertEquals("hh:mm BBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5086 
5087     sdf.applyPattern(UnicodeString("hh BBB"));
5088 
5089     // assertEquals("hh BBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5090     assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5091     // assertEquals("hh BBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5092     assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5093     // assertEquals("hh BBB | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5094     assertEquals("hh BBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5095 
5096     // Wide.
5097     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5098 
5099     // assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5100     assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5101     assertEquals("hh:mm:ss BBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5102     assertEquals("hh:mm:ss BBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5103     assertEquals("hh:mm:ss BBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5104     assertEquals("hh:mm:ss BBBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5105     assertEquals("hh:mm:ss BBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5106 
5107     sdf.applyPattern(UnicodeString("hh:mm BBBB"));
5108 
5109     // assertEquals("hh:mm BBBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5110     assertEquals("hh:mm BBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5111     // assertEquals("hh:mm BBBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5112     assertEquals("hh:mm BBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5113     assertEquals("hh:mm BBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5114 
5115     sdf.applyPattern(UnicodeString("hh BBBB"));
5116 
5117     // assertEquals("hh BBBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5118     assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5119     // assertEquals("hh BBBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5120     assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5121     // assertEquals("hh BBBB | 00:80:00", "12 midnight", sdf.format(k003000, out.remove()));
5122     assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5123 
5124     // Narrow.
5125     sdf.applyPattern(UnicodeString("hh:mm:ss BBBBB"));
5126 
5127     // assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5128     assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5129     assertEquals("hh:mm:ss BBBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5130     assertEquals("hh:mm:ss BBBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5131     assertEquals("hh:mm:ss BBBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5132     assertEquals("hh:mm:ss BBBBB | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5133     assertEquals("hh:mm:ss BBBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5134 
5135     sdf.applyPattern(UnicodeString("hh:mm BBBBB"));
5136 
5137     // assertEquals("hh:mm BBBBB | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5138     assertEquals("hh:mm BBBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5139     // assertEquals("hh:mm BBBBB | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5140     assertEquals("hh:mm BBBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5141     assertEquals("hh:mm BBBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5142 
5143     sdf.applyPattern(UnicodeString("hh BBBBB"));
5144 
5145     // assertEquals("hh BBBBB | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5146     assertEquals("hh BBBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5147     // assertEquals("hh BBBBB | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5148     assertEquals("hh BBBBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5149     // assertEquals("hh BBBBB | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5150     assertEquals("hh BBBBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5151 }
5152 
TestDayPeriodWithLocales()5153 void DateFormatTest::TestDayPeriodWithLocales() {
5154     // Some times on 2015-11-13 (UTC+0).
5155     UDate k000000 = 1447372800000.0;
5156     UDate k010000 = 1447376400000.0;
5157     UDate k120000 = 1447416000000.0;
5158     UDate k220000 = 1447452000000.0;
5159 
5160     UErrorCode errorCode = U_ZERO_ERROR;
5161     const TimeZone *tz = TimeZone::getGMT();
5162     UnicodeString out;
5163 
5164     // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5165     // For ICU 57 output of "midnight" and its localized equivalentns is temporarily suppressed.
5166 
5167     // Locale de has a word for midnight, but not noon.
5168     SimpleDateFormat sdf(UnicodeString(), Locale::getGermany(), errorCode);
5169     if (U_FAILURE(errorCode)) {
5170         dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5171         return;
5172     }
5173     sdf.setTimeZone(*tz);
5174 
5175     sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
5176 
5177     // assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 Mitternacht",
5178     //     sdf.format(k000000, out.remove()));
5179     assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 vorm.",
5180         sdf.format(k000000, out.remove()));
5181     assertEquals("hh:mm:ss bbbb | 12:00:00 | de", "12:00:00 nachm.",
5182         sdf.format(k120000, out.remove()));
5183 
5184     // Locale ee has a rule that wraps around midnight (21h - 4h).
5185     sdf = SimpleDateFormat(UnicodeString(), Locale("ee"), errorCode);
5186     sdf.setTimeZone(*tz);
5187 
5188     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5189 
5190     assertEquals("hh:mm:ss BBBB | 22:00:00 | ee", UnicodeString("10:00:00 z\\u00E3").unescape(),
5191         sdf.format(k220000, out.remove()));
5192     assertEquals("hh:mm:ss BBBB | 00:00:00 | ee", UnicodeString("12:00:00 z\\u00E3").unescape(),
5193         sdf.format(k000000, out.remove()));
5194     assertEquals("hh:mm:ss BBBB | 01:00:00 | ee", UnicodeString("01:00:00 z\\u00E3").unescape(),
5195         sdf.format(k010000, out.remove()));
5196 
5197     // Locale root has rules for AM/PM only.
5198     sdf = SimpleDateFormat(UnicodeString(), Locale("root"), errorCode);
5199     sdf.setTimeZone(*tz);
5200 
5201     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5202 
5203     assertEquals("hh:mm:ss BBBB | 00:00:00 | root", "12:00:00 AM",
5204         sdf.format(k000000, out.remove()));
5205     assertEquals("hh:mm:ss BBBB | 12:00:00 | root", "12:00:00 PM",
5206         sdf.format(k120000, out.remove()));
5207 
5208     // Empty string should behave exactly as root.
5209     sdf = SimpleDateFormat(UnicodeString(), Locale(""), errorCode);
5210     sdf.setTimeZone(*tz);
5211 
5212     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5213 
5214     assertEquals("hh:mm:ss BBBB | 00:00:00 | \"\" (root)", "12:00:00 AM",
5215         sdf.format(k000000, out.remove()));
5216     assertEquals("hh:mm:ss BBBB | 12:00:00 | \"\" (root)", "12:00:00 PM",
5217         sdf.format(k120000, out.remove()));
5218 
5219     // Locale en_US should fall back to en.
5220     sdf = SimpleDateFormat(UnicodeString(), Locale("en_US"), errorCode);
5221     sdf.setTimeZone(*tz);
5222 
5223     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5224 
5225     // assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 midnight",
5226     //     sdf.format(k000000, out.remove()));
5227     assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 at night",
5228          sdf.format(k000000, out.remove()));
5229     assertEquals("hh:mm:ss BBBB | 01:00:00 | en_US", "01:00:00 at night",
5230         sdf.format(k010000, out.remove()));
5231     assertEquals("hh:mm:ss BBBB | 12:00:00 | en_US", "12:00:00 noon",
5232         sdf.format(k120000, out.remove()));
5233 
5234     // Locale es_CO should not fall back to es and should have a
5235     // different string for 1 in the morning.
5236     // (es_CO: "de la manana" (first n has a tilde) vs. es: "de la madrugada")
5237     sdf = SimpleDateFormat(UnicodeString(), Locale("es_CO"), errorCode);
5238     sdf.setTimeZone(*tz);
5239 
5240     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5241     assertEquals("hh:mm:ss BBBB | 01:00:00 | es_CO", UnicodeString("01:00:00 de la ma\\u00F1ana").unescape(),
5242         sdf.format(k010000, out.remove()));
5243 
5244     sdf = SimpleDateFormat(UnicodeString(), Locale("es"), errorCode);
5245     sdf.setTimeZone(*tz);
5246 
5247     sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5248     assertEquals("hh:mm:ss BBBB | 01:00:00 | es", "01:00:00 de la madrugada",
5249         sdf.format(k010000, out.remove()));
5250 }
5251 
TestMinuteSecondFieldsInOddPlaces()5252 void DateFormatTest::TestMinuteSecondFieldsInOddPlaces() {
5253     // Some times on 2015-11-13 (UTC+0).
5254     UDate k000000 = 1447372800000.0;
5255     UDate k000030 = 1447372830000.0;
5256     UDate k003000 = 1447374600000.0;
5257     UDate k060030 = 1447394430000.0;
5258     UDate k063000 = 1447396200000.0;
5259 
5260     UErrorCode errorCode = U_ZERO_ERROR;
5261     const TimeZone *tz = TimeZone::getGMT();
5262     UnicodeString out;
5263 
5264     // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5265     // For ICU 57 output of "midnight" is temporarily suppressed.
5266 
5267     // Seconds field is not present.
5268 
5269     // Apply pattern through constructor to make sure parsePattern() is called during initialization.
5270     SimpleDateFormat sdf(UnicodeString("hh:mm 'ss' bbbb"), errorCode);
5271     if (U_FAILURE(errorCode)) {
5272         dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5273         return;
5274     }
5275     sdf.setTimeZone(*tz);
5276 
5277     // assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss midnight",
5278     //     sdf.format(k000030, out.remove()));
5279     assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss AM",
5280         sdf.format(k000030, out.remove()));
5281     assertEquals("hh:mm 'ss' bbbb | 06:00:30", "06:00 ss AM",
5282         sdf.format(k060030, out.remove()));
5283 
5284     sdf.applyPattern(UnicodeString("hh:mm 'ss' BBBB"));
5285 
5286     // assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss midnight",
5287     //     sdf.format(k000030, out.remove()));
5288     assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss at night",
5289         sdf.format(k000030, out.remove()));
5290     assertEquals("hh:mm 'ss' BBBB | 06:00:30", "06:00 ss in the morning",
5291         sdf.format(k060030, out.remove()));
5292 
5293     // Minutes field is not present.
5294     sdf.applyPattern(UnicodeString("hh 'mm ss' bbbb"));
5295 
5296     // assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss midnight",
5297     //     sdf.format(k003000, out.remove()));
5298     assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss AM",
5299         sdf.format(k003000, out.remove()));
5300     assertEquals("hh 'mm ss' bbbb | 06:30:00", "06 mm ss AM",
5301         sdf.format(k063000, out.remove()));
5302 
5303     sdf.applyPattern(UnicodeString("hh 'mm ss' BBBB"));
5304 
5305     // assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss midnight",
5306     //     sdf.format(k003000, out.remove()));
5307     assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss at night",
5308         sdf.format(k003000, out.remove()));
5309     assertEquals("hh 'mm ss' BBBB | 06:30:00", "06 mm ss in the morning",
5310         sdf.format(k063000, out.remove()));
5311 
5312     // Minutes and seconds fields appear after day periods.
5313     sdf.applyPattern(UnicodeString("bbbb hh:mm:ss"));
5314 
5315     // assertEquals("bbbb hh:mm:ss | 00:00:00", "midnight 12:00:00",
5316     //     sdf.format(k000000, out.remove()));
5317     assertEquals("bbbb hh:mm:ss | 00:00:00", "AM 12:00:00",
5318         sdf.format(k000000, out.remove()));
5319     assertEquals("bbbb hh:mm:ss | 00:00:30", "AM 12:00:30",
5320         sdf.format(k000030, out.remove()));
5321     assertEquals("bbbb hh:mm:ss | 00:30:00", "AM 12:30:00",
5322         sdf.format(k003000, out.remove()));
5323 
5324     sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5325 
5326     // assertEquals("BBBB hh:mm:ss | 00:00:00", "midnight 12:00:00",
5327     //     sdf.format(k000000, out.remove()));
5328     assertEquals("BBBB hh:mm:ss | 00:00:00", "at night 12:00:00",
5329         sdf.format(k000000, out.remove()));
5330     assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5331         sdf.format(k000030, out.remove()));
5332     assertEquals("BBBB hh:mm:ss | 00:30:00", "at night 12:30:00",
5333         sdf.format(k003000, out.remove()));
5334 
5335     // Confirm applyPattern() reparses the pattern string.
5336     sdf.applyPattern(UnicodeString("BBBB hh"));
5337     // assertEquals("BBBB hh | 00:00:30", "midnight 12",
5338     //     sdf.format(k000030, out.remove()));
5339     assertEquals("BBBB hh | 00:00:30", "at night 12",
5340          sdf.format(k000030, out.remove()));
5341 
5342     sdf.applyPattern(UnicodeString("BBBB hh:mm:'ss'"));
5343     // assertEquals("BBBB hh:mm:'ss' | 00:00:30", "midnight 12:00:ss",
5344     //     sdf.format(k000030, out.remove()));
5345     assertEquals("BBBB hh | 00:00:30", "at night 12:00:ss",
5346         sdf.format(k000030, out.remove()));
5347 
5348     sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5349     assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5350         sdf.format(k000030, out.remove()));
5351 }
5352 
TestDayPeriodParsing()5353 void DateFormatTest::TestDayPeriodParsing() {
5354     // Some times on 2015-11-13 (UTC+0).
5355     UDate k000000 = 1447372800000.0;
5356     UDate k003700 = 1447375020000.0;
5357     UDate k010000 = 1447376400000.0;
5358     UDate k013000 = 1447378200000.0;
5359     UDate k030000 = 1447383600000.0;
5360     UDate k090000 = 1447405200000.0;
5361     UDate k120000 = 1447416000000.0;
5362     UDate k130000 = 1447419600000.0;
5363     UDate k133700 = 1447421820000.0;
5364     UDate k150000 = 1447426800000.0;
5365     UDate k190000 = 1447441200000.0;
5366     UDate k193000 = 1447443000000.0;
5367     UDate k200000 = 1447444800000.0;
5368     UDate k210000 = 1447448400000.0;
5369 
5370     UErrorCode errorCode = U_ZERO_ERROR;
5371     SimpleDateFormat sdf(UnicodeString(), errorCode);
5372     if (U_FAILURE(errorCode)) {
5373         dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5374         return;
5375     }
5376     const TimeZone *tz = TimeZone::getGMT();
5377     sdf.setTimeZone(*tz);
5378     UnicodeString out;
5379 
5380     // 'B' -- flexible day periods
5381     // A day period on its own parses to the center of that period.
5382     sdf.applyPattern(UnicodeString("yyyy-MM-dd B"));
5383     assertEquals("yyyy-MM-dd B | 2015-11-13 midnight",
5384         k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5385     assertEquals("yyyy-MM-dd B | 2015-11-13 noon",
5386         k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5387     assertEquals("yyyy-MM-dd B | 2015-11-13 in the afternoon",
5388         k150000, sdf.parse(UnicodeString("2015-11-13 in the afternoon"), errorCode));
5389     assertEquals("yyyy-MM-dd B | 2015-11-13 in the evening",
5390         k193000, sdf.parse(UnicodeString("2015-11-13 in the evening"), errorCode));
5391     assertEquals("yyyy-MM-dd B | 2015-11-13 at night",
5392         k013000, sdf.parse(UnicodeString("2015-11-13 at night"), errorCode));
5393 
5394     // If time and day period are consistent with each other then time is parsed accordingly.
5395     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5396     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 midnight",
5397         k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5398     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 noon",
5399         k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5400     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 at night",
5401         k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5402     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 in the afternoon",
5403         k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5404     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 in the morning",
5405         k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5406     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 at night",
5407         k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5408 
5409     // If the hour is 13 thru 23 then day period has no effect on time (since time is assumed
5410     // to be in 24-hour format).
5411     sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5412     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 midnight",
5413         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5414     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 noon",
5415         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5416     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5417         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5418     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the afternoon",
5419         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the afternoon"), errorCode));
5420     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the morning",
5421         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the morning"), errorCode));
5422     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5423         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5424 
5425     // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5426     // This unfortunately means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5427     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5428     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 midnight",
5429         k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5430     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 noon",
5431         k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5432 
5433     // But when parsed with 'H', 0 indicates a 24-hour time, therefore we disregard the day period.
5434     sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5435     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 midnight",
5436         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5437     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 noon",
5438         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5439     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5440         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5441     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the afternoon",
5442         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the afternoon"), errorCode));
5443     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the morning",
5444         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the morning"), errorCode));
5445     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5446         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5447 
5448     // Even when parsed with 'H', hours 1 thru 12 are considered 12-hour time and takes
5449     // day period into account in parsing.
5450     sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5451     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 midnight",
5452         k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5453     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 noon",
5454         k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5455     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 at night",
5456         k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5457     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 in the afternoon",
5458         k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5459     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 in the morning",
5460         k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5461     assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 at night",
5462         k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5463 
5464     // If a 12-hour time and the day period don't agree with each other, time is parsed as close
5465     // to the given day period as possible.
5466     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5467 
5468     // AFTERNOON1 is [12, 18), but "7 in the afternoon" parses to 19:00.
5469     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 07:00 in the afternoon",
5470         k190000, sdf.parse(UnicodeString("2015-11-13 07:00 in the afternoon"), errorCode));
5471     // NIGHT1 is [21, 6), but "8 at night" parses to 20:00.
5472     assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 08:00 at night",
5473         k200000, sdf.parse(UnicodeString("2015-11-13 08:00 at night"), errorCode));
5474 
5475     // 'b' -- fixed day periods (AM, PM, midnight, noon)
5476     // On their own, "midnight" parses to 00:00 and "noon" parses to 12:00.
5477     // AM and PM are handled by the 'a' parser (which doesn't handle this case well).
5478     sdf.applyPattern(UnicodeString("yyyy-MM-dd b"));
5479     assertEquals("yyyy-MM-dd b | 2015-11-13 midnight",
5480         k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5481     assertEquals("yyyy-MM-dd b | 2015-11-13 noon",
5482         k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5483 
5484     // For 12-hour times, AM and PM should be parsed as if with pattern character 'a'.
5485     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5486     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 AM",
5487         k010000, sdf.parse(UnicodeString("2015-11-13 01:00 AM"), errorCode));
5488     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 PM",
5489         k130000, sdf.parse(UnicodeString("2015-11-13 01:00 PM"), errorCode));
5490 
5491     // 12 midnight parses to 00:00, and 12 noon parses to 12:00.
5492     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 midnight",
5493         k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5494     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 noon",
5495         k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5496 
5497     // Hours 13-23 indicate 24-hour time so we disregard "midnight" or "noon".
5498     // Again, AM and PM are handled by the 'a' parser which doesn't handle this case well.
5499     sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5500     assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 midnight",
5501         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5502     assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 noon",
5503         k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5504 
5505     // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5506     // Again, this means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5507     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5508     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 midnight",
5509         k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5510     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 noon",
5511         k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5512 
5513     // With 'H' though 0 indicates a 24-hour time, therefore we disregard the day period.
5514     sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5515     assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 midnight",
5516         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5517     assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 noon",
5518         k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5519 
5520     // If "midnight" or "noon" is parsed with a 12-hour time other than 12:00, choose
5521     // the version that's closer to the period given.
5522     sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5523     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 midnight",
5524         k030000, sdf.parse(UnicodeString("2015-11-13 03:00 midnight"), errorCode));
5525     assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 noon",
5526         k150000, sdf.parse(UnicodeString("2015-11-13 03:00 noon"), errorCode));
5527 }
5528 
5529 #endif /* #if !UCONFIG_NO_FORMATTING */
5530 
5531 //eof
5532