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