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