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