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