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