1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 ********************************************************************/
8
9 #include "unicode/utypes.h"
10
11 #if !UCONFIG_NO_FORMATTING
12
13 #include "dtfmttst.h"
14 #include "unicode/localpointer.h"
15 #include "unicode/timezone.h"
16 #include "unicode/gregocal.h"
17 #include "unicode/smpdtfmt.h"
18 #include "unicode/datefmt.h"
19 #include "unicode/dtptngen.h"
20 #include "unicode/simpletz.h"
21 #include "unicode/strenum.h"
22 #include "unicode/dtfmtsym.h"
23 #include "cmemory.h"
24 #include "cstring.h"
25 #include "caltest.h" // for fieldName
26 #include <stdio.h> // for sprintf
27
28 #if U_PLATFORM_USES_ONLY_WIN32_API
29 #include "windttst.h"
30 #endif
31
32 #define ASSERT_OK(status) if(U_FAILURE(status)) {errcheckln(status, #status " = %s @ %s:%d", u_errorName(status), __FILE__, __LINE__); return; }
33
34 // *****************************************************************************
35 // class DateFormatTest
36 // *****************************************************************************
37
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)38 void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
39 {
40 if(exec) {
41 logln("TestSuite DateFormatTest: ");
42 }
43 TESTCASE_AUTO_BEGIN;
44 TESTCASE_AUTO(TestPatterns);
45 TESTCASE_AUTO(TestEquals);
46 TESTCASE_AUTO(TestTwoDigitYearDSTParse);
47 TESTCASE_AUTO(TestFieldPosition);
48 TESTCASE_AUTO(TestPartialParse994);
49 TESTCASE_AUTO(TestRunTogetherPattern985);
50 TESTCASE_AUTO(TestRunTogetherPattern917);
51 TESTCASE_AUTO(TestCzechMonths459);
52 TESTCASE_AUTO(TestLetterDPattern212);
53 TESTCASE_AUTO(TestDayOfYearPattern195);
54 TESTCASE_AUTO(TestQuotePattern161);
55 TESTCASE_AUTO(TestBadInput135);
56 TESTCASE_AUTO(TestBadInput135a);
57 TESTCASE_AUTO(TestTwoDigitYear);
58 TESTCASE_AUTO(TestDateFormatZone061);
59 TESTCASE_AUTO(TestDateFormatZone146);
60 TESTCASE_AUTO(TestLocaleDateFormat);
61 TESTCASE_AUTO(TestFormattingLocaleTimeSeparator);
62 TESTCASE_AUTO(TestWallyWedel);
63 TESTCASE_AUTO(TestDateFormatCalendar);
64 TESTCASE_AUTO(TestSpaceParsing);
65 TESTCASE_AUTO(TestExactCountFormat);
66 TESTCASE_AUTO(TestWhiteSpaceParsing);
67 TESTCASE_AUTO(TestInvalidPattern);
68 TESTCASE_AUTO(TestGeneral);
69 TESTCASE_AUTO(TestGreekMay);
70 TESTCASE_AUTO(TestGenericTime);
71 TESTCASE_AUTO(TestGenericTimeZoneOrder);
72 TESTCASE_AUTO(TestHost);
73 TESTCASE_AUTO(TestEras);
74 TESTCASE_AUTO(TestNarrowNames);
75 TESTCASE_AUTO(TestShortDays);
76 TESTCASE_AUTO(TestStandAloneDays);
77 TESTCASE_AUTO(TestStandAloneMonths);
78 TESTCASE_AUTO(TestQuarters);
79 TESTCASE_AUTO(TestZTimeZoneParsing);
80 TESTCASE_AUTO(TestRelative);
81 TESTCASE_AUTO(TestRelativeClone);
82 TESTCASE_AUTO(TestHostClone);
83 TESTCASE_AUTO(TestHebrewClone);
84 TESTCASE_AUTO(TestDateFormatSymbolsClone);
85 TESTCASE_AUTO(TestTimeZoneDisplayName);
86 TESTCASE_AUTO(TestRoundtripWithCalendar);
87 TESTCASE_AUTO(Test6338);
88 TESTCASE_AUTO(Test6726);
89 TESTCASE_AUTO(TestGMTParsing);
90 TESTCASE_AUTO(Test6880);
91 TESTCASE_AUTO(TestISOEra);
92 TESTCASE_AUTO(TestFormalChineseDate);
93 TESTCASE_AUTO(TestNumberAsStringParsing);
94 TESTCASE_AUTO(TestStandAloneGMTParse);
95 TESTCASE_AUTO(TestParsePosition);
96 TESTCASE_AUTO(TestMonthPatterns);
97 TESTCASE_AUTO(TestContext);
98 TESTCASE_AUTO(TestNonGregoFmtParse);
99 TESTCASE_AUTO(TestFormatsWithNumberSystems);
100 /*
101 TESTCASE_AUTO(TestRelativeError);
102 TESTCASE_AUTO(TestRelativeOther);
103 */
104 TESTCASE_AUTO(TestDotAndAtLeniency);
105 TESTCASE_AUTO(TestDateFormatLeniency);
106 TESTCASE_AUTO(TestParseMultiPatternMatch);
107
108 TESTCASE_AUTO(TestParseLeniencyAPIs);
109 TESTCASE_AUTO(TestNumberFormatOverride);
110 TESTCASE_AUTO(TestCreateInstanceForSkeleton);
111 TESTCASE_AUTO(TestCreateInstanceForSkeletonDefault);
112 TESTCASE_AUTO(TestCreateInstanceForSkeletonWithCalendar);
113 TESTCASE_AUTO(TestDFSCreateForLocaleNonGregorianLocale);
114 TESTCASE_AUTO(TestDFSCreateForLocaleWithCalendarInLocale);
115 TESTCASE_AUTO(TestChangeCalendar);
116
117 TESTCASE_AUTO(TestPatternFromSkeleton);
118
119 TESTCASE_AUTO(TestAmPmMidnightNoon);
120 TESTCASE_AUTO(TestFlexibleDayPeriod);
121 TESTCASE_AUTO(TestDayPeriodWithLocales);
122 TESTCASE_AUTO(TestMinuteSecondFieldsInOddPlaces);
123 TESTCASE_AUTO(TestDayPeriodParsing);
124 TESTCASE_AUTO(TestParseRegression13744);
125
126 TESTCASE_AUTO_END;
127 }
128
TestPatterns()129 void DateFormatTest::TestPatterns() {
130 static const struct {
131 const char *actualPattern;
132 const char *expectedPattern;
133 const char *localeID;
134 const char *expectedLocalPattern;
135 } EXPECTED[] = {
136 {UDAT_YEAR, "y","en","y"},
137
138 {UDAT_QUARTER, "QQQQ", "en", "QQQQ"},
139 {UDAT_ABBR_QUARTER, "QQQ", "en", "QQQ"},
140 {UDAT_YEAR_QUARTER, "yQQQQ", "en", "QQQQ y"},
141 {UDAT_YEAR_ABBR_QUARTER, "yQQQ", "en", "QQQ y"},
142
143 {UDAT_NUM_MONTH, "M", "en", "L"},
144 {UDAT_ABBR_MONTH, "MMM", "en", "LLL"},
145 {UDAT_MONTH, "MMMM", "en", "LLLL"},
146 {UDAT_YEAR_NUM_MONTH, "yM","en","M/y"},
147 {UDAT_YEAR_ABBR_MONTH, "yMMM","en","MMM y"},
148 {UDAT_YEAR_MONTH, "yMMMM","en","MMMM y"},
149
150 {UDAT_DAY, "d","en","d"},
151 {UDAT_YEAR_NUM_MONTH_DAY, "yMd", "en", "M/d/y"},
152 {UDAT_YEAR_ABBR_MONTH_DAY, "yMMMd", "en", "MMM d, y"},
153 {UDAT_YEAR_MONTH_DAY, "yMMMMd", "en", "MMMM d, y"},
154 {UDAT_YEAR_NUM_MONTH_WEEKDAY_DAY, "yMEd", "en", "EEE, M/d/y"},
155 {UDAT_YEAR_ABBR_MONTH_WEEKDAY_DAY, "yMMMEd", "en", "EEE, MMM d, y"},
156 {UDAT_YEAR_MONTH_WEEKDAY_DAY, "yMMMMEEEEd", "en", "EEEE, MMMM d, y"},
157
158 {UDAT_NUM_MONTH_DAY, "Md","en","M/d"},
159 {UDAT_ABBR_MONTH_DAY, "MMMd","en","MMM d"},
160 {UDAT_MONTH_DAY, "MMMMd","en","MMMM d"},
161 {UDAT_NUM_MONTH_WEEKDAY_DAY, "MEd","en","EEE, M/d"},
162 {UDAT_ABBR_MONTH_WEEKDAY_DAY, "MMMEd","en","EEE, MMM d"},
163 {UDAT_MONTH_WEEKDAY_DAY, "MMMMEEEEd","en","EEEE, MMMM d"},
164
165 {UDAT_HOUR, "j", "en", "h a"}, // (fixed expected result per ticket 6872<-6626)
166 {UDAT_HOUR24, "H", "en", "HH"}, // (fixed expected result per ticket 6872<-6626
167
168 {UDAT_MINUTE, "m", "en", "m"},
169 {UDAT_HOUR_MINUTE, "jm","en","h:mm a"}, // (fixed expected result per ticket 6872<-7180)
170 {UDAT_HOUR24_MINUTE, "Hm", "en", "HH:mm"}, // (fixed expected result per ticket 6872<-6626)
171
172 {UDAT_SECOND, "s", "en", "s"},
173 {UDAT_HOUR_MINUTE_SECOND, "jms","en","h:mm:ss a"}, // (fixed expected result per ticket 6872<-7180)
174 {UDAT_HOUR24_MINUTE_SECOND, "Hms","en","HH:mm:ss"}, // (fixed expected result per ticket 6872<-6626)
175 {UDAT_MINUTE_SECOND, "ms", "en", "mm:ss"}, // (fixed expected result per ticket 6872<-6626)
176
177 {UDAT_LOCATION_TZ, "VVVV", "en", "VVVV"},
178 {UDAT_GENERIC_TZ, "vvvv", "en", "vvvv"},
179 {UDAT_ABBR_GENERIC_TZ, "v", "en", "v"},
180 {UDAT_SPECIFIC_TZ, "zzzz", "en", "zzzz"},
181 {UDAT_ABBR_SPECIFIC_TZ, "z", "en", "z"},
182 {UDAT_ABBR_UTC_TZ, "ZZZZ", "en", "ZZZZ"},
183
184 {UDAT_YEAR_NUM_MONTH_DAY UDAT_ABBR_UTC_TZ, "yMdZZZZ", "en", "M/d/y, ZZZZ"},
185 {UDAT_MONTH_DAY UDAT_LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d, VVVV"}
186 };
187
188 IcuTestErrorCode errorCode(*this, "TestPatterns()");
189 for (int32_t i = 0; i < UPRV_LENGTHOF(EXPECTED); i++) {
190 // Verify that patterns have the correct values
191 UnicodeString actualPattern(EXPECTED[i].actualPattern, -1, US_INV);
192 UnicodeString expectedPattern(EXPECTED[i].expectedPattern, -1, US_INV);
193 Locale locale(EXPECTED[i].localeID);
194 if (actualPattern != expectedPattern) {
195 errln("FAILURE! Expected pattern: " + expectedPattern +
196 " but was: " + actualPattern);
197 }
198
199 // Verify that DataFormat instances produced contain the correct
200 // localized patterns
201 // TODO: use DateFormat::getInstanceForSkeleton(), ticket #9029
202 // Java test code:
203 // DateFormat date1 = DateFormat.getPatternInstance(actualPattern,
204 // locale);
205 // DateFormat date2 = DateFormat.getPatternInstance(Calendar.getInstance(locale),
206 // actualPattern, locale);
207 LocalPointer<DateTimePatternGenerator> generator(
208 DateTimePatternGenerator::createInstance(locale, errorCode));
209 if(errorCode.errDataIfFailureAndReset("DateTimePatternGenerator::createInstance() failed for locale ID \"%s\"", EXPECTED[i].localeID)) {
210 continue;
211 }
212 UnicodeString pattern = generator->getBestPattern(actualPattern, errorCode);
213 SimpleDateFormat date1(pattern, locale, errorCode);
214 SimpleDateFormat date2(pattern, locale, errorCode);
215 date2.adoptCalendar(Calendar::createInstance(locale, errorCode));
216 if(errorCode.errIfFailureAndReset("DateFormat::getInstanceForSkeleton() failed")) {
217 errln(" for actualPattern \"%s\" & locale ID \"%s\"",
218 EXPECTED[i].actualPattern, EXPECTED[i].localeID);
219 continue;
220 }
221
222 UnicodeString expectedLocalPattern(EXPECTED[i].expectedLocalPattern, -1, US_INV);
223 UnicodeString actualLocalPattern1;
224 UnicodeString actualLocalPattern2;
225 date1.toLocalizedPattern(actualLocalPattern1, errorCode);
226 date2.toLocalizedPattern(actualLocalPattern2, errorCode);
227 if (actualLocalPattern1 != expectedLocalPattern) {
228 errln("FAILURE! Expected local pattern: " + expectedLocalPattern
229 + " but was: " + actualLocalPattern1);
230 }
231 if (actualLocalPattern2 != expectedLocalPattern) {
232 errln("FAILURE! Expected local pattern: " + expectedLocalPattern
233 + " but was: " + actualLocalPattern2);
234 }
235 }
236 }
237
238 // Test written by Wally Wedel and emailed to me.
TestWallyWedel()239 void DateFormatTest::TestWallyWedel()
240 {
241 UErrorCode status = U_ZERO_ERROR;
242 /*
243 * Instantiate a TimeZone so we can get the ids.
244 */
245 TimeZone *tz = new SimpleTimeZone(7,"");
246 /*
247 * Computational variables.
248 */
249 int32_t offset, hours, minutes, seconds;
250 /*
251 * Instantiate a SimpleDateFormat set up to produce a full time
252 zone name.
253 */
254 SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)"zzzz", status);
255 /*
256 * A String array for the time zone ids.
257 */
258 int32_t ids_length;
259 StringEnumeration* ids = TimeZone::createEnumeration();
260 if (ids == NULL) {
261 dataerrln("Unable to create TimeZone enumeration.");
262 if (sdf != NULL) {
263 delete sdf;
264 }
265 return;
266 }
267 ids_length = ids->count(status);
268 /*
269 * How many ids do we have?
270 */
271 logln("Time Zone IDs size: %d", ids_length);
272 /*
273 * Column headings (sort of)
274 */
275 logln("Ordinal ID offset(h:m) name");
276 /*
277 * Loop through the tzs.
278 */
279 UDate today = Calendar::getNow();
280 Calendar *cal = Calendar::createInstance(status);
281 for (int32_t i = 0; i < ids_length; i++) {
282 // logln(i + " " + ids[i]);
283 const UnicodeString* id = ids->snext(status);
284 TimeZone *ttz = TimeZone::createTimeZone(*id);
285 // offset = ttz.getRawOffset();
286 cal->setTimeZone(*ttz);
287 cal->setTime(today, status);
288 offset = cal->get(UCAL_ZONE_OFFSET, status) + cal->get(UCAL_DST_OFFSET, status);
289 // logln(i + " " + ids[i] + " offset " + offset);
290 const char* sign = "+";
291 if (offset < 0) {
292 sign = "-";
293 offset = -offset;
294 }
295 hours = offset/3600000;
296 minutes = (offset%3600000)/60000;
297 seconds = (offset%60000)/1000;
298 UnicodeString dstOffset = (UnicodeString)"" + sign + (hours < 10 ? "0" : "") +
299 (int32_t)hours + ":" + (minutes < 10 ? "0" : "") + (int32_t)minutes;
300 if (seconds != 0) {
301 dstOffset = dstOffset + ":" + (seconds < 10 ? "0" : "") + seconds;
302 }
303 /*
304 * Instantiate a date so we can display the time zone name.
305 */
306 sdf->setTimeZone(*ttz);
307 /*
308 * Format the output.
309 */
310 UnicodeString fmtOffset;
311 FieldPosition pos(FieldPosition::DONT_CARE);
312 sdf->format(today,fmtOffset, pos);
313 // UnicodeString fmtOffset = tzS.toString();
314 UnicodeString *fmtDstOffset = 0;
315 if (fmtOffset.startsWith("GMT") && fmtOffset.length() != 3)
316 {
317 //fmtDstOffset = fmtOffset->substring(3);
318 fmtDstOffset = new UnicodeString();
319 fmtOffset.extract(3, fmtOffset.length(), *fmtDstOffset);
320 }
321 /*
322 * Show our result.
323 */
324 UBool ok = fmtDstOffset == 0 || *fmtDstOffset == dstOffset;
325 if (ok)
326 {
327 logln(UnicodeString() + i + " " + *id + " " + dstOffset +
328 " " + fmtOffset +
329 (fmtDstOffset != 0 ? " ok" : " ?"));
330 }
331 else
332 {
333 errln(UnicodeString() + i + " " + *id + " " + dstOffset +
334 " " + fmtOffset + " *** FAIL ***");
335 }
336 delete ttz;
337 delete fmtDstOffset;
338 }
339 delete cal;
340 // delete ids; // TODO: BAD API
341 delete ids;
342 delete sdf;
343 delete tz;
344 }
345
346 // -------------------------------------
347
348 /**
349 * Test operator==
350 */
351 void
TestEquals()352 DateFormatTest::TestEquals()
353 {
354 DateFormat* fmtA = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
355 DateFormat* fmtB = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
356 if ( fmtA == NULL || fmtB == NULL){
357 dataerrln("Error calling DateFormat::createDateTimeInstance");
358 delete fmtA;
359 delete fmtB;
360 return;
361 }
362
363 if (!(*fmtA == *fmtB)) errln((UnicodeString)"FAIL");
364 delete fmtA;
365 delete fmtB;
366
367 TimeZone* test = TimeZone::createTimeZone("PDT");
368 delete test;
369 }
370
371 // -------------------------------------
372
373 /**
374 * Test the parsing of 2-digit years.
375 */
376 void
TestTwoDigitYearDSTParse(void)377 DateFormatTest::TestTwoDigitYearDSTParse(void)
378 {
379 UErrorCode status = U_ZERO_ERROR;
380 SimpleDateFormat* fullFmt = new SimpleDateFormat((UnicodeString)"EEE MMM dd HH:mm:ss.SSS zzz yyyy G", status);
381 SimpleDateFormat *fmt = new SimpleDateFormat((UnicodeString)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status);
382 //DateFormat* fmt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, Locale::ENGLISH);
383 UnicodeString* s = new UnicodeString("03-Apr-04 2:20:47 o'clock AM PST", "");
384 TimeZone* defaultTZ = TimeZone::createDefault();
385 TimeZone* PST = TimeZone::createTimeZone("PST");
386 int32_t defaultOffset = defaultTZ->getRawOffset();
387 int32_t PSTOffset = PST->getRawOffset();
388 int32_t hour = 2 + (defaultOffset - PSTOffset) / (60*60*1000);
389 // hour is the expected hour of day, in units of seconds
390 hour = ((hour < 0) ? hour + 24 : hour) * 60*60;
391
392 UnicodeString str;
393
394 if(U_FAILURE(status)) {
395 dataerrln("Could not set up test. exitting - %s", u_errorName(status));
396 return;
397 }
398
399 UDate d = fmt->parse(*s, status);
400 logln(*s + " P> " + ((DateFormat*)fullFmt)->format(d, str));
401 int32_t y, m, day, hr, min, sec;
402 dateToFields(d, y, m, day, hr, min, sec);
403 hour += defaultTZ->inDaylightTime(d, status) ? 1 : 0;
404 hr = hr*60*60;
405 if (hr != hour)
406 errln((UnicodeString)"FAIL: Should parse to hour " + hour + " but got " + hr);
407
408 if (U_FAILURE(status))
409 errln((UnicodeString)"FAIL: " + (int32_t)status);
410
411 delete s;
412 delete fmt;
413 delete fullFmt;
414 delete PST;
415 delete defaultTZ;
416 }
417
418 // -------------------------------------
419
toHexString(int32_t i)420 UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
421
422 UnicodeString&
escape(UnicodeString & s)423 DateFormatTest::escape(UnicodeString& s)
424 {
425 UnicodeString buf;
426 for (int32_t i=0; i<s.length(); ++i)
427 {
428 UChar c = s[(int32_t)i];
429 if (c <= (UChar)0x7F) buf += c;
430 else {
431 buf += (UChar)0x5c; buf += (UChar)0x55;
432 buf += toHexString((c & 0xF000) >> 12);
433 buf += toHexString((c & 0x0F00) >> 8);
434 buf += toHexString((c & 0x00F0) >> 4);
435 buf += toHexString(c & 0x000F);
436 }
437 }
438 return (s = buf);
439 }
440
441 // -------------------------------------
442
443 /**
444 * This MUST be kept in sync with DateFormatSymbols.gPatternChars.
445 */
446 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
447 static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:";
448 #else
449 static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB";
450 #endif
451
452 /**
453 * A list of the names of all the fields in DateFormat.
454 * This MUST be kept in sync with DateFormat.
455 */
456 static const char* DATEFORMAT_FIELD_NAMES[] = {
457 "ERA_FIELD",
458 "YEAR_FIELD",
459 "MONTH_FIELD",
460 "DATE_FIELD",
461 "HOUR_OF_DAY1_FIELD",
462 "HOUR_OF_DAY0_FIELD",
463 "MINUTE_FIELD",
464 "SECOND_FIELD",
465 "MILLISECOND_FIELD",
466 "DAY_OF_WEEK_FIELD",
467 "DAY_OF_YEAR_FIELD",
468 "DAY_OF_WEEK_IN_MONTH_FIELD",
469 "WEEK_OF_YEAR_FIELD",
470 "WEEK_OF_MONTH_FIELD",
471 "AM_PM_FIELD",
472 "HOUR1_FIELD",
473 "HOUR0_FIELD",
474 "TIMEZONE_FIELD",
475 "YEAR_WOY_FIELD",
476 "DOW_LOCAL_FIELD",
477 "EXTENDED_YEAR_FIELD",
478 "JULIAN_DAY_FIELD",
479 "MILLISECONDS_IN_DAY_FIELD",
480 "TIMEZONE_RFC_FIELD",
481 "GENERIC_TIMEZONE_FIELD",
482 "STAND_ALONE_DAY_FIELD",
483 "STAND_ALONE_MONTH_FIELD",
484 "QUARTER_FIELD",
485 "STAND_ALONE_QUARTER_FIELD",
486 "TIMEZONE_SPECIAL_FIELD",
487 "YEAR_NAME_FIELD",
488 "TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD",
489 "TIMEZONE_ISO_FIELD",
490 "TIMEZONE_ISO_LOCAL_FIELD",
491 "RELATED_YEAR_FIELD",
492 "AM_PM_MIDNIGHT_NOON_FIELD",
493 "FLEXIBLE_DAY_PERIOD_FIELD",
494 "UDAT_TIME_SEPARATOR_FIELD",
495 };
496
497 static const int32_t DATEFORMAT_FIELD_NAMES_LENGTH =
498 UPRV_LENGTHOF(DATEFORMAT_FIELD_NAMES);
499
500 /**
501 * Verify that returned field position indices are correct.
502 */
TestFieldPosition()503 void DateFormatTest::TestFieldPosition() {
504 UErrorCode ec = U_ZERO_ERROR;
505 int32_t i, j, exp;
506 UnicodeString buf;
507
508 // Verify data
509 DateFormatSymbols rootSyms(Locale(""), ec);
510 if (U_FAILURE(ec)) {
511 dataerrln("Unable to create DateFormatSymbols - %s", u_errorName(ec));
512 return;
513 }
514
515 // local pattern chars data is not longer loaded
516 // from icu locale bundle
517 assertEquals("patternChars", PATTERN_CHARS, rootSyms.getLocalPatternChars(buf));
518 assertEquals("patternChars", PATTERN_CHARS, DateFormatSymbols::getPatternUChars());
519 assertTrue("DATEFORMAT_FIELD_NAMES", DATEFORMAT_FIELD_NAMES_LENGTH == UDAT_FIELD_COUNT);
520 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
521 assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS));
522 #else
523 assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS) + 1); // +1 for missing TIME_SEPARATOR pattern char
524 #endif
525
526 // Create test formatters
527 const int32_t COUNT = 4;
528 DateFormat* dateFormats[COUNT];
529 dateFormats[0] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getUS());
530 dateFormats[1] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getFrance());
531 // Make the pattern "G y M d..."
532 buf.remove().append(PATTERN_CHARS);
533 for (j=buf.length()-1; j>=0; --j) buf.insert(j, (UChar)32/*' '*/);
534 dateFormats[2] = new SimpleDateFormat(buf, Locale::getUS(), ec);
535 // Make the pattern "GGGG yyyy MMMM dddd..."
536 for (j=buf.length()-1; j>=0; j-=2) {
537 for (i=0; i<3; ++i) {
538 buf.insert(j, buf.charAt(j));
539 }
540 }
541 dateFormats[3] = new SimpleDateFormat(buf, Locale::getUS(), ec);
542 if(U_FAILURE(ec)){
543 errln(UnicodeString("Could not create SimpleDateFormat object for locale en_US. Error: " )+ UnicodeString(u_errorName(ec)));
544 return;
545 }
546 UDate aug13 = 871508052513.0;
547
548 // Expected output field values for above DateFormats on aug13
549 // Fields are given in order of DateFormat field number
550 const char* EXPECTED[] = {
551 "", "1997", "August", "13", "", "", "34", "12", "", "Wednesday",
552 "", "", "", "", "PM", "2", "", "Pacific Daylight Time", "", "",
553 "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
554 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
555 ":",
556 #else
557 "",
558 #endif
559
560 "", "1997", "ao\\u00FBt", "13", "", "14", "34", "12", "", "mercredi",
561 "", "", "", "", "", "", "", "heure d\\u2019\\u00E9t\\u00E9 du Pacifique", "", "",
562 "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
563 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
564 ":",
565 #else
566 "",
567 #endif
568
569 "AD", "1997", "8", "13", "14", "14", "34", "12", "5", "Wed",
570 "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4",
571 "1997", "2450674", "52452513", "-0700", "PT", "4", "8", "3", "3", "uslax",
572 "1997", "GMT-7", "-07", "-07", "1997", "PM", "in the afternoon",
573 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
574 ":",
575 #else
576 "",
577 #endif
578
579 "Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130", "Wednesday",
580 "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "Wednesday",
581 "1997", "2450674", "52452513", "GMT-07:00", "Pacific Time", "Wednesday", "August", "3rd quarter", "3rd quarter", "Los Angeles Time",
582 "1997", "GMT-07:00", "-0700", "-0700", "1997", "PM", "in the afternoon",
583 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
584 ":",
585 #else
586 "",
587 #endif
588 };
589
590 const int32_t EXPECTED_LENGTH = UPRV_LENGTHOF(EXPECTED);
591
592 assertTrue("data size", EXPECTED_LENGTH == COUNT * UDAT_FIELD_COUNT);
593
594 TimeZone* PT = TimeZone::createTimeZone("America/Los_Angeles");
595 for (j = 0, exp = 0; j < COUNT; ++j) {
596 // String str;
597 DateFormat* df = dateFormats[j];
598 df->setTimeZone(*PT);
599 SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
600 if (sdtfmt != NULL) {
601 logln(" Pattern = " + sdtfmt->toPattern(buf.remove()));
602 } else {
603 logln(" Pattern = ? (not a SimpleDateFormat)");
604 }
605 logln((UnicodeString)" Result = " + df->format(aug13, buf.remove()));
606
607 int32_t expBase = exp; // save for later
608 for (i = 0; i < UDAT_FIELD_COUNT; ++i, ++exp) {
609 FieldPosition pos(i);
610 buf.remove();
611 df->format(aug13, buf, pos);
612 UnicodeString field;
613 buf.extractBetween(pos.getBeginIndex(), pos.getEndIndex(), field);
614 assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
615 ctou(EXPECTED[exp]), field);
616 }
617
618 // test FieldPositionIterator API
619 logln("FieldPositionIterator");
620 {
621 UErrorCode status = U_ZERO_ERROR;
622 FieldPositionIterator posIter;
623 FieldPosition fp;
624
625 buf.remove();
626 df->format(aug13, buf, &posIter, status);
627 while (posIter.next(fp)) {
628 int32_t i = fp.getField();
629 UnicodeString field;
630 buf.extractBetween(fp.getBeginIndex(), fp.getEndIndex(), field);
631 assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
632 ctou(EXPECTED[expBase + i]), field);
633 }
634
635 }
636 }
637
638
639 // test null posIter
640 buf.remove();
641 UErrorCode status = U_ZERO_ERROR;
642 dateFormats[0]->format(aug13, buf, NULL, status);
643 // if we didn't crash, we succeeded.
644
645 for (i=0; i<COUNT; ++i) {
646 delete dateFormats[i];
647 }
648 delete PT;
649 }
650
651 // -------------------------------------
652
653 /**
654 * General parse/format tests. Add test cases as needed.
655 */
TestGeneral()656 void DateFormatTest::TestGeneral() {
657 const char* DATA[] = {
658 "yyyy MM dd HH:mm:ss.SSS",
659
660 // Milliseconds are left-justified, since they format as fractions of a second
661 "y/M/d H:mm:ss.S", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5", "2004 03 10 16:36:31.500",
662 "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.56", "2004 03 10 16:36:31.560",
663 "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567",
664 "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5670",
665 };
666 expect(DATA, UPRV_LENGTHOF(DATA), Locale("en", "", ""));
667 }
668
669 // -------------------------------------
670
671 /**
672 * Verify that strings which contain incomplete specifications are parsed
673 * correctly. In some instances, this means not being parsed at all, and
674 * returning an appropriate error.
675 */
676 void
TestPartialParse994()677 DateFormatTest::TestPartialParse994()
678 {
679 UErrorCode status = U_ZERO_ERROR;
680 SimpleDateFormat* f = new SimpleDateFormat(status);
681 if (U_FAILURE(status)) {
682 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
683 delete f;
684 return;
685 }
686 UDate null = 0;
687 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", date(97, 1 - 1, 17, 10, 11, 42));
688 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null);
689 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null);
690 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null);
691 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null);
692 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
693 delete f;
694 }
695
696 // -------------------------------------
697
698 void
tryPat994(SimpleDateFormat * format,const char * pat,const char * str,UDate expected)699 DateFormatTest::tryPat994(SimpleDateFormat* format, const char* pat, const char* str, UDate expected)
700 {
701 UErrorCode status = U_ZERO_ERROR;
702 UDate null = 0;
703 logln(UnicodeString("Pattern \"") + pat + "\" String \"" + str + "\"");
704 //try {
705 format->applyPattern(pat);
706 UDate date = format->parse(str, status);
707 if (U_FAILURE(status) || date == null)
708 {
709 logln((UnicodeString)"ParseException: " + (int32_t)status);
710 if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
711 }
712 else
713 {
714 UnicodeString f;
715 ((DateFormat*)format)->format(date, f);
716 logln(UnicodeString(" parse(") + str + ") -> " + dateToString(date));
717 logln((UnicodeString)" format -> " + f);
718 if (expected == null ||
719 !(date == expected)) errln((UnicodeString)"FAIL: Expected null");//" + expected);
720 if (!(f == str)) errln(UnicodeString("FAIL: Expected ") + str);
721 }
722 //}
723 //catch(ParseException e) {
724 // logln((UnicodeString)"ParseException: " + e.getMessage());
725 // if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
726 //}
727 //catch(Exception e) {
728 // errln((UnicodeString)"*** Exception:");
729 // e.printStackTrace();
730 //}
731 }
732
733 // -------------------------------------
734
735 /**
736 * Verify the behavior of patterns in which digits for different fields run together
737 * without intervening separators.
738 */
739 void
TestRunTogetherPattern985()740 DateFormatTest::TestRunTogetherPattern985()
741 {
742 UErrorCode status = U_ZERO_ERROR;
743 UnicodeString format("yyyyMMddHHmmssSSS");
744 UnicodeString now, then;
745 //UBool flag;
746 SimpleDateFormat *formatter = new SimpleDateFormat(format, status);
747 if (U_FAILURE(status)) {
748 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
749 delete formatter;
750 return;
751 }
752 UDate date1 = Calendar::getNow();
753 ((DateFormat*)formatter)->format(date1, now);
754 logln(now);
755 ParsePosition pos(0);
756 UDate date2 = formatter->parse(now, pos);
757 if (date2 == 0) then = UnicodeString("Parse stopped at ") + pos.getIndex();
758 else ((DateFormat*)formatter)->format(date2, then);
759 logln(then);
760 if (!(date2 == date1)) errln((UnicodeString)"FAIL");
761 delete formatter;
762 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
763 }
764
765 // -------------------------------------
766
767 /**
768 * Verify the behavior of patterns in which digits for different fields run together
769 * without intervening separators.
770 */
771 void
TestRunTogetherPattern917()772 DateFormatTest::TestRunTogetherPattern917()
773 {
774 UErrorCode status = U_ZERO_ERROR;
775 SimpleDateFormat* fmt;
776 UnicodeString myDate;
777 fmt = new SimpleDateFormat((UnicodeString)"yyyy/MM/dd", status);
778 if (U_FAILURE(status)) {
779 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
780 delete fmt;
781 return;
782 }
783 myDate = "1997/02/03";
784 testIt917(fmt, myDate, date(97, 2 - 1, 3));
785 delete fmt;
786 fmt = new SimpleDateFormat((UnicodeString)"yyyyMMdd", status);
787 myDate = "19970304";
788 testIt917(fmt, myDate, date(97, 3 - 1, 4));
789 delete fmt;
790 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
791 }
792
793 // -------------------------------------
794
795 void
testIt917(SimpleDateFormat * fmt,UnicodeString & str,UDate expected)796 DateFormatTest::testIt917(SimpleDateFormat* fmt, UnicodeString& str, UDate expected)
797 {
798 UErrorCode status = U_ZERO_ERROR;
799 UnicodeString pattern;
800 logln((UnicodeString)"pattern=" + fmt->toPattern(pattern) + " string=" + str);
801 Formattable o;
802 //try {
803 ((Format*)fmt)->parseObject(str, o, status);
804 //}
805 if (U_FAILURE(status)) return;
806 //catch(ParseException e) {
807 // e.printStackTrace();
808 // return;
809 //}
810 logln((UnicodeString)"Parsed object: " + dateToString(o.getDate()));
811 if (!(o.getDate() == expected)) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
812 UnicodeString formatted; ((Format*)fmt)->format(o, formatted, status);
813 logln((UnicodeString)"Formatted string: " + formatted);
814 if (!(formatted == str)) errln((UnicodeString)"FAIL: Expected " + str);
815 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
816 }
817
818 // -------------------------------------
819
820 /**
821 * Verify the handling of Czech June and July, which have the unique attribute that
822 * one is a proper prefix substring of the other.
823 */
824 void
TestCzechMonths459()825 DateFormatTest::TestCzechMonths459()
826 {
827 UErrorCode status = U_ZERO_ERROR;
828 DateFormat* fmt = DateFormat::createDateInstance(DateFormat::FULL, Locale("cs", "", ""));
829 if (fmt == NULL){
830 dataerrln("Error calling DateFormat::createDateInstance()");
831 return;
832 }
833
834 UnicodeString pattern;
835 logln((UnicodeString)"Pattern " + ((SimpleDateFormat*) fmt)->toPattern(pattern));
836 UDate june = date(97, UCAL_JUNE, 15);
837 UDate july = date(97, UCAL_JULY, 15);
838 UnicodeString juneStr; fmt->format(june, juneStr);
839 UnicodeString julyStr; fmt->format(july, julyStr);
840 //try {
841 logln((UnicodeString)"format(June 15 1997) = " + juneStr);
842 UDate d = fmt->parse(juneStr, status);
843 UnicodeString s; fmt->format(d, s);
844 int32_t month,yr,day,hr,min,sec; dateToFields(d,yr,month,day,hr,min,sec);
845 logln((UnicodeString)" -> parse -> " + s + " (month = " + month + ")");
846 if (month != UCAL_JUNE) errln((UnicodeString)"FAIL: Month should be June");
847 logln((UnicodeString)"format(July 15 1997) = " + julyStr);
848 d = fmt->parse(julyStr, status);
849 fmt->format(d, s);
850 dateToFields(d,yr,month,day,hr,min,sec);
851 logln((UnicodeString)" -> parse -> " + s + " (month = " + month + ")");
852 if (month != UCAL_JULY) errln((UnicodeString)"FAIL: Month should be July");
853 //}
854 //catch(ParseException e) {
855 if (U_FAILURE(status))
856 errln((UnicodeString)"Exception: " + (int32_t)status);
857 //}
858 delete fmt;
859 }
860
861 // -------------------------------------
862
863 /**
864 * Test the handling of 'D' in patterns.
865 */
866 void
TestLetterDPattern212()867 DateFormatTest::TestLetterDPattern212()
868 {
869 UErrorCode status = U_ZERO_ERROR;
870 UnicodeString dateString("1995-040.05:01:29");
871 UnicodeString bigD("yyyy-DDD.hh:mm:ss");
872 UnicodeString littleD("yyyy-ddd.hh:mm:ss");
873 UDate expLittleD = date(95, 0, 1, 5, 1, 29);
874 UDate expBigD = expLittleD + 39 * 24 * 3600000.0;
875 expLittleD = expBigD; // Expect the same, with default lenient parsing
876 logln((UnicodeString)"dateString= " + dateString);
877 SimpleDateFormat *formatter = new SimpleDateFormat(bigD, status);
878 if (U_FAILURE(status)) {
879 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
880 delete formatter;
881 return;
882 }
883 ParsePosition pos(0);
884 UDate myDate = formatter->parse(dateString, pos);
885 logln((UnicodeString)"Using " + bigD + " -> " + myDate);
886 if (myDate != expBigD) errln((UnicodeString)"FAIL: bigD - Expected " + dateToString(expBigD));
887 delete formatter;
888 formatter = new SimpleDateFormat(littleD, status);
889 ASSERT_OK(status);
890 pos = ParsePosition(0);
891 myDate = formatter->parse(dateString, pos);
892 logln((UnicodeString)"Using " + littleD + " -> " + dateToString(myDate));
893 if (myDate != expLittleD) errln((UnicodeString)"FAIL: littleD - Expected " + dateToString(expLittleD));
894 delete formatter;
895 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
896 }
897
898 // -------------------------------------
899
900 /**
901 * Test the day of year pattern.
902 */
903 void
TestDayOfYearPattern195()904 DateFormatTest::TestDayOfYearPattern195()
905 {
906 UErrorCode status = U_ZERO_ERROR;
907 UDate today = Calendar::getNow();
908 int32_t year,month,day,hour,min,sec; dateToFields(today,year,month,day,hour,min,sec);
909 UDate expected = date(year, month, day);
910 logln((UnicodeString)"Test Date: " + dateToString(today));
911 SimpleDateFormat* sdf = (SimpleDateFormat*)DateFormat::createDateInstance();
912 if (sdf == NULL){
913 dataerrln("Error calling DateFormat::createDateInstance()");
914 return;
915 }
916 tryPattern(*sdf, today, 0, expected);
917 tryPattern(*sdf, today, "G yyyy DDD", expected);
918 delete sdf;
919 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
920 }
921
922 // -------------------------------------
923
924 void
tryPattern(SimpleDateFormat & sdf,UDate d,const char * pattern,UDate expected)925 DateFormatTest::tryPattern(SimpleDateFormat& sdf, UDate d, const char* pattern, UDate expected)
926 {
927 UErrorCode status = U_ZERO_ERROR;
928 if (pattern != 0) sdf.applyPattern(pattern);
929 UnicodeString thePat;
930 logln((UnicodeString)"pattern: " + sdf.toPattern(thePat));
931 UnicodeString formatResult; (*(DateFormat*)&sdf).format(d, formatResult);
932 logln((UnicodeString)" format -> " + formatResult);
933 // try {
934 UDate d2 = sdf.parse(formatResult, status);
935 logln((UnicodeString)" parse(" + formatResult + ") -> " + dateToString(d2));
936 if (d2 != expected) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
937 UnicodeString format2; (*(DateFormat*)&sdf).format(d2, format2);
938 logln((UnicodeString)" format -> " + format2);
939 if (!(formatResult == format2)) errln((UnicodeString)"FAIL: Round trip drift");
940 //}
941 //catch(Exception e) {
942 if (U_FAILURE(status))
943 errln((UnicodeString)"Error: " + (int32_t)status);
944 //}
945 }
946
947 // -------------------------------------
948
949 /**
950 * Test the handling of single quotes in patterns.
951 */
952 void
TestQuotePattern161()953 DateFormatTest::TestQuotePattern161()
954 {
955 UErrorCode status = U_ZERO_ERROR;
956 SimpleDateFormat* formatter = new SimpleDateFormat((UnicodeString)"MM/dd/yyyy 'at' hh:mm:ss a zzz", status);
957 if (U_FAILURE(status)) {
958 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
959 delete formatter;
960 return;
961 }
962 UDate currentTime_1 = date(97, UCAL_AUGUST, 13, 10, 42, 28);
963 UnicodeString dateString; ((DateFormat*)formatter)->format(currentTime_1, dateString);
964 UnicodeString exp("08/13/1997 at 10:42:28 AM ");
965 logln((UnicodeString)"format(" + dateToString(currentTime_1) + ") = " + dateString);
966 if (0 != dateString.compareBetween(0, exp.length(), exp, 0, exp.length())) errln((UnicodeString)"FAIL: Expected " + exp);
967 delete formatter;
968 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
969 }
970
971 // -------------------------------------
972
973 /**
974 * Verify the correct behavior when handling invalid input strings.
975 */
976 void
TestBadInput135()977 DateFormatTest::TestBadInput135()
978 {
979 UErrorCode status = U_ZERO_ERROR;
980 DateFormat::EStyle looks[] = {
981 DateFormat::SHORT, DateFormat::MEDIUM, DateFormat::LONG, DateFormat::FULL
982 };
983 int32_t looks_length = UPRV_LENGTHOF(looks);
984 const char* strings[] = {
985 "Mar 15", "Mar 15 1997", "asdf", "3/1/97 1:23:", "3/1/00 1:23:45 AM"
986 };
987 int32_t strings_length = UPRV_LENGTHOF(strings);
988 DateFormat *full = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::LONG);
989 if(full==NULL) {
990 dataerrln("could not create date time instance");
991 return;
992 }
993 UnicodeString expected("March 1, 2000 at 1:23:45 AM ");
994 for (int32_t i = 0; i < strings_length;++i) {
995 const char* text = strings[i];
996 for (int32_t j = 0; j < looks_length;++j) {
997 DateFormat::EStyle dateLook = looks[j];
998 for (int32_t k = 0; k < looks_length;++k) {
999 DateFormat::EStyle timeLook = looks[k];
1000 DateFormat *df = DateFormat::createDateTimeInstance(dateLook, timeLook);
1001 if (df == NULL){
1002 dataerrln("Error calling DateFormat::createDateTimeInstance()");
1003 continue;
1004 }
1005 UnicodeString prefix = UnicodeString(text) + ", " + dateLook + "/" + timeLook + ": ";
1006 //try {
1007 UDate when = df->parse(text, status);
1008 if (when == 0 && U_SUCCESS(status)) {
1009 errln(prefix + "SHOULD NOT HAPPEN: parse returned 0.");
1010 continue;
1011 }
1012 if (U_SUCCESS(status))
1013 {
1014 UnicodeString format;
1015 UnicodeString pattern;
1016 SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
1017 if (sdtfmt != NULL) {
1018 sdtfmt->toPattern(pattern);
1019 }
1020 full->format(when, format);
1021 logln(prefix + "OK: " + format);
1022 if (0!=format.compareBetween(0, expected.length(), expected, 0, expected.length()))
1023 errln((UnicodeString)"FAIL: Parse \"" + text + "\", pattern \"" + pattern + "\", expected " + expected + " got " + format);
1024 }
1025 //}
1026 //catch(ParseException e) {
1027 else
1028 status = U_ZERO_ERROR;
1029 //}
1030 //catch(StringIndexOutOfBoundsException e) {
1031 // errln(prefix + "SHOULD NOT HAPPEN: " + (int)status);
1032 //}
1033 delete df;
1034 }
1035 }
1036 }
1037 delete full;
1038 if (U_FAILURE(status))
1039 errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1040 }
1041
1042 static const char* const parseFormats[] = {
1043 "MMMM d, yyyy",
1044 "MMMM d yyyy",
1045 "M/d/yy",
1046 "d MMMM, yyyy",
1047 "d MMMM yyyy",
1048 "d MMMM",
1049 "MMMM d",
1050 "yyyy",
1051 "h:mm a MMMM d, yyyy"
1052 };
1053
1054 #if 0
1055 // strict inputStrings
1056 static const char* const inputStrings[] = {
1057 "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1058 "April 1, 1997", "April 1, 1997", 0, 0, 0, 0, 0, "April 1", 0, 0,
1059 "Jan 1, 1970", "January 1, 1970", 0, 0, 0, 0, 0, "January 1", 0, 0,
1060 "Jan 1 2037", 0, "January 1 2037", 0, 0, 0, 0, "January 1", 0, 0,
1061 "1/1/70", 0, 0, "1/1/70", 0, 0, 0, 0, "0001", 0,
1062 "5 May 1997", 0, 0, 0, 0, "5 May 1997", "5 May", 0, "0005", 0,
1063 "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1064 "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1065 "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1066 "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1067 "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1068 };
1069 #else
1070 // lenient inputStrings
1071 static const char* const inputStrings[] = {
1072 "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1073 "April 1, 1997", "April 1, 1997", "April 1 1997", "4/1/97", 0, 0, 0, "April 1", 0, 0,
1074 "Jan 1, 1970", "January 1, 1970", "January 1 1970", "1/1/70", 0, 0, 0, "January 1", 0, 0,
1075 "Jan 1 2037", "January 1, 2037", "January 1 2037", "1/1/37", 0, 0, 0, "January 1", 0, 0,
1076 "1/1/70", "January 1, 0070", "January 1 0070", "1/1/70", "1 January, 0070", "1 January 0070", "1 January", "January 1", "0001", 0,
1077 "5 May 1997", 0, 0, 0, "5 May, 1997", "5 May 1997", "5 May", 0, "0005", 0,
1078 "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1079 "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1080 "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1081 "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1082 "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1083 };
1084 #endif
1085
1086 // -------------------------------------
1087
1088 /**
1089 * Verify the correct behavior when parsing an array of inputs against an
1090 * array of patterns, with known results. The results are encoded after
1091 * the input strings in each row.
1092 */
1093 void
TestBadInput135a()1094 DateFormatTest::TestBadInput135a()
1095 {
1096 UErrorCode status = U_ZERO_ERROR;
1097 SimpleDateFormat* dateParse = new SimpleDateFormat(status);
1098 if(U_FAILURE(status)) {
1099 dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1100 delete dateParse;
1101 return;
1102 }
1103 const char* s;
1104 UDate date;
1105 const uint32_t PF_LENGTH = UPRV_LENGTHOF(parseFormats);
1106 const uint32_t INPUT_LENGTH = UPRV_LENGTHOF(inputStrings);
1107
1108 dateParse->applyPattern("d MMMM, yyyy");
1109 dateParse->adoptTimeZone(TimeZone::createDefault());
1110 s = "not parseable";
1111 UnicodeString thePat;
1112 logln(UnicodeString("Trying to parse \"") + s + "\" with " + dateParse->toPattern(thePat));
1113 //try {
1114 date = dateParse->parse(s, status);
1115 if (U_SUCCESS(status))
1116 errln((UnicodeString)"FAIL: Expected exception during parse");
1117 //}
1118 //catch(Exception ex) {
1119 else
1120 logln((UnicodeString)"Exception during parse: " + (int32_t)status);
1121 status = U_ZERO_ERROR;
1122 //}
1123 for (uint32_t i = 0; i < INPUT_LENGTH; i += (PF_LENGTH + 1)) {
1124 ParsePosition parsePosition(0);
1125 UnicodeString s( inputStrings[i]);
1126 for (uint32_t index = 0; index < PF_LENGTH;++index) {
1127 const char* expected = inputStrings[i + 1 + index];
1128 dateParse->applyPattern(parseFormats[index]);
1129 dateParse->adoptTimeZone(TimeZone::createDefault());
1130 //try {
1131 parsePosition.setIndex(0);
1132 date = dateParse->parse(s, parsePosition);
1133 if (parsePosition.getIndex() != 0) {
1134 UnicodeString s1, s2;
1135 s.extract(0, parsePosition.getIndex(), s1);
1136 s.extract(parsePosition.getIndex(), s.length(), s2);
1137 if (date == 0) {
1138 errln((UnicodeString)"ERROR: null result fmt=\"" +
1139 parseFormats[index] +
1140 "\" pos=" + parsePosition.getIndex() + " " +
1141 s1 + "|" + s2);
1142 }
1143 else {
1144 UnicodeString result;
1145 ((DateFormat*)dateParse)->format(date, result);
1146 logln((UnicodeString)"Parsed \"" + s + "\" using \"" + dateParse->toPattern(thePat) + "\" to: " + result);
1147 if (expected == 0)
1148 errln((UnicodeString)"FAIL: Expected parse failure, got " + result);
1149 else if (!(result == expected))
1150 errln(UnicodeString("FAIL: Parse \"") + s + UnicodeString("\", expected ") + expected + UnicodeString(", got ") + result);
1151 }
1152 }
1153 else if (expected != 0) {
1154 errln(UnicodeString("FAIL: Expected ") + expected + " from \"" +
1155 s + "\" with \"" + dateParse->toPattern(thePat) + "\"");
1156 }
1157 //}
1158 //catch(Exception ex) {
1159 if (U_FAILURE(status))
1160 errln((UnicodeString)"An exception was thrown during parse: " + (int32_t)status);
1161 //}
1162 }
1163 }
1164 delete dateParse;
1165 if (U_FAILURE(status))
1166 errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1167 }
1168
1169 // -------------------------------------
1170
1171 /**
1172 * Test the parsing of two-digit years.
1173 */
1174 void
TestTwoDigitYear()1175 DateFormatTest::TestTwoDigitYear()
1176 {
1177 UErrorCode ec = U_ZERO_ERROR;
1178 SimpleDateFormat fmt("dd/MM/yy", Locale::getUK(), ec);
1179 if (U_FAILURE(ec)) {
1180 dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1181 return;
1182 }
1183 parse2DigitYear(fmt, "5/6/30", date(130, UCAL_JUNE, 5));
1184 parse2DigitYear(fmt, "4/6/50", date(50, UCAL_JUNE, 4));
1185 }
1186
1187 // -------------------------------------
1188
1189 void
parse2DigitYear(DateFormat & fmt,const char * str,UDate expected)1190 DateFormatTest::parse2DigitYear(DateFormat& fmt, const char* str, UDate expected)
1191 {
1192 UErrorCode status = U_ZERO_ERROR;
1193 //try {
1194 UDate d = fmt.parse(str, status);
1195 UnicodeString thePat;
1196 logln(UnicodeString("Parsing \"") + str + "\" with " + ((SimpleDateFormat*)&fmt)->toPattern(thePat) +
1197 " => " + dateToString(d));
1198 if (d != expected) errln((UnicodeString)"FAIL: Expected " + expected);
1199 //}
1200 //catch(ParseException e) {
1201 if (U_FAILURE(status))
1202 errln((UnicodeString)"FAIL: Got exception");
1203 //}
1204 }
1205
1206 // -------------------------------------
1207
1208 /**
1209 * Test the formatting of time zones.
1210 */
1211 void
TestDateFormatZone061()1212 DateFormatTest::TestDateFormatZone061()
1213 {
1214 UErrorCode status = U_ZERO_ERROR;
1215 UDate date;
1216 DateFormat *formatter;
1217 date= 859248000000.0;
1218 logln((UnicodeString)"Date 1997/3/25 00:00 GMT: " + date);
1219 formatter = new SimpleDateFormat((UnicodeString)"dd-MMM-yyyyy HH:mm", Locale::getUK(), status);
1220 if(U_FAILURE(status)) {
1221 dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1222 delete formatter;
1223 return;
1224 }
1225 formatter->adoptTimeZone(TimeZone::createTimeZone("GMT"));
1226 UnicodeString temp; formatter->format(date, temp);
1227 logln((UnicodeString)"Formatted in GMT to: " + temp);
1228 //try {
1229 UDate tempDate = formatter->parse(temp, status);
1230 logln((UnicodeString)"Parsed to: " + dateToString(tempDate));
1231 if (tempDate != date) errln((UnicodeString)"FAIL: Expected " + dateToString(date));
1232 //}
1233 //catch(Throwable t) {
1234 if (U_FAILURE(status))
1235 errln((UnicodeString)"Date Formatter throws: " + (int32_t)status);
1236 //}
1237 delete formatter;
1238 }
1239
1240 // -------------------------------------
1241
1242 /**
1243 * Test the formatting of time zones.
1244 */
1245 void
TestDateFormatZone146()1246 DateFormatTest::TestDateFormatZone146()
1247 {
1248 TimeZone *saveDefault = TimeZone::createDefault();
1249
1250 //try {
1251 TimeZone *thedefault = TimeZone::createTimeZone("GMT");
1252 TimeZone::setDefault(*thedefault);
1253 // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
1254
1255 // check to be sure... its GMT all right
1256 TimeZone *testdefault = TimeZone::createDefault();
1257 UnicodeString testtimezone;
1258 testdefault->getID(testtimezone);
1259 if (testtimezone == "GMT")
1260 logln("Test timezone = " + testtimezone);
1261 else
1262 dataerrln("Test timezone should be GMT, not " + testtimezone);
1263
1264 UErrorCode status = U_ZERO_ERROR;
1265 // now try to use the default GMT time zone
1266 GregorianCalendar *greenwichcalendar =
1267 new GregorianCalendar(1997, 3, 4, 23, 0, status);
1268 if (U_FAILURE(status)) {
1269 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
1270 } else {
1271 //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
1272 //greenwichcalendar.set(1997, 3, 4, 23, 0);
1273 // try anything to set hour to 23:00 !!!
1274 greenwichcalendar->set(UCAL_HOUR_OF_DAY, 23);
1275 // get time
1276 UDate greenwichdate = greenwichcalendar->getTime(status);
1277 // format every way
1278 UnicodeString DATA [] = {
1279 UnicodeString("simple format: "), UnicodeString("04/04/97 23:00 GMT"),
1280 UnicodeString("MM/dd/yy HH:mm z"),
1281 UnicodeString("full format: "), UnicodeString("Friday, April 4, 1997 11:00:00 o'clock PM GMT"),
1282 UnicodeString("EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z"),
1283 UnicodeString("long format: "), UnicodeString("April 4, 1997 11:00:00 PM GMT"),
1284 UnicodeString("MMMM d, yyyy h:mm:ss a z"),
1285 UnicodeString("default format: "), UnicodeString("04-Apr-97 11:00:00 PM"),
1286 UnicodeString("dd-MMM-yy h:mm:ss a"),
1287 UnicodeString("short format: "), UnicodeString("4/4/97 11:00 PM"),
1288 UnicodeString("M/d/yy h:mm a")
1289 };
1290 int32_t DATA_length = UPRV_LENGTHOF(DATA);
1291
1292 for (int32_t i=0; i<DATA_length; i+=3) {
1293 DateFormat *fmt = new SimpleDateFormat(DATA[i+2], Locale::getEnglish(), status);
1294 if (U_FAILURE(status)) {
1295 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
1296 break;
1297 }
1298 fmt->setCalendar(*greenwichcalendar);
1299 UnicodeString result;
1300 result = fmt->format(greenwichdate, result);
1301 logln(DATA[i] + result);
1302 if (result != DATA[i+1])
1303 errln("FAIL: Expected " + DATA[i+1] + ", got " + result);
1304 delete fmt;
1305 }
1306 }
1307 //}
1308 //finally {
1309 TimeZone::adoptDefault(saveDefault);
1310 //}
1311 delete testdefault;
1312 delete greenwichcalendar;
1313 delete thedefault;
1314
1315
1316 }
1317
1318 // -------------------------------------
1319
1320 /**
1321 * Test the formatting of dates in different locales.
1322 */
1323 void
TestLocaleDateFormat()1324 DateFormatTest::TestLocaleDateFormat() // Bug 495
1325 {
1326 UDate testDate = date(97, UCAL_SEPTEMBER, 15);
1327 DateFormat *dfFrench = DateFormat::createDateTimeInstance(DateFormat::FULL,
1328 DateFormat::FULL, Locale::getFrench());
1329 DateFormat *dfUS = DateFormat::createDateTimeInstance(DateFormat::FULL,
1330 DateFormat::FULL, Locale::getUS());
1331 UnicodeString expectedFRENCH ( "lundi 15 septembre 1997 \\u00E0 00:00:00 heure d\\u2019\\u00E9t\\u00E9 du Pacifique", -1, US_INV );
1332 expectedFRENCH = expectedFRENCH.unescape();
1333 UnicodeString expectedUS ( "Monday, September 15, 1997 at 12:00:00 AM Pacific Daylight Time" );
1334 logln((UnicodeString)"Date set to : " + dateToString(testDate));
1335 UnicodeString out;
1336 if (dfUS == NULL || dfFrench == NULL){
1337 dataerrln("Error calling DateFormat::createDateTimeInstance)");
1338 delete dfUS;
1339 delete dfFrench;
1340 return;
1341 }
1342
1343 dfFrench->format(testDate, out);
1344 logln((UnicodeString)"Date Formated with French Locale " + out);
1345 if (!(out == expectedFRENCH))
1346 errln((UnicodeString)"FAIL: Expected " + expectedFRENCH);
1347 out.truncate(0);
1348 dfUS->format(testDate, out);
1349 logln((UnicodeString)"Date Formated with US Locale " + out);
1350 if (!(out == expectedUS))
1351 errln((UnicodeString)"FAIL: Expected " + expectedUS);
1352 delete dfUS;
1353 delete dfFrench;
1354 }
1355
1356 void
TestFormattingLocaleTimeSeparator()1357 DateFormatTest::TestFormattingLocaleTimeSeparator()
1358 {
1359 // This test not as useful as it once was, since timeSeparator
1360 // in the Arabic locale is changed back to ":" in CLDR 28.
1361 const UDate testDate = 874266720000.; // Sun Sep 14 21:52:00 CET 1997
1362 logln((UnicodeString)"Date set to : " + dateToString(testDate));
1363
1364 const LocalPointer<const TimeZone> tz(TimeZone::createTimeZone("CET"));
1365
1366 const LocalPointer<DateFormat> dfArab(DateFormat::createTimeInstance(
1367 DateFormat::SHORT, Locale("ar", "EG")));
1368
1369 const LocalPointer<DateFormat> dfLatn(DateFormat::createTimeInstance(
1370 DateFormat::SHORT, Locale("ar", "EG", NULL, "numbers=latn")));
1371
1372 if (dfLatn.isNull() || dfArab.isNull()) {
1373 dataerrln("Error calling DateFormat::createTimeInstance()");
1374 return;
1375 }
1376
1377 dfArab->setTimeZone(*tz);
1378 dfLatn->setTimeZone(*tz);
1379
1380 const UnicodeString expectedArab = UnicodeString(
1381 "\\u0669:\\u0665\\u0662 \\u0645", -1, US_INV).unescape();
1382
1383 const UnicodeString expectedLatn = UnicodeString(
1384 "9:52 \\u0645", -1, US_INV).unescape();
1385
1386 UnicodeString actualArab;
1387 UnicodeString actualLatn;
1388
1389 dfArab->format(testDate, actualArab);
1390 dfLatn->format(testDate, actualLatn);
1391
1392 assertEquals("Arab", expectedArab, actualArab);
1393 assertEquals("Latn", expectedLatn, actualLatn);
1394 }
1395
1396 /**
1397 * Test DateFormat(Calendar) API
1398 */
TestDateFormatCalendar()1399 void DateFormatTest::TestDateFormatCalendar() {
1400 DateFormat *date=0, *time=0, *full=0;
1401 Calendar *cal=0;
1402 UnicodeString str;
1403 ParsePosition pos;
1404 UDate when;
1405 UErrorCode ec = U_ZERO_ERROR;
1406
1407 /* Create a formatter for date fields. */
1408 date = DateFormat::createDateInstance(DateFormat::kShort, Locale::getUS());
1409 if (date == NULL) {
1410 dataerrln("FAIL: createDateInstance failed");
1411 goto FAIL;
1412 }
1413
1414 /* Create a formatter for time fields. */
1415 time = DateFormat::createTimeInstance(DateFormat::kShort, Locale::getUS());
1416 if (time == NULL) {
1417 errln("FAIL: createTimeInstance failed");
1418 goto FAIL;
1419 }
1420
1421 /* Create a full format for output */
1422 full = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull,
1423 Locale::getUS());
1424 if (full == NULL) {
1425 errln("FAIL: createInstance failed");
1426 goto FAIL;
1427 }
1428
1429 /* Create a calendar */
1430 cal = Calendar::createInstance(Locale::getUS(), ec);
1431 if (cal == NULL || U_FAILURE(ec)) {
1432 errln((UnicodeString)"FAIL: Calendar::createInstance failed with " +
1433 u_errorName(ec));
1434 goto FAIL;
1435 }
1436
1437 /* Parse the date */
1438 cal->clear();
1439 str = UnicodeString("4/5/2001", "");
1440 pos.setIndex(0);
1441 date->parse(str, *cal, pos);
1442 if (pos.getIndex() != str.length()) {
1443 errln((UnicodeString)"FAIL: DateFormat::parse(4/5/2001) failed at " +
1444 pos.getIndex());
1445 goto FAIL;
1446 }
1447
1448 /* Parse the time */
1449 str = UnicodeString("5:45 PM", "");
1450 pos.setIndex(0);
1451 time->parse(str, *cal, pos);
1452 if (pos.getIndex() != str.length()) {
1453 errln((UnicodeString)"FAIL: DateFormat::parse(17:45) failed at " +
1454 pos.getIndex());
1455 goto FAIL;
1456 }
1457
1458 /* Check result */
1459 when = cal->getTime(ec);
1460 if (U_FAILURE(ec)) {
1461 errln((UnicodeString)"FAIL: cal->getTime() failed with " + u_errorName(ec));
1462 goto FAIL;
1463 }
1464 str.truncate(0);
1465 full->format(when, str);
1466 // Thursday, April 5, 2001 5:45:00 PM PDT 986517900000
1467 if (when == 986517900000.0) {
1468 logln("Ok: Parsed result: " + str);
1469 } else {
1470 errln("FAIL: Parsed result: " + str + ", exp 4/5/2001 5:45 PM");
1471 }
1472
1473 FAIL:
1474 delete date;
1475 delete time;
1476 delete full;
1477 delete cal;
1478 }
1479
1480 /**
1481 * Test DateFormat's parsing of space characters. See jitterbug 1916.
1482 */
TestSpaceParsing()1483 void DateFormatTest::TestSpaceParsing() {
1484 const char* DATA[] = {
1485 "yyyy MM dd HH:mm:ss",
1486
1487 // pattern, input, expected parse or NULL if expect parse failure
1488 "MMMM d yy", " 04 05 06", "2006 04 05 00:00:00",
1489 NULL, "04 05 06", "2006 04 05 00:00:00",
1490
1491 "MM d yy", " 04 05 06", "2006 04 05 00:00:00",
1492 NULL, "04 05 06", "2006 04 05 00:00:00",
1493 NULL, "04/05/06", "2006 04 05 00:00:00",
1494 NULL, "04-05-06", "2006 04 05 00:00:00",
1495 NULL, "04.05.06", "2006 04 05 00:00:00",
1496 NULL, "04 / 05 / 06", "2006 04 05 00:00:00",
1497 NULL, "Apr / 05/ 06", "2006 04 05 00:00:00",
1498 NULL, "Apr-05-06", "2006 04 05 00:00:00",
1499 NULL, "Apr 05, 2006", "2006 04 05 00:00:00",
1500
1501 "MMMM d yy", " Apr 05 06", "2006 04 05 00:00:00",
1502 NULL, "Apr 05 06", "2006 04 05 00:00:00",
1503 NULL, "Apr05 06", "2006 04 05 00:00:00",
1504
1505 "hh:mm:ss a", "12:34:56 PM", "1970 01 01 12:34:56",
1506 NULL, "12:34:56PM", "1970 01 01 12:34:56",
1507 NULL, "12.34.56PM", "1970 01 01 12:34:56",
1508 NULL, "12 : 34 : 56 PM", "1970 01 01 12:34:56",
1509
1510 "MM d yy 'at' hh:mm:ss a", "04/05/06 12:34:56 PM", "2006 04 05 12:34:56",
1511
1512 "MMMM dd yyyy hh:mm a", "September 27, 1964 21:56 PM", "1964 09 28 09:56:00",
1513 NULL, "November 4, 2008 0:13 AM", "2008 11 04 00:13:00",
1514
1515 "HH'h'mm'min'ss's'", "12h34min56s", "1970 01 01 12:34:56",
1516 NULL, "12h34mi56s", "1970 01 01 12:34:56",
1517 NULL, "12h34m56s", "1970 01 01 12:34:56",
1518 NULL, "12:34:56", "1970 01 01 12:34:56"
1519 };
1520 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1521
1522 expectParse(DATA, DATA_len, Locale("en"));
1523 }
1524
1525 /**
1526 * Test handling of "HHmmss" pattern.
1527 */
TestExactCountFormat()1528 void DateFormatTest::TestExactCountFormat() {
1529 const char* DATA[] = {
1530 "yyyy MM dd HH:mm:ss",
1531
1532 // pattern, input, expected parse or NULL if expect parse failure
1533 "HHmmss", "123456", "1970 01 01 12:34:56",
1534 NULL, "12345", "1970 01 01 01:23:45",
1535 NULL, "1234", NULL,
1536 NULL, "00-05", NULL,
1537 NULL, "12-34", NULL,
1538 NULL, "00+05", NULL,
1539 "ahhmm", "PM730", "1970 01 01 19:30:00",
1540 };
1541 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1542
1543 expectParse(DATA, DATA_len, Locale("en"));
1544 }
1545
1546 /**
1547 * Test handling of white space.
1548 */
TestWhiteSpaceParsing()1549 void DateFormatTest::TestWhiteSpaceParsing() {
1550 const char* DATA[] = {
1551 "yyyy MM dd",
1552
1553 // pattern, input, expected parse or null if expect parse failure
1554
1555 // Pattern space run should parse input text space run
1556 "MM d yy", " 04 01 03", "2003 04 01",
1557 NULL, " 04 01 03 ", "2003 04 01",
1558 };
1559 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1560
1561 expectParse(DATA, DATA_len, Locale("en"));
1562 }
1563
1564
TestInvalidPattern()1565 void DateFormatTest::TestInvalidPattern() {
1566 UErrorCode ec = U_ZERO_ERROR;
1567 SimpleDateFormat f(UnicodeString("Yesterday"), ec);
1568 if (U_FAILURE(ec)) {
1569 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1570 return;
1571 }
1572 UnicodeString out;
1573 FieldPosition pos;
1574 f.format((UDate)0, out, pos);
1575 logln(out);
1576 // The bug is that the call to format() will crash. By not
1577 // crashing, the test passes.
1578 }
1579
TestGreekMay()1580 void DateFormatTest::TestGreekMay() {
1581 UErrorCode ec = U_ZERO_ERROR;
1582 UDate date = -9896080848000.0;
1583 SimpleDateFormat fmt("EEEE, dd MMMM yyyy h:mm:ss a", Locale("el", "", ""), ec);
1584 if (U_FAILURE(ec)) {
1585 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1586 return;
1587 }
1588 UnicodeString str;
1589 fmt.format(date, str);
1590 ParsePosition pos(0);
1591 UDate d2 = fmt.parse(str, pos);
1592 if (date != d2) {
1593 errln("FAIL: unable to parse strings where case-folding changes length");
1594 }
1595 }
1596
TestStandAloneMonths()1597 void DateFormatTest::TestStandAloneMonths()
1598 {
1599 const char *EN_DATA[] = {
1600 "yyyy MM dd HH:mm:ss",
1601
1602 "yyyy LLLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 March 10 16:36:31", "2004 03 10 16:36:31",
1603 "yyyy LLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31",
1604 "yyyy LLLL dd H:mm:ss", "F", "2004 03 10 16:36:31", "2004 March 10 16:36:31",
1605 "yyyy LLL dd H:mm:ss", "pf", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31",
1606
1607 "LLLL", "fp", "1970 01 01 0:00:00", "January", "1970 01 01 0:00:00",
1608 "LLLL", "fp", "1970 02 01 0:00:00", "February", "1970 02 01 0:00:00",
1609 "LLLL", "fp", "1970 03 01 0:00:00", "March", "1970 03 01 0:00:00",
1610 "LLLL", "fp", "1970 04 01 0:00:00", "April", "1970 04 01 0:00:00",
1611 "LLLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1612 "LLLL", "fp", "1970 06 01 0:00:00", "June", "1970 06 01 0:00:00",
1613 "LLLL", "fp", "1970 07 01 0:00:00", "July", "1970 07 01 0:00:00",
1614 "LLLL", "fp", "1970 08 01 0:00:00", "August", "1970 08 01 0:00:00",
1615 "LLLL", "fp", "1970 09 01 0:00:00", "September", "1970 09 01 0:00:00",
1616 "LLLL", "fp", "1970 10 01 0:00:00", "October", "1970 10 01 0:00:00",
1617 "LLLL", "fp", "1970 11 01 0:00:00", "November", "1970 11 01 0:00:00",
1618 "LLLL", "fp", "1970 12 01 0:00:00", "December", "1970 12 01 0:00:00",
1619
1620 "LLL", "fp", "1970 01 01 0:00:00", "Jan", "1970 01 01 0:00:00",
1621 "LLL", "fp", "1970 02 01 0:00:00", "Feb", "1970 02 01 0:00:00",
1622 "LLL", "fp", "1970 03 01 0:00:00", "Mar", "1970 03 01 0:00:00",
1623 "LLL", "fp", "1970 04 01 0:00:00", "Apr", "1970 04 01 0:00:00",
1624 "LLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1625 "LLL", "fp", "1970 06 01 0:00:00", "Jun", "1970 06 01 0:00:00",
1626 "LLL", "fp", "1970 07 01 0:00:00", "Jul", "1970 07 01 0:00:00",
1627 "LLL", "fp", "1970 08 01 0:00:00", "Aug", "1970 08 01 0:00:00",
1628 "LLL", "fp", "1970 09 01 0:00:00", "Sep", "1970 09 01 0:00:00",
1629 "LLL", "fp", "1970 10 01 0:00:00", "Oct", "1970 10 01 0:00:00",
1630 "LLL", "fp", "1970 11 01 0:00:00", "Nov", "1970 11 01 0:00:00",
1631 "LLL", "fp", "1970 12 01 0:00:00", "Dec", "1970 12 01 0:00:00",
1632 };
1633
1634 const char *CS_DATA[] = {
1635 "yyyy MM dd HH:mm:ss",
1636
1637 "yyyy LLLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 duben 10 16:36:31", "2004 04 10 16:36:31",
1638 "yyyy MMMM dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31",
1639 "yyyy LLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 dub 10 16:36:31", "2004 04 10 16:36:31",
1640 "yyyy LLLL dd H:mm:ss", "F", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1641 "yyyy MMMM dd H:mm:ss", "F", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1642 "yyyy LLLL dd H:mm:ss", "pf", "2004 duben 10 16:36:31", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1643 "yyyy MMMM dd H:mm:ss", "pf", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1644
1645 "LLLL", "fp", "1970 01 01 0:00:00", "leden", "1970 01 01 0:00:00",
1646 "LLLL", "fp", "1970 02 01 0:00:00", "\\u00FAnor", "1970 02 01 0:00:00",
1647 "LLLL", "fp", "1970 03 01 0:00:00", "b\\u0159ezen", "1970 03 01 0:00:00",
1648 "LLLL", "fp", "1970 04 01 0:00:00", "duben", "1970 04 01 0:00:00",
1649 "LLLL", "fp", "1970 05 01 0:00:00", "kv\\u011Bten", "1970 05 01 0:00:00",
1650 "LLLL", "fp", "1970 06 01 0:00:00", "\\u010Derven", "1970 06 01 0:00:00",
1651 "LLLL", "fp", "1970 07 01 0:00:00", "\\u010Dervenec", "1970 07 01 0:00:00",
1652 "LLLL", "fp", "1970 08 01 0:00:00", "srpen", "1970 08 01 0:00:00",
1653 "LLLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159\\u00ED", "1970 09 01 0:00:00",
1654 "LLLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDjen", "1970 10 01 0:00:00",
1655 "LLLL", "fp", "1970 11 01 0:00:00", "listopad", "1970 11 01 0:00:00",
1656 "LLLL", "fp", "1970 12 01 0:00:00", "prosinec", "1970 12 01 0:00:00",
1657
1658 "LLL", "fp", "1970 01 01 0:00:00", "led", "1970 01 01 0:00:00",
1659 "LLL", "fp", "1970 02 01 0:00:00", "\\u00FAno", "1970 02 01 0:00:00",
1660 "LLL", "fp", "1970 03 01 0:00:00", "b\\u0159e", "1970 03 01 0:00:00",
1661 "LLL", "fp", "1970 04 01 0:00:00", "dub", "1970 04 01 0:00:00",
1662 "LLL", "fp", "1970 05 01 0:00:00", "kv\\u011B", "1970 05 01 0:00:00",
1663 "LLL", "fp", "1970 06 01 0:00:00", "\\u010Dvn", "1970 06 01 0:00:00",
1664 "LLL", "fp", "1970 07 01 0:00:00", "\\u010Dvc", "1970 07 01 0:00:00",
1665 "LLL", "fp", "1970 08 01 0:00:00", "srp", "1970 08 01 0:00:00",
1666 "LLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159", "1970 09 01 0:00:00",
1667 "LLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDj", "1970 10 01 0:00:00",
1668 "LLL", "fp", "1970 11 01 0:00:00", "lis", "1970 11 01 0:00:00",
1669 "LLL", "fp", "1970 12 01 0:00:00", "pro", "1970 12 01 0:00:00",
1670 };
1671
1672 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1673 expect(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1674 }
1675
TestStandAloneDays()1676 void DateFormatTest::TestStandAloneDays()
1677 {
1678 const char *EN_DATA[] = {
1679 "yyyy MM dd HH:mm:ss",
1680
1681 "cccc", "fp", "1970 01 04 0:00:00", "Sunday", "1970 01 04 0:00:00",
1682 "cccc", "fp", "1970 01 05 0:00:00", "Monday", "1970 01 05 0:00:00",
1683 "cccc", "fp", "1970 01 06 0:00:00", "Tuesday", "1970 01 06 0:00:00",
1684 "cccc", "fp", "1970 01 07 0:00:00", "Wednesday", "1970 01 07 0:00:00",
1685 "cccc", "fp", "1970 01 01 0:00:00", "Thursday", "1970 01 01 0:00:00",
1686 "cccc", "fp", "1970 01 02 0:00:00", "Friday", "1970 01 02 0:00:00",
1687 "cccc", "fp", "1970 01 03 0:00:00", "Saturday", "1970 01 03 0:00:00",
1688
1689 "ccc", "fp", "1970 01 04 0:00:00", "Sun", "1970 01 04 0:00:00",
1690 "ccc", "fp", "1970 01 05 0:00:00", "Mon", "1970 01 05 0:00:00",
1691 "ccc", "fp", "1970 01 06 0:00:00", "Tue", "1970 01 06 0:00:00",
1692 "ccc", "fp", "1970 01 07 0:00:00", "Wed", "1970 01 07 0:00:00",
1693 "ccc", "fp", "1970 01 01 0:00:00", "Thu", "1970 01 01 0:00:00",
1694 "ccc", "fp", "1970 01 02 0:00:00", "Fri", "1970 01 02 0:00:00",
1695 "ccc", "fp", "1970 01 03 0:00:00", "Sat", "1970 01 03 0:00:00",
1696 };
1697
1698 const char *CS_DATA[] = {
1699 "yyyy MM dd HH:mm:ss",
1700
1701 "cccc", "fp", "1970 01 04 0:00:00", "ned\\u011Ble", "1970 01 04 0:00:00",
1702 "cccc", "fp", "1970 01 05 0:00:00", "pond\\u011Bl\\u00ED", "1970 01 05 0:00:00",
1703 "cccc", "fp", "1970 01 06 0:00:00", "\\u00FAter\\u00FD", "1970 01 06 0:00:00",
1704 "cccc", "fp", "1970 01 07 0:00:00", "st\\u0159eda", "1970 01 07 0:00:00",
1705 "cccc", "fp", "1970 01 01 0:00:00", "\\u010Dtvrtek", "1970 01 01 0:00:00",
1706 "cccc", "fp", "1970 01 02 0:00:00", "p\\u00E1tek", "1970 01 02 0:00:00",
1707 "cccc", "fp", "1970 01 03 0:00:00", "sobota", "1970 01 03 0:00:00",
1708
1709 "ccc", "fp", "1970 01 04 0:00:00", "ne", "1970 01 04 0:00:00",
1710 "ccc", "fp", "1970 01 05 0:00:00", "po", "1970 01 05 0:00:00",
1711 "ccc", "fp", "1970 01 06 0:00:00", "\\u00FAt", "1970 01 06 0:00:00",
1712 "ccc", "fp", "1970 01 07 0:00:00", "st", "1970 01 07 0:00:00",
1713 "ccc", "fp", "1970 01 01 0:00:00", "\\u010Dt", "1970 01 01 0:00:00",
1714 "ccc", "fp", "1970 01 02 0:00:00", "p\\u00E1", "1970 01 02 0:00:00",
1715 "ccc", "fp", "1970 01 03 0:00:00", "so", "1970 01 03 0:00:00",
1716 };
1717
1718 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1719 expect(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1720 }
1721
TestShortDays()1722 void DateFormatTest::TestShortDays()
1723 {
1724 const char *EN_DATA[] = {
1725 "yyyy MM dd HH:mm:ss",
1726
1727 "EEEEEE, MMM d y", "fp", "2013 01 13 0:00:00", "Su, Jan 13 2013", "2013 01 13 0:00:00",
1728 "EEEEEE, MMM d y", "fp", "2013 01 16 0:00:00", "We, Jan 16 2013", "2013 01 16 0:00:00",
1729 "EEEEEE d", "fp", "1970 01 17 0:00:00", "Sa 17", "1970 01 17 0:00:00",
1730 "cccccc d", "fp", "1970 01 17 0:00:00", "Sa 17", "1970 01 17 0:00:00",
1731 "cccccc", "fp", "1970 01 03 0:00:00", "Sa", "1970 01 03 0:00:00",
1732 };
1733 const char *SV_DATA[] = {
1734 "yyyy MM dd HH:mm:ss",
1735
1736 "EEEEEE d MMM y", "fp", "2013 01 13 0:00:00", "s\\u00F6 13 jan. 2013", "2013 01 13 0:00:00",
1737 "EEEEEE d MMM y", "fp", "2013 01 16 0:00:00", "on 16 jan. 2013", "2013 01 16 0:00:00",
1738 "EEEEEE d", "fp", "1970 01 17 0:00:00", "l\\u00F6 17", "1970 01 17 0:00:00",
1739 "cccccc d", "fp", "1970 01 17 0:00:00", "l\\u00F6 17", "1970 01 17 0:00:00",
1740 "cccccc", "fp", "1970 01 03 0:00:00", "l\\u00F6", "1970 01 03 0:00:00",
1741 };
1742 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1743 expect(SV_DATA, UPRV_LENGTHOF(SV_DATA), Locale("sv", "", ""));
1744 }
1745
TestNarrowNames()1746 void DateFormatTest::TestNarrowNames()
1747 {
1748 const char *EN_DATA[] = {
1749 "yyyy MM dd HH:mm:ss",
1750
1751 "yyyy MMMMM dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1752 "yyyy LLLLL dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1753
1754 "MMMMM", "1970 01 01 0:00:00", "J",
1755 "MMMMM", "1970 02 01 0:00:00", "F",
1756 "MMMMM", "1970 03 01 0:00:00", "M",
1757 "MMMMM", "1970 04 01 0:00:00", "A",
1758 "MMMMM", "1970 05 01 0:00:00", "M",
1759 "MMMMM", "1970 06 01 0:00:00", "J",
1760 "MMMMM", "1970 07 01 0:00:00", "J",
1761 "MMMMM", "1970 08 01 0:00:00", "A",
1762 "MMMMM", "1970 09 01 0:00:00", "S",
1763 "MMMMM", "1970 10 01 0:00:00", "O",
1764 "MMMMM", "1970 11 01 0:00:00", "N",
1765 "MMMMM", "1970 12 01 0:00:00", "D",
1766
1767 "LLLLL", "1970 01 01 0:00:00", "J",
1768 "LLLLL", "1970 02 01 0:00:00", "F",
1769 "LLLLL", "1970 03 01 0:00:00", "M",
1770 "LLLLL", "1970 04 01 0:00:00", "A",
1771 "LLLLL", "1970 05 01 0:00:00", "M",
1772 "LLLLL", "1970 06 01 0:00:00", "J",
1773 "LLLLL", "1970 07 01 0:00:00", "J",
1774 "LLLLL", "1970 08 01 0:00:00", "A",
1775 "LLLLL", "1970 09 01 0:00:00", "S",
1776 "LLLLL", "1970 10 01 0:00:00", "O",
1777 "LLLLL", "1970 11 01 0:00:00", "N",
1778 "LLLLL", "1970 12 01 0:00:00", "D",
1779
1780 "EEEEE", "1970 01 04 0:00:00", "S",
1781 "EEEEE", "1970 01 05 0:00:00", "M",
1782 "EEEEE", "1970 01 06 0:00:00", "T",
1783 "EEEEE", "1970 01 07 0:00:00", "W",
1784 "EEEEE", "1970 01 01 0:00:00", "T",
1785 "EEEEE", "1970 01 02 0:00:00", "F",
1786 "EEEEE", "1970 01 03 0:00:00", "S",
1787
1788 "ccccc", "1970 01 04 0:00:00", "S",
1789 "ccccc", "1970 01 05 0:00:00", "M",
1790 "ccccc", "1970 01 06 0:00:00", "T",
1791 "ccccc", "1970 01 07 0:00:00", "W",
1792 "ccccc", "1970 01 01 0:00:00", "T",
1793 "ccccc", "1970 01 02 0:00:00", "F",
1794 "ccccc", "1970 01 03 0:00:00", "S",
1795
1796 "h:mm a", "2015 01 01 10:00:00", "10:00 AM",
1797 "h:mm a", "2015 01 01 22:00:00", "10:00 PM",
1798 "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a",
1799 "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p",
1800 };
1801
1802 const char *CS_DATA[] = {
1803 "yyyy MM dd HH:mm:ss",
1804
1805 "yyyy LLLLL dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1806 "yyyy MMMMM dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1807
1808 "MMMMM", "1970 01 01 0:00:00", "1",
1809 "MMMMM", "1970 02 01 0:00:00", "2",
1810 "MMMMM", "1970 03 01 0:00:00", "3",
1811 "MMMMM", "1970 04 01 0:00:00", "4",
1812 "MMMMM", "1970 05 01 0:00:00", "5",
1813 "MMMMM", "1970 06 01 0:00:00", "6",
1814 "MMMMM", "1970 07 01 0:00:00", "7",
1815 "MMMMM", "1970 08 01 0:00:00", "8",
1816 "MMMMM", "1970 09 01 0:00:00", "9",
1817 "MMMMM", "1970 10 01 0:00:00", "10",
1818 "MMMMM", "1970 11 01 0:00:00", "11",
1819 "MMMMM", "1970 12 01 0:00:00", "12",
1820
1821 "LLLLL", "1970 01 01 0:00:00", "1",
1822 "LLLLL", "1970 02 01 0:00:00", "2",
1823 "LLLLL", "1970 03 01 0:00:00", "3",
1824 "LLLLL", "1970 04 01 0:00:00", "4",
1825 "LLLLL", "1970 05 01 0:00:00", "5",
1826 "LLLLL", "1970 06 01 0:00:00", "6",
1827 "LLLLL", "1970 07 01 0:00:00", "7",
1828 "LLLLL", "1970 08 01 0:00:00", "8",
1829 "LLLLL", "1970 09 01 0:00:00", "9",
1830 "LLLLL", "1970 10 01 0:00:00", "10",
1831 "LLLLL", "1970 11 01 0:00:00", "11",
1832 "LLLLL", "1970 12 01 0:00:00", "12",
1833
1834 "EEEEE", "1970 01 04 0:00:00", "N",
1835 "EEEEE", "1970 01 05 0:00:00", "P",
1836 "EEEEE", "1970 01 06 0:00:00", "\\u00DA",
1837 "EEEEE", "1970 01 07 0:00:00", "S",
1838 "EEEEE", "1970 01 01 0:00:00", "\\u010C",
1839 "EEEEE", "1970 01 02 0:00:00", "P",
1840 "EEEEE", "1970 01 03 0:00:00", "S",
1841
1842 "ccccc", "1970 01 04 0:00:00", "N",
1843 "ccccc", "1970 01 05 0:00:00", "P",
1844 "ccccc", "1970 01 06 0:00:00", "\\u00DA",
1845 "ccccc", "1970 01 07 0:00:00", "S",
1846 "ccccc", "1970 01 01 0:00:00", "\\u010C",
1847 "ccccc", "1970 01 02 0:00:00", "P",
1848 "ccccc", "1970 01 03 0:00:00", "S",
1849
1850 "h:mm a", "2015 01 01 10:00:00", "10:00 dop.",
1851 "h:mm a", "2015 01 01 22:00:00", "10:00 odp.",
1852 "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 dop.",
1853 "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 odp.",
1854 };
1855
1856 const char *CA_DATA[] = {
1857 "yyyy MM dd HH:mm:ss",
1858
1859 "h:mm a", "2015 01 01 10:00:00", "10:00 a. m.",
1860 "h:mm a", "2015 01 01 22:00:00", "10:00 p. m.",
1861 "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a. m.",
1862 "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p. m.",
1863 };
1864
1865 expectFormat(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1866 expectFormat(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1867 expectFormat(CA_DATA, UPRV_LENGTHOF(CA_DATA), Locale("ca", "", ""));
1868 }
1869
TestEras()1870 void DateFormatTest::TestEras()
1871 {
1872 const char *EN_DATA[] = {
1873 "yyyy MM dd",
1874
1875 "MMMM dd yyyy G", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1876 "MMMM dd yyyy GG", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1877 "MMMM dd yyyy GGG", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1878 "MMMM dd yyyy GGGG", "fp", "1951 07 17", "July 17 1951 Anno Domini", "1951 07 17",
1879
1880 "MMMM dd yyyy G", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1881 "MMMM dd yyyy GG", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1882 "MMMM dd yyyy GGG", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1883 "MMMM dd yyyy GGGG", "fp", "-438 07 17", "July 17 0439 Before Christ", "-438 07 17",
1884 };
1885
1886 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1887 }
1888
TestQuarters()1889 void DateFormatTest::TestQuarters()
1890 {
1891 const char *EN_DATA[] = {
1892 "yyyy MM dd",
1893
1894 "Q", "fp", "1970 01 01", "1", "1970 01 01",
1895 "QQ", "fp", "1970 04 01", "02", "1970 04 01",
1896 "QQQ", "fp", "1970 07 01", "Q3", "1970 07 01",
1897 "QQQQ", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1898
1899 "q", "fp", "1970 01 01", "1", "1970 01 01",
1900 "qq", "fp", "1970 04 01", "02", "1970 04 01",
1901 "qqq", "fp", "1970 07 01", "Q3", "1970 07 01",
1902 "qqqq", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1903
1904 "Qyy", "fp", "2015 04 01", "215", "2015 04 01",
1905 "QQyy", "fp", "2015 07 01", "0315", "2015 07 01",
1906 };
1907
1908 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1909 }
1910
1911 /**
1912 * Test parsing. Input is an array that starts with the following
1913 * header:
1914 *
1915 * [0] = pattern string to parse [i+2] with
1916 *
1917 * followed by test cases, each of which is 3 array elements:
1918 *
1919 * [i] = pattern, or NULL to reuse prior pattern
1920 * [i+1] = input string
1921 * [i+2] = expected parse result (parsed with pattern [0])
1922 *
1923 * If expect parse failure, then [i+2] should be NULL.
1924 */
expectParse(const char ** data,int32_t data_length,const Locale & loc)1925 void DateFormatTest::expectParse(const char** data, int32_t data_length,
1926 const Locale& loc) {
1927 const UDate FAIL = (UDate) -1;
1928 const UnicodeString FAIL_STR("parse failure");
1929 int32_t i = 0;
1930
1931 UErrorCode ec = U_ZERO_ERROR;
1932 SimpleDateFormat fmt("", loc, ec);
1933 SimpleDateFormat ref(data[i++], loc, ec);
1934 SimpleDateFormat gotfmt("G yyyy MM dd HH:mm:ss z", loc, ec);
1935 if (U_FAILURE(ec)) {
1936 dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1937 return;
1938 }
1939
1940 const char* currentPat = NULL;
1941 while (i<data_length) {
1942 const char* pattern = data[i++];
1943 const char* input = data[i++];
1944 const char* expected = data[i++];
1945
1946 ec = U_ZERO_ERROR;
1947 if (pattern != NULL) {
1948 fmt.applyPattern(pattern);
1949 currentPat = pattern;
1950 }
1951 UDate got = fmt.parse(input, ec);
1952 UnicodeString gotstr(FAIL_STR);
1953 if (U_FAILURE(ec)) {
1954 got = FAIL;
1955 } else {
1956 gotstr.remove();
1957 gotfmt.format(got, gotstr);
1958 }
1959
1960 UErrorCode ec2 = U_ZERO_ERROR;
1961 UDate exp = FAIL;
1962 UnicodeString expstr(FAIL_STR);
1963 if (expected != NULL) {
1964 expstr = expected;
1965 exp = ref.parse(expstr, ec2);
1966 if (U_FAILURE(ec2)) {
1967 // This only happens if expected is in wrong format --
1968 // should never happen once test is debugged.
1969 errln("FAIL: Internal test error");
1970 return;
1971 }
1972 }
1973
1974 if (got == exp) {
1975 logln((UnicodeString)"Ok: " + input + " x " +
1976 currentPat + " => " + gotstr);
1977 } else {
1978 errln((UnicodeString)"FAIL: " + input + " x " +
1979 currentPat + " => " + gotstr + ", expected " +
1980 expstr);
1981 }
1982 }
1983 }
1984
1985 /**
1986 * Test formatting and parsing. Input is an array that starts
1987 * with the following header:
1988 *
1989 * [0] = pattern string to parse [i+2] with
1990 *
1991 * followed by test cases, each of which is 3 array elements:
1992 *
1993 * [i] = pattern, or null to reuse prior pattern
1994 * [i+1] = control string, either "fp", "pf", or "F".
1995 * [i+2..] = data strings
1996 *
1997 * The number of data strings depends on the control string.
1998 * Examples:
1999 * 1. "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.56", "2004 03 10 16:36:31.560",
2000 * 'f': Format date [i+2] (as parsed using pattern [0]) and expect string [i+3].
2001 * 'p': Parse string [i+3] and expect date [i+4].
2002 *
2003 * 2. "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567"
2004 * 'F': Format date [i+2] and expect string [i+3],
2005 * then parse string [i+3] and expect date [i+2].
2006 *
2007 * 3. "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5670",
2008 * 'p': Parse string [i+2] and expect date [i+3].
2009 * 'f': Format date [i+3] and expect string [i+4].
2010 */
expect(const char ** data,int32_t data_length,const Locale & loc)2011 void DateFormatTest::expect(const char** data, int32_t data_length,
2012 const Locale& loc) {
2013 int32_t i = 0;
2014 UErrorCode ec = U_ZERO_ERROR;
2015 UnicodeString str, str2;
2016 SimpleDateFormat fmt("", loc, ec);
2017 SimpleDateFormat ref(data[i++], loc, ec);
2018 SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2019 if (U_FAILURE(ec)) {
2020 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2021 return;
2022 }
2023
2024 UnicodeString currentPat;
2025 while (i<data_length) {
2026 const char* pattern = data[i++];
2027 if (pattern != NULL) {
2028 fmt.applyPattern(pattern);
2029 currentPat = pattern;
2030 }
2031
2032 const char* control = data[i++];
2033
2034 if (uprv_strcmp(control, "fp") == 0) {
2035 // 'f'
2036 const char* datestr = data[i++];
2037 const char* string = data[i++];
2038 UDate date = ref.parse(ctou(datestr), ec);
2039 if (!assertSuccess("parse", ec)) return;
2040 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2041 ctou(string),
2042 fmt.format(date, str.remove()));
2043 // 'p'
2044 datestr = data[i++];
2045 date = ref.parse(ctou(datestr), ec);
2046 if (!assertSuccess("parse", ec)) return;
2047 UDate parsedate = fmt.parse(ctou(string), ec);
2048 if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2049 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2050 univ.format(date, str.remove()),
2051 univ.format(parsedate, str2.remove()));
2052 }
2053 }
2054
2055 else if (uprv_strcmp(control, "pf") == 0) {
2056 // 'p'
2057 const char* string = data[i++];
2058 const char* datestr = data[i++];
2059 UDate date = ref.parse(ctou(datestr), ec);
2060 if (!assertSuccess("parse", ec)) return;
2061 UDate parsedate = fmt.parse(ctou(string), ec);
2062 if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2063 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2064 univ.format(date, str.remove()),
2065 univ.format(parsedate, str2.remove()));
2066 }
2067 // 'f'
2068 string = data[i++];
2069 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2070 ctou(string),
2071 fmt.format(date, str.remove()));
2072 }
2073
2074 else if (uprv_strcmp(control, "F") == 0) {
2075 const char* datestr = data[i++];
2076 const char* string = data[i++];
2077 UDate date = ref.parse(ctou(datestr), ec);
2078 if (!assertSuccess("parse", ec)) return;
2079 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2080 ctou(string),
2081 fmt.format(date, str.remove()));
2082
2083 UDate parsedate = fmt.parse(string, ec);
2084 if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2085 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2086 univ.format(date, str.remove()),
2087 univ.format(parsedate, str2.remove()));
2088 }
2089 }
2090
2091 else {
2092 errln((UnicodeString)"FAIL: Invalid control string " + control);
2093 return;
2094 }
2095 }
2096 }
2097
2098 /**
2099 * Test formatting. Input is an array that starts
2100 * with the following header:
2101 *
2102 * [0] = pattern string to parse [i+2] with
2103 *
2104 * followed by test cases, each of which is 3 array elements:
2105 *
2106 * [i] = pattern, or null to reuse prior pattern
2107 * [i+1] = data string a
2108 * [i+2] = data string b
2109 *
2110 * Examples:
2111 * Format date [i+1] and expect string [i+2].
2112 *
2113 * "y/M/d H:mm:ss.SSSS", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567"
2114 */
expectFormat(const char ** data,int32_t data_length,const Locale & loc)2115 void DateFormatTest::expectFormat(const char** data, int32_t data_length,
2116 const Locale& loc) {
2117 int32_t i = 0;
2118 UErrorCode ec = U_ZERO_ERROR;
2119 UnicodeString str, str2;
2120 SimpleDateFormat fmt("", loc, ec);
2121 SimpleDateFormat ref(data[i++], loc, ec);
2122 SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2123 if (U_FAILURE(ec)) {
2124 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2125 return;
2126 }
2127
2128 UnicodeString currentPat;
2129
2130 while (i<data_length) {
2131 const char* pattern = data[i++];
2132 if (pattern != NULL) {
2133 fmt.applyPattern(pattern);
2134 currentPat = pattern;
2135 }
2136
2137 const char* datestr = data[i++];
2138 const char* string = data[i++];
2139 UDate date = ref.parse(ctou(datestr), ec);
2140 if (!assertSuccess("parse", ec)) return;
2141 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2142 ctou(string),
2143 fmt.format(date, str.remove()));
2144 }
2145 }
2146
TestGenericTime()2147 void DateFormatTest::TestGenericTime() {
2148 const Locale en("en");
2149 // Note: We no longer parse strings in different styles.
2150 /*
2151 const char* ZDATA[] = {
2152 "yyyy MM dd HH:mm zzz",
2153 // round trip
2154 "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2155 "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2156 "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2157 "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2158 // non-generic timezone string influences dst offset even if wrong for date/time
2159 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
2160 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 Pacific Time",
2161 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
2162 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 Pacific Time",
2163 // generic timezone generates dst offset appropriate for local time
2164 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2165 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2166 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2167 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2168 // daylight savings time transition edge cases.
2169 // time to parse does not really exist, PT interpreted as earlier time
2170 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2171 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2172 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
2173 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2174 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2175 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT",
2176 "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2177 // time to parse is ambiguous, PT interpreted as later time
2178 "y/M/d H:mm zzz", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PST",
2179 "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PT",
2180 "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2181
2182 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2183 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2184 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
2185 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2186 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2187 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PT",
2188 "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2189 };
2190 */
2191 const char* ZDATA[] = {
2192 "yyyy MM dd HH:mm zzz",
2193 // round trip
2194 "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2195 "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2196 "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2197 "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2198 // non-generic timezone string influences dst offset even if wrong for date/time
2199 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
2200 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
2201 // generic timezone generates dst offset appropriate for local time
2202 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PST", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2203 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 Pacific Time", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2204 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2205 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 Pacific Time", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2206 // daylight savings time transition edge cases.
2207 // time to parse does not really exist, PT interpreted as earlier time
2208 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2209 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
2210 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2211 "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2212 // time to parse is ambiguous, PT interpreted as later time
2213 "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PT",
2214 "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2215
2216 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2217 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
2218 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2219 "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2220 };
2221
2222 const int32_t ZDATA_length = UPRV_LENGTHOF(ZDATA);
2223 expect(ZDATA, ZDATA_length, en);
2224
2225 UErrorCode status = U_ZERO_ERROR;
2226
2227 logln("cross format/parse tests"); // Note: We no longer support cross format/parse
2228 UnicodeString basepat("yy/MM/dd H:mm ");
2229 SimpleDateFormat formats[] = {
2230 SimpleDateFormat(basepat + "vvv", en, status),
2231 SimpleDateFormat(basepat + "vvvv", en, status),
2232 SimpleDateFormat(basepat + "zzz", en, status),
2233 SimpleDateFormat(basepat + "zzzz", en, status)
2234 };
2235 if (U_FAILURE(status)) {
2236 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(status));
2237 return;
2238 }
2239 const int32_t formats_length = UPRV_LENGTHOF(formats);
2240
2241 UnicodeString test;
2242 SimpleDateFormat univ("yyyy MM dd HH:mm zzz", en, status);
2243 ASSERT_OK(status);
2244 const UnicodeString times[] = {
2245 "2004 01 02 03:04 PST",
2246 "2004 07 08 09:10 PDT"
2247 };
2248 int32_t times_length = UPRV_LENGTHOF(times);
2249 for (int i = 0; i < times_length; ++i) {
2250 UDate d = univ.parse(times[i], status);
2251 logln(UnicodeString("\ntime: ") + d);
2252 for (int j = 0; j < formats_length; ++j) {
2253 test.remove();
2254 formats[j].format(d, test);
2255 logln("\ntest: '" + test + "'");
2256 for (int k = 0; k < formats_length; ++k) {
2257 UDate t = formats[k].parse(test, status);
2258 if (U_SUCCESS(status)) {
2259 if (d != t) {
2260 errln((UnicodeString)"FAIL: format " + k +
2261 " incorrectly parsed output of format " + j +
2262 " (" + test + "), returned " +
2263 dateToString(t) + " instead of " + dateToString(d));
2264 } else {
2265 logln((UnicodeString)"OK: format " + k + " parsed ok");
2266 }
2267 } else if (status == U_PARSE_ERROR) {
2268 errln((UnicodeString)"FAIL: format " + k +
2269 " could not parse output of format " + j +
2270 " (" + test + ")");
2271 }
2272 }
2273 }
2274 }
2275 }
2276
TestGenericTimeZoneOrder()2277 void DateFormatTest::TestGenericTimeZoneOrder() {
2278 // generic times should parse the same no matter what the placement of the time zone string
2279
2280 // Note: We no longer support cross style format/parse
2281
2282 //const char* XDATA[] = {
2283 // "yyyy MM dd HH:mm zzz",
2284 // // standard time, explicit daylight/standard
2285 // "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2286 // "y/M/d zzz H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
2287 // "zzz y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
2288
2289 // // standard time, generic
2290 // "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2291 // "y/M/d vvvv H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
2292 // "vvvv y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
2293
2294 // // dahylight time, explicit daylight/standard
2295 // "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2296 // "y/M/d zzz H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
2297 // "zzz y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
2298
2299 // // daylight time, generic
2300 // "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2301 // "y/M/d vvvv H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 Pacific Time 1:00",
2302 // "vvvv y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "Pacific Time 2004/7/1 1:00",
2303 //};
2304 const char* XDATA[] = {
2305 "yyyy MM dd HH:mm zzz",
2306 // standard time, explicit daylight/standard
2307 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PST", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2308 "y/M/d zzz H:mm", "pf", "2004/1/1 PST 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
2309 "zzz y/M/d H:mm", "pf", "PST 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
2310
2311 // standard time, generic
2312 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 Pacific Time", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2313 "y/M/d vvvv H:mm", "pf", "2004/1/1 Pacific Time 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
2314 "vvvv y/M/d H:mm", "pf", "Pacific Time 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
2315
2316 // dahylight time, explicit daylight/standard
2317 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2318 "y/M/d zzz H:mm", "pf", "2004/7/1 PDT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
2319 "zzz y/M/d H:mm", "pf", "PDT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
2320
2321 // daylight time, generic
2322 "y/M/d H:mm v", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PT",
2323 "y/M/d v H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PT 1:00",
2324 "v y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PT 2004/7/1 1:00",
2325 };
2326 const int32_t XDATA_length = UPRV_LENGTHOF(XDATA);
2327 Locale en("en");
2328 expect(XDATA, XDATA_length, en);
2329 }
2330
TestZTimeZoneParsing(void)2331 void DateFormatTest::TestZTimeZoneParsing(void) {
2332 UErrorCode status = U_ZERO_ERROR;
2333 const Locale en("en");
2334 UnicodeString test;
2335 //SimpleDateFormat univ("yyyy-MM-dd'T'HH:mm Z", en, status);
2336 SimpleDateFormat univ("HH:mm Z", en, status);
2337 if (failure(status, "construct SimpleDateFormat", TRUE)) return;
2338 const TimeZone *t = TimeZone::getGMT();
2339 univ.setTimeZone(*t);
2340
2341 univ.setLenient(false);
2342 ParsePosition pp(0);
2343 struct {
2344 UnicodeString input;
2345 UnicodeString expected_result;
2346 } tests[] = {
2347 { "11:00 -0200", "13:00 +0000" },
2348 { "11:00 +0200", "09:00 +0000" },
2349 { "11:00 +0400", "07:00 +0000" },
2350 { "11:00 +0530", "05:30 +0000" }
2351 };
2352
2353 UnicodeString result;
2354 int32_t tests_length = UPRV_LENGTHOF(tests);
2355 for (int i = 0; i < tests_length; ++i) {
2356 pp.setIndex(0);
2357 UDate d = univ.parse(tests[i].input, pp);
2358 if(pp.getIndex() != tests[i].input.length()){
2359 errln("Test %i: setZoneString() did not succeed. Consumed: %i instead of %i",
2360 i, pp.getIndex(), tests[i].input.length());
2361 return;
2362 }
2363 result.remove();
2364 univ.format(d, result);
2365 if(result != tests[i].expected_result) {
2366 errln("Expected " + tests[i].expected_result
2367 + " got " + result);
2368 return;
2369 }
2370 logln("SUCCESS: Parsed " + tests[i].input
2371 + " got " + result
2372 + " expected " + tests[i].expected_result);
2373 }
2374 }
2375
TestHost(void)2376 void DateFormatTest::TestHost(void)
2377 {
2378 #if U_PLATFORM_USES_ONLY_WIN32_API
2379 Win32DateTimeTest::testLocales(this);
2380 #endif
2381 }
2382
2383 // Relative Date Tests
2384
TestRelative(int daysdelta,const Locale & loc,const char * expectChars)2385 void DateFormatTest::TestRelative(int daysdelta,
2386 const Locale& loc,
2387 const char *expectChars) {
2388 char banner[25];
2389 sprintf(banner, "%d", daysdelta);
2390 UnicodeString bannerStr(banner, "");
2391
2392 UErrorCode status = U_ZERO_ERROR;
2393
2394 FieldPosition pos(FieldPosition::DONT_CARE);
2395 UnicodeString test;
2396 Locale en("en");
2397 DateFormat *fullrelative = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2398
2399 if (fullrelative == NULL) {
2400 dataerrln("DateFormat::createDateInstance(DateFormat::kFullRelative, %s) returned NULL", loc.getName());
2401 return;
2402 }
2403
2404 DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull , loc);
2405
2406 if (full == NULL) {
2407 errln("DateFormat::createDateInstance(DateFormat::kFull, %s) returned NULL", loc.getName());
2408 return;
2409 }
2410
2411 DateFormat *en_full = DateFormat::createDateInstance(DateFormat::kFull, en);
2412
2413 if (en_full == NULL) {
2414 errln("DateFormat::createDateInstance(DateFormat::kFull, en) returned NULL");
2415 return;
2416 }
2417
2418 DateFormat *en_fulltime = DateFormat::createDateTimeInstance(DateFormat::kFull,DateFormat::kFull,en);
2419
2420 if (en_fulltime == NULL) {
2421 errln("DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, en) returned NULL");
2422 return;
2423 }
2424
2425 UnicodeString result;
2426 UnicodeString normalResult;
2427 UnicodeString expect;
2428 UnicodeString parseResult;
2429
2430 Calendar *c = Calendar::createInstance(status);
2431
2432 // Today = Today
2433 c->setTime(Calendar::getNow(), status);
2434 if(daysdelta != 0) {
2435 c->add(Calendar::DATE,daysdelta,status);
2436 }
2437 ASSERT_OK(status);
2438
2439 // calculate the expected string
2440 if(expectChars != NULL) {
2441 expect = expectChars;
2442 } else {
2443 full->format(*c, expect, pos); // expected = normal full
2444 }
2445
2446 fullrelative ->format(*c, result, pos);
2447 en_full ->format(*c, normalResult, pos);
2448
2449 if(result != expect) {
2450 errln("FAIL: Relative Format ["+bannerStr+"] of "+normalResult+" failed, expected "+expect+" but got " + result);
2451 } else {
2452 logln("PASS: Relative Format ["+bannerStr+"] of "+normalResult+" got " + result);
2453 }
2454
2455
2456 //verify
2457 UDate d = fullrelative->parse(result, status);
2458 ASSERT_OK(status);
2459
2460 UnicodeString parseFormat; // parse rel->format full
2461 en_full->format(d, parseFormat, status);
2462
2463 UnicodeString origFormat;
2464 en_full->format(*c, origFormat, pos);
2465
2466 if(parseFormat!=origFormat) {
2467 errln("FAIL: Relative Parse ["+bannerStr+"] of "+result+" failed, expected "+parseFormat+" but got "+origFormat);
2468 } else {
2469 logln("PASS: Relative Parse ["+bannerStr+"] of "+result+" passed, got "+parseFormat);
2470 }
2471
2472 delete full;
2473 delete fullrelative;
2474 delete en_fulltime;
2475 delete en_full;
2476 delete c;
2477 }
2478
2479
TestRelative(void)2480 void DateFormatTest::TestRelative(void)
2481 {
2482 Locale en("en");
2483 TestRelative( 0, en, "today");
2484 TestRelative(-1, en, "yesterday");
2485 TestRelative( 1, en, "tomorrow");
2486 TestRelative( 2, en, NULL);
2487 TestRelative( -2, en, NULL);
2488 TestRelative( 3, en, NULL);
2489 TestRelative( -3, en, NULL);
2490 TestRelative( 300, en, NULL);
2491 TestRelative( -300, en, NULL);
2492 }
2493
TestRelativeClone(void)2494 void DateFormatTest::TestRelativeClone(void)
2495 {
2496 /*
2497 Verify that a cloned formatter gives the same results
2498 and is useable after the original has been deleted.
2499 */
2500 UErrorCode status = U_ZERO_ERROR;
2501 Locale loc("en");
2502 UDate now = Calendar::getNow();
2503 DateFormat *full = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2504 if (full == NULL) {
2505 dataerrln("FAIL: Can't create Relative date instance");
2506 return;
2507 }
2508 UnicodeString result1;
2509 full->format(now, result1, status);
2510 Format *fullClone = full->clone();
2511 delete full;
2512 full = NULL;
2513
2514 UnicodeString result2;
2515 fullClone->format(now, result2, status);
2516 ASSERT_OK(status);
2517 if (result1 != result2) {
2518 errln("FAIL: Clone returned different result from non-clone.");
2519 }
2520 delete fullClone;
2521 }
2522
TestHostClone(void)2523 void DateFormatTest::TestHostClone(void)
2524 {
2525 /*
2526 Verify that a cloned formatter gives the same results
2527 and is useable after the original has been deleted.
2528 */
2529 // This is mainly important on Windows.
2530 UErrorCode status = U_ZERO_ERROR;
2531 Locale loc("en_US@compat=host");
2532 UDate now = Calendar::getNow();
2533 DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull, loc);
2534 if (full == NULL) {
2535 dataerrln("FAIL: Can't create host date instance");
2536 return;
2537 }
2538 UnicodeString result1;
2539 full->format(now, result1, status);
2540 Format *fullClone = full->clone();
2541 delete full;
2542 full = NULL;
2543
2544 UnicodeString result2;
2545 fullClone->format(now, result2, status);
2546 ASSERT_OK(status);
2547 if (result1 != result2) {
2548 errln("FAIL: Clone returned different result from non-clone.");
2549 }
2550 delete fullClone;
2551 }
2552
TestHebrewClone(void)2553 void DateFormatTest::TestHebrewClone(void)
2554 {
2555 /*
2556 Verify that a cloned formatter gives the same results
2557 and is useable after the original has been deleted.
2558 */
2559 UErrorCode status = U_ZERO_ERROR;
2560 Locale loc("he@calendar=hebrew");
2561 UDate now = Calendar::getNow();
2562 LocalPointer<DateFormat> fmt(
2563 DateFormat::createDateInstance(DateFormat::kLong, loc));
2564 if (fmt.isNull()) {
2565 dataerrln("FAIL: Can't create Hebrew date instance");
2566 return;
2567 }
2568 UnicodeString result1;
2569 fmt->format(now, result1, status);
2570 LocalPointer<Format> fmtClone(fmt->clone());
2571
2572 // free fmt to be sure that fmtClone is independent of fmt.
2573 fmt.adoptInstead(NULL);
2574
2575 UnicodeString result2;
2576 fmtClone->format(now, result2, status);
2577 ASSERT_OK(status);
2578 if (result1 != result2) {
2579 errln("FAIL: Clone returned different result from non-clone.");
2580 }
2581 }
2582
getActualAndValidLocales(const Format & fmt,Locale & valid,Locale & actual)2583 static UBool getActualAndValidLocales(
2584 const Format &fmt, Locale &valid, Locale &actual) {
2585 const SimpleDateFormat* dat = dynamic_cast<const SimpleDateFormat*>(&fmt);
2586 if (dat == NULL) {
2587 return FALSE;
2588 }
2589 const DateFormatSymbols *sym = dat->getDateFormatSymbols();
2590 if (sym == NULL) {
2591 return FALSE;
2592 }
2593 UErrorCode status = U_ZERO_ERROR;
2594 valid = sym->getLocale(ULOC_VALID_LOCALE, status);
2595 actual = sym->getLocale(ULOC_ACTUAL_LOCALE, status);
2596 return U_SUCCESS(status);
2597 }
2598
TestDateFormatSymbolsClone(void)2599 void DateFormatTest::TestDateFormatSymbolsClone(void)
2600 {
2601 /*
2602 Verify that a cloned formatter gives the same results
2603 and is useable after the original has been deleted.
2604 */
2605 Locale loc("de_CH_LUCERNE");
2606 LocalPointer<DateFormat> fmt(
2607 DateFormat::createDateInstance(DateFormat::kDefault, loc));
2608 if (fmt.isNull()) {
2609 dataerrln("FAIL: DateFormat::createDateInstance failed for %s", loc.getName());
2610 return;
2611 }
2612 Locale valid1;
2613 Locale actual1;
2614 if (!getActualAndValidLocales(*fmt, valid1, actual1)) {
2615 dataerrln("FAIL: Could not fetch valid + actual locales");
2616 return;
2617 }
2618 LocalPointer<Format> fmtClone(fmt->clone());
2619
2620 // Free fmt to be sure that fmtClone is really independent of fmt.
2621 fmt.adoptInstead(NULL);
2622 Locale valid2;
2623 Locale actual2;
2624 if (!getActualAndValidLocales(*fmtClone, valid2, actual2)) {
2625 errln("FAIL: Could not fetch valid + actual locales");
2626 return;
2627 }
2628 if (valid1 != valid2 || actual1 != actual2) {
2629 errln("Date format symbol locales of clone don't match original");
2630 }
2631 }
2632
TestTimeZoneDisplayName()2633 void DateFormatTest::TestTimeZoneDisplayName()
2634 {
2635 // This test data was ported from ICU4J. Don't know why the 6th column in there because it's not being
2636 // used currently.
2637 const char *fallbackTests[][6] = {
2638 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2639 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2640 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZZ", "-08:00", "-8:00" },
2641 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "PST", "America/Los_Angeles" },
2642 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Pacific Standard Time", "America/Los_Angeles" },
2643 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2644 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2645 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "PDT", "America/Los_Angeles" },
2646 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Pacific Daylight Time", "America/Los_Angeles" },
2647 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "PT", "America/Los_Angeles" },
2648 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Pacific Time", "America/Los_Angeles" },
2649 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "Los Angeles Time", "America/Los_Angeles" },
2650 { "en_GB", "America/Los_Angeles", "2004-01-15T12:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2651 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "Z", "-0700", "-7:00" },
2652 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2653 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2654 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2655 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2656 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2657 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2658 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2659 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "v", "MST", "America/Phoenix" },
2660 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "vvvv", "Mountain Standard Time", "America/Phoenix" },
2661 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "VVVV", "Phoenix Time", "America/Phoenix" },
2662
2663 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2664 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2665 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2666 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2667 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2668 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2669 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2670 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2671 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2672 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2673 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2674
2675 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2676 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2677 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2678 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2679 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2680 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2681 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2682 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2683 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2684 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2685 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2686
2687 { "en", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2688 { "en", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2689 { "en", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2690 { "en", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Cuba Standard Time", "-5:00" },
2691 { "en", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2692 { "en", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2693 { "en", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2694 { "en", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Cuba Daylight Time", "-4:00" },
2695 { "en", "America/Havana", "2004-07-15T00:00:00Z", "v", "Cuba Time", "America/Havana" },
2696 { "en", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Cuba Time", "America/Havana" },
2697 { "en", "America/Havana", "2004-07-15T00:00:00Z", "VVVV", "Cuba Time", "America/Havana" },
2698
2699 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2700 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2701 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2702 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2703 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2704 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2705 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2706 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2707 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2708 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2709 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2710
2711 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2712 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2713 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2714 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2715 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2716 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2717 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2718 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2719 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2720 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2721 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2722
2723 { "en", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2724 { "en", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2725 { "en", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2726 { "en", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Greenwich Mean Time", "+0:00" },
2727 { "en", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2728 { "en", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2729 { "en", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "Europe/London" },
2730 { "en", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "British Summer Time", "Europe/London" },
2731 // icu en.txt has exemplar city for this time zone
2732 { "en", "Europe/London", "2004-07-15T00:00:00Z", "v", "United Kingdom Time", "Europe/London" },
2733 { "en", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "United Kingdom Time", "Europe/London" },
2734 { "en", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "United Kingdom Time", "Europe/London" },
2735
2736 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2737 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2738 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2739 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2740 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2741 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2742 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2743 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2744 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2745 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2746
2747 // JB#5150
2748 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2749 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2750 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2751 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2752 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2753 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2754 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2755 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2756 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "India Time", "Asia/Calcutta" },
2757 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "India Standard Time", "Asia/Calcutta" },
2758
2759 // Proper CLDR primary zone support #9733
2760 { "en", "America/Santiago", "2013-01-01T00:00:00Z", "VVVV", "Chile Time", "America/Santiago" },
2761 { "en", "Pacific/Easter", "2013-01-01T00:00:00Z", "VVVV", "Easter Time", "Pacific/Easter" },
2762
2763 // ==========
2764
2765 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2766 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2767 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2768 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Normalzeit", "-8:00" },
2769 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2770 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2771 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2772 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Sommerzeit", "-7:00" },
2773 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles Zeit", "America/Los_Angeles" },
2774 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Nordamerikanische Westk\\u00fcstenzeit", "America/Los_Angeles" },
2775
2776 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2777 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2778 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2779 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2780 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2781 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2782 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2783 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2784 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2785 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2786
2787 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2788 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2789 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2790 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2791 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2792 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2793 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2794 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2795 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2796 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2797
2798 { "de", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2799 { "de", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2800 { "de", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2801 { "de", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Kubanische Normalzeit", "-5:00" },
2802 { "de", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2803 { "de", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2804 { "de", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2805 { "de", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Kubanische Sommerzeit", "-4:00" },
2806 { "de", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2807 { "de", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2808 // added to test proper fallback of country name
2809 { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2810 { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2811
2812 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2813 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2814 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2815 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2816 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2817 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2818 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2819 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2820 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2821 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2822
2823 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2824 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2825 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2826 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2827 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2828 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2829 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2830 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2831 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2832 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2833
2834 { "de", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2835 { "de", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2836 { "de", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2837 { "de", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Mittlere Greenwich-Zeit", "+0:00" },
2838 { "de", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2839 { "de", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2840 { "de", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2841 { "de", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "Britische Sommerzeit", "+1:00" },
2842 { "de", "Europe/London", "2004-07-15T00:00:00Z", "v", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2843 { "de", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2844
2845 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2846 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2847 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2848 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2849 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2850 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2851 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2852 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2853 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2854 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2855
2856 // JB#5150
2857 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2858 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2859 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2860 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2861 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2862 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2863 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2864 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2865 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "Indien Zeit", "Asia/Calcutta" },
2866 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "Indische Zeit", "Asia/Calcutta" },
2867
2868 // ==========
2869
2870 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2871 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2872 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2873 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u6807\\u51c6\\u65f6\\u95f4", "America/Los_Angeles" },
2874 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2875 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2876 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
2877 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u590f\\u4ee4\\u65f6\\u95f4", "America/Los_Angeles" },
2878 // icu zh.txt has exemplar city for this time zone
2879 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4", "America/Los_Angeles" },
2880 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u65f6\\u95f4", "America/Los_Angeles" },
2881
2882 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2883 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2884 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2885 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2886 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2887 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2888 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2889 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2890 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2891 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2892
2893 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2894 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2895 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2896 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2897 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2898 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2899 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2900 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2901 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2902 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2903
2904 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2905 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2906 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2907 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u6807\\u51c6\\u65f6\\u95f4", "-5:00" },
2908 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2909 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2910 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2911 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u590f\\u4ee4\\u65f6\\u95f4", "-4:00" },
2912 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2913 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2914
2915 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2916 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2917 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2918 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2919 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2920 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2921 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2922 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2923 // icu zh.txt does not have info for this time zone
2924 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2925 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2926
2927 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2928 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2929 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2930 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2931 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2932 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2933 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2934 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2935 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2936 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2937
2938 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2939 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2940 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2941 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2942 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2943 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u683C\\u6797\\u5C3C\\u6CBB\\u6807\\u51C6\\u65F6\\u95F4", "+0:00" },
2944 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2945 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2946 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2947 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u4ee4\\u65f6\\u95f4", "+1:00" },
2948 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2949 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2950 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2951
2952 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2953 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2954 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2955 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2956 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2957 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2958 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2959 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2960 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2961 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2962
2963 // JB#5150
2964 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2965 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2966 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2967 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2968 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2969 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2970 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2971 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2972 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2973 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2974
2975 // ==========
2976
2977 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2978 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2979 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2980 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-8:00" },
2981 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2982 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2983 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2984 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "-7:00" },
2985 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u0932\\u0949\\u0938 \\u090f\\u0902\\u091c\\u093f\\u0932\\u094d\\u0938 \\u0938\\u092e\\u092f", "America/Los_Angeles" },
2986 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u0938\\u092e\\u092f", "America/Los_Angeles" },
2987
2988 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2989 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2990 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2991 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2992 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2993 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2994 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2995 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2996 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u092C\\u094D\\u092F\\u0942\\u0928\\u0938 \\u0906\\u092F\\u0930\\u0938 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2997 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2998
2999 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3000 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3001 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3002 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
3003 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3004 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3005 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3006 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
3007 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u092C\\u094D\\u092F\\u0942\\u0928\\u0938 \\u0906\\u092F\\u0930\\u0938 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
3008 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
3009
3010 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3011 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3012 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3013 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-5:00" },
3014 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3015 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3016 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3017 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "-4:00" },
3018 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092E\\u092F", "America/Havana" },
3019 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092e\\u092f", "America/Havana" },
3020
3021 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3022 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3023 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3024 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "+11:00" },
3025 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3026 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3027 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3028 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "+10:00" },
3029 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3030 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0911\\u0938\\u094d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e \\u0938\\u092e\\u092f", "Australia/Sydney" },
3031
3032 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3033 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3034 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3035 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "+11:00" },
3036 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3037 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3038 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3039 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "+10:00" },
3040 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3041 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0911\\u0938\\u094d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e \\u0938\\u092e\\u092f", "Australia/Sydney" },
3042
3043 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3044 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3045 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3046 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u0917\\u094d\\u0930\\u0940\\u0928\\u0935\\u093f\\u091a \\u092e\\u0940\\u0928 \\u091f\\u093e\\u0907\\u092e", "+0:00" },
3047 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3048 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3049 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3050 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u092c\\u094d\\u0930\\u093f\\u091f\\u093f\\u0936 \\u0917\\u094d\\u0930\\u0940\\u0937\\u094d\\u092e\\u0915\\u093e\\u0932\\u0940\\u0928 \\u0938\\u092e\\u092f", "+1:00" },
3051 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u092f\\u0942\\u0928\\u093e\\u0907\\u091f\\u0947\\u0921 \\u0915\\u093f\\u0902\\u0917\\u0921\\u092e \\u0938\\u092e\\u092f", "Europe/London" },
3052 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u092f\\u0942\\u0928\\u093e\\u0907\\u091f\\u0947\\u0921 \\u0915\\u093f\\u0902\\u0917\\u0921\\u092e \\u0938\\u092e\\u092f", "Europe/London" },
3053
3054 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3055 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3056 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3057 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3058 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3059 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3060 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3061 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3062 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3063 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3064
3065 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3066 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3067 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "IST", "+5:30" },
3068 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3069 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3070 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3071 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "IST", "+05:30" },
3072 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3073 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IST", "Asia/Calcutta" },
3074 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "Asia/Calcutta" },
3075
3076 // ==========
3077
3078 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3079 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-08:00", "-8:00" },
3080 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-8", "America/Los_Angeles" },
3081 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3082 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3083 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-07:00", "-7:00" },
3084 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-7", "America/Los_Angeles" },
3085 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3086 // icu bg.txt has exemplar city for this time zone
3087 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3088 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3089 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3090
3091 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3092 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3093 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3094 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3095 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3096 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3097 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3098 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3099 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
3100 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Buenos_Aires" },
3101
3102 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3103 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3104 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3105 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3106 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3107 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3108 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3109 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3110 // icu bg.txt does not have info for this time zone
3111 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
3112 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Buenos_Aires" },
3113
3114 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3115 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-05:00", "-5:00" },
3116 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-5", "-5:00" },
3117 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-5:00" },
3118 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3119 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-04:00", "-4:00" },
3120 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-4", "-4:00" },
3121 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-4:00" },
3122 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u041a\\u0443\\u0431\\u0430", "America/Havana" },
3123 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043C\\u0435", "America/Havana" },
3124
3125 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3126 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3127 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3128 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u043B\\u044F\\u0442\\u043D\\u043E \\u0447\\u0430\\u0441\\u043E\\u0432\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+11:00" },
3129 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3130 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3131 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3132 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+10:00" },
3133 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3134 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "Australia/Sydney" },
3135
3136 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3137 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3138 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3139 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u043B\\u044F\\u0442\\u043D\\u043E \\u0447\\u0430\\u0441\\u043E\\u0432\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+11:00" },
3140 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3141 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3142 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3143 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+10:00" },
3144 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3145 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "Australia/Sydney" },
3146
3147 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3148 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3149 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3150 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u0421\\u0440\\u0435\\u0434\\u043d\\u043e \\u0433\\u0440\\u0438\\u043d\\u0443\\u0438\\u0447\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+0:00" },
3151 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3152 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+01:00", "+1:00" },
3153 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+1", "+1:00" },
3154 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u0411\\u0440\\u0438\\u0442\\u0430\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+1:00" },
3155 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u041E\\u0431\\u0435\\u0434\\u0438\\u043D\\u0435\\u043D\\u043E\\u0442\\u043E \\u043A\\u0440\\u0430\\u043B\\u0441\\u0442\\u0432\\u043E", "Europe/London" },
3156 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u041E\\u0431\\u0435\\u0434\\u0438\\u043D\\u0435\\u043D\\u043E\\u0442\\u043E \\u043A\\u0440\\u0430\\u043B\\u0441\\u0442\\u0432\\u043E", "Europe/London" },
3157
3158 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3159 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3160 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3161 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3162 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3163 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3164 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3165 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3166 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3167 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3168
3169 // JB#5150
3170 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3171 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3172 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+5:30" },
3173 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u043D\\u0434\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
3174 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3175 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3176 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+05:30" },
3177 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u043D\\u0434\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
3178 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u0418\\u043D\\u0434\\u0438\\u044F", "Asia/Calcutta" },
3179 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u043D\\u0434\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "Asia/Calcutta" },
3180 // ==========
3181
3182 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3183 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3184 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
3185 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u6a19\\u6e96\\u6642", "America/Los_Angeles" },
3186 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-700" },
3187 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3188 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
3189 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u590f\\u6642\\u9593", "America/Los_Angeles" },
3190 // icu ja.txt has exemplar city for this time zone
3191 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3192 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30E1\\u30EA\\u30AB\\u592A\\u5e73\\u6D0B\\u6642\\u9593", "America/Los_Angeles" },
3193 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3194
3195 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3196 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3197 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3198 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3199 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3200 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3201 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3202 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3203 // icu ja.txt does not have info for this time zone
3204 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3205 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3206
3207 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3208 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3209 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3210 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3211 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3212 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3213 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3214 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3215 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3216 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3217
3218 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3219 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3220 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3221 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u6A19\\u6E96\\u6642", "-5:00" },
3222 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3223 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3224 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3225 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u590F\\u6642\\u9593", "-4:00" },
3226 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3227 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3228
3229 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3230 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3231 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3232 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3233 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3234 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3235 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3236 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3237 // icu ja.txt does not have info for this time zone
3238 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3239 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3240
3241 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3242 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3243 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3244 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3245 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3246 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3247 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3248 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3249 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3250 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3251
3252 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3253 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3254 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3255 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u30B0\\u30EA\\u30CB\\u30C3\\u30B8\\u6A19\\u6E96\\u6642", "+0:00" },
3256 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3257 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3258 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3259 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u6642\\u9593", "+1:00" },
3260 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3261 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3262 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3263
3264 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3265 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3266 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3267 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3268 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3269 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3270 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3271 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3272 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3273 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3274
3275 // JB#5150
3276 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3277 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3278 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3279 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3280 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3281 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3282 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3283 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3284 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u30A4\\u30F3\\u30C9\\u6642\\u9593", "Asia/Calcutta" },
3285 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "Asia/Calcutta" },
3286
3287 // ==========
3288
3289 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3290 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3291 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
3292 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "GMT-08:00", "-8:00" },
3293 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3294 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3295 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
3296 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "GMT-07:00", "-7:00" },
3297 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles", "America/Los_Angeles" },
3298 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Los Angeles", "America/Los_Angeles" },
3299
3300 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3301 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3302 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3303 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3304 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3305 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3306 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3307 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3308 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3309 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3310
3311 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3312 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3313 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3314 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3315 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3316 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3317 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3318 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3319 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3320 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3321
3322 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3323 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3324 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3325 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "GMT-05:00", "-5:00" },
3326 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3327 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3328 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3329 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "GMT-04:00", "-4:00" },
3330 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u12A9\\u1263", "America/Havana" },
3331 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u12A9\\u1263", "America/Havana" },
3332
3333 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3334 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3335 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3336 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3337 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3338 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3339 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3340 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3341 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3342 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3343
3344 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3345 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3346 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3347 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3348 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3349 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3350 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3351 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3352 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3353 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3354
3355 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3356 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3357 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3358 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "GMT", "+0:00" },
3359 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3360 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3361 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3362 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "GMT+01:00", "+1:00" },
3363 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u12A5\\u1295\\u130D\\u120A\\u12DD", "Europe/London" },
3364 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u12A5\\u1295\\u130D\\u120A\\u12DD", "Europe/London" },
3365
3366 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3367 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3368 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3369 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3370 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3371 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3372 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3373 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3374 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3375 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3376
3377 // JB#5150
3378 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3379 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3380 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3381 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3382 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3383 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3384 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3385 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3386 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u1205\\u1295\\u12F2", "Alna/Calcutta" },
3387 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u1205\\u1295\\u12F2", "Asia/Calcutta" },
3388
3389 // Ticket#8589 Partial location name to use country name if the zone is the golden
3390 // zone for the time zone's country.
3391 { "en_MX", "America/Chicago", "1995-07-15T00:00:00Z", "vvvv", "Central Time (United States)", "America/Chicago"},
3392
3393 // Tests proper handling of time zones that should have empty sets when inherited from the parent.
3394 // For example, en_GB understands CET as Central European Time, but en_HK, which inherits from en_GB
3395 // does not
3396 { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3397 { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3398 { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "CET", "+1:00"},
3399 { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "CEST", "+2:00"},
3400 { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3401 { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3402 { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "GMT+1", "+1:00"},
3403 { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "GMT+2", "+2:00"},
3404
3405 { NULL, NULL, NULL, NULL, NULL, NULL },
3406 };
3407
3408 UErrorCode status = U_ZERO_ERROR;
3409 Calendar *cal = GregorianCalendar::createInstance(status);
3410 if (failure(status, "GregorianCalendar::createInstance", TRUE)) return;
3411 SimpleDateFormat testfmt(UnicodeString("yyyy-MM-dd'T'HH:mm:ss'Z'"), status);
3412 if (failure(status, "SimpleDateFormat constructor", TRUE)) return;
3413 testfmt.setTimeZone(*TimeZone::getGMT());
3414
3415 for (int i = 0; fallbackTests[i][0]; i++) {
3416 const char **testLine = fallbackTests[i];
3417 UnicodeString info[5];
3418 for ( int j = 0 ; j < 5 ; j++ ) {
3419 info[j] = UnicodeString(testLine[j], -1, US_INV);
3420 }
3421 info[4] = info[4].unescape();
3422 logln("%s;%s;%s;%s", testLine[0], testLine[1], testLine[2], testLine[3]);
3423
3424 TimeZone *tz = TimeZone::createTimeZone(info[1]);
3425
3426 UDate d = testfmt.parse(testLine[2], status);
3427 cal->setTime(d, status);
3428 if (U_FAILURE(status)) {
3429 errln(UnicodeString("Failed to set date: ") + testLine[2]);
3430 }
3431
3432 SimpleDateFormat fmt(info[3], Locale(testLine[0]),status);
3433 ASSERT_OK(status);
3434 cal->adoptTimeZone(tz);
3435 UnicodeString result;
3436 FieldPosition pos(FieldPosition::DONT_CARE);
3437 fmt.format(*cal,result,pos);
3438 if (result != info[4]) {
3439 errln(info[0] + ";" + info[1] + ";" + info[2] + ";" + info[3] + " expected: '" +
3440 info[4] + "' but got: '" + result + "'");
3441 }
3442 }
3443 delete cal;
3444 }
3445
TestRoundtripWithCalendar(void)3446 void DateFormatTest::TestRoundtripWithCalendar(void) {
3447 UErrorCode status = U_ZERO_ERROR;
3448
3449 TimeZone *tz = TimeZone::createTimeZone("Europe/Paris");
3450 TimeZone *gmt = TimeZone::createTimeZone("Etc/GMT");
3451
3452 Calendar *calendars[] = {
3453 Calendar::createInstance(*tz, Locale("und@calendar=gregorian"), status),
3454 Calendar::createInstance(*tz, Locale("und@calendar=buddhist"), status),
3455 // Calendar::createInstance(*tz, Locale("und@calendar=hebrew"), status),
3456 Calendar::createInstance(*tz, Locale("und@calendar=islamic"), status),
3457 Calendar::createInstance(*tz, Locale("und@calendar=japanese"), status),
3458 NULL
3459 };
3460 if (U_FAILURE(status)) {
3461 dataerrln("Failed to initialize calendars: %s", u_errorName(status));
3462 for (int i = 0; calendars[i] != NULL; i++) {
3463 delete calendars[i];
3464 }
3465 return;
3466 }
3467
3468 //FIXME The formatters commented out below are currently failing because of
3469 // the calendar calculation problem reported by #6691
3470
3471 // The order of test formatters must match the order of calendars above.
3472 DateFormat *formatters[] = {
3473 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("en_US")), //calendar=gregorian
3474 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("th_TH")), //calendar=buddhist
3475 // DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("he_IL@calendar=hebrew")),
3476 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ar_EG@calendar=islamic")),
3477 // DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ja_JP@calendar=japanese")),
3478 NULL
3479 };
3480
3481 UDate d = Calendar::getNow();
3482 UnicodeString buf;
3483 FieldPosition fpos;
3484 ParsePosition ppos;
3485
3486 for (int i = 0; formatters[i] != NULL; i++) {
3487 buf.remove();
3488 fpos.setBeginIndex(0);
3489 fpos.setEndIndex(0);
3490 calendars[i]->setTime(d, status);
3491
3492 // Normal case output - the given calendar matches the calendar
3493 // used by the formatter
3494 formatters[i]->format(*calendars[i], buf, fpos);
3495 UnicodeString refStr(buf);
3496
3497 for (int j = 0; calendars[j] != NULL; j++) {
3498 if (j == i) {
3499 continue;
3500 }
3501 buf.remove();
3502 fpos.setBeginIndex(0);
3503 fpos.setEndIndex(0);
3504 calendars[j]->setTime(d, status);
3505
3506 // Even the different calendar type is specified,
3507 // we should get the same result.
3508 formatters[i]->format(*calendars[j], buf, fpos);
3509 if (refStr != buf) {
3510 errln((UnicodeString)"FAIL: Different format result with a different calendar for the same time -"
3511 + "\n Reference calendar type=" + calendars[i]->getType()
3512 + "\n Another calendar type=" + calendars[j]->getType()
3513 + "\n Expected result=" + refStr
3514 + "\n Actual result=" + buf);
3515 }
3516 }
3517
3518 calendars[i]->setTimeZone(*gmt);
3519 calendars[i]->clear();
3520 ppos.setErrorIndex(-1);
3521 ppos.setIndex(0);
3522
3523 // Normal case parse result - the given calendar matches the calendar
3524 // used by the formatter
3525 formatters[i]->parse(refStr, *calendars[i], ppos);
3526
3527 for (int j = 0; calendars[j] != NULL; j++) {
3528 if (j == i) {
3529 continue;
3530 }
3531 calendars[j]->setTimeZone(*gmt);
3532 calendars[j]->clear();
3533 ppos.setErrorIndex(-1);
3534 ppos.setIndex(0);
3535
3536 // Even the different calendar type is specified,
3537 // we should get the same time and time zone.
3538 formatters[i]->parse(refStr, *calendars[j], ppos);
3539 if (calendars[i]->getTime(status) != calendars[j]->getTime(status)
3540 || calendars[i]->getTimeZone() != calendars[j]->getTimeZone()) {
3541 UnicodeString tzid;
3542 errln((UnicodeString)"FAIL: Different parse result with a different calendar for the same string -"
3543 + "\n Reference calendar type=" + calendars[i]->getType()
3544 + "\n Another calendar type=" + calendars[j]->getType()
3545 + "\n Date string=" + refStr
3546 + "\n Expected time=" + calendars[i]->getTime(status)
3547 + "\n Expected time zone=" + calendars[i]->getTimeZone().getID(tzid)
3548 + "\n Actual time=" + calendars[j]->getTime(status)
3549 + "\n Actual time zone=" + calendars[j]->getTimeZone().getID(tzid));
3550 }
3551 }
3552 if (U_FAILURE(status)) {
3553 errln((UnicodeString)"FAIL: " + u_errorName(status));
3554 break;
3555 }
3556 }
3557
3558 delete tz;
3559 delete gmt;
3560 for (int i = 0; calendars[i] != NULL; i++) {
3561 delete calendars[i];
3562 }
3563 for (int i = 0; formatters[i] != NULL; i++) {
3564 delete formatters[i];
3565 }
3566 }
3567
3568 /*
3569 void DateFormatTest::TestRelativeError(void)
3570 {
3571 UErrorCode status;
3572 Locale en("en");
3573
3574 DateFormat *en_reltime_reldate = DateFormat::createDateTimeInstance(DateFormat::kFullRelative,DateFormat::kFullRelative,en);
3575 if(en_reltime_reldate == NULL) {
3576 logln("PASS: rel date/rel time failed");
3577 } else {
3578 errln("FAIL: rel date/rel time created, should have failed.");
3579 delete en_reltime_reldate;
3580 }
3581 }
3582
3583 void DateFormatTest::TestRelativeOther(void)
3584 {
3585 logln("Nothing in this test. When we get more data from CLDR, put in some tests of -2, +2, etc. ");
3586 }
3587 */
3588
Test6338(void)3589 void DateFormatTest::Test6338(void)
3590 {
3591 UErrorCode status = U_ZERO_ERROR;
3592
3593 SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("ar"), status);
3594 if (failure(status, "new SimpleDateFormat", TRUE)) return;
3595
3596 UDate dt1 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3597 UnicodeString str1;
3598 str1 = fmt1->format(dt1, str1);
3599 logln(str1);
3600
3601 UDate dt11 = fmt1->parse(str1, status);
3602 failure(status, "fmt->parse");
3603
3604 UnicodeString str11;
3605 str11 = fmt1->format(dt11, str11);
3606 logln(str11);
3607
3608 if (str1 != str11) {
3609 errln((UnicodeString)"FAIL: Different dates str1:" + str1
3610 + " str2:" + str11);
3611 }
3612 delete fmt1;
3613
3614 /////////////////
3615
3616 status = U_ZERO_ERROR;
3617 SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("y M d"), Locale("ar"), status);
3618 failure(status, "new SimpleDateFormat");
3619
3620 UDate dt2 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3621 UnicodeString str2;
3622 str2 = fmt2->format(dt2, str2);
3623 logln(str2);
3624
3625 UDate dt22 = fmt2->parse(str2, status);
3626 failure(status, "fmt->parse");
3627
3628 UnicodeString str22;
3629 str22 = fmt2->format(dt22, str22);
3630 logln(str22);
3631
3632 if (str2 != str22) {
3633 errln((UnicodeString)"FAIL: Different dates str1:" + str2
3634 + " str2:" + str22);
3635 }
3636 delete fmt2;
3637
3638 /////////////////
3639
3640 status = U_ZERO_ERROR;
3641 SimpleDateFormat *fmt3 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("en-us"), status);
3642 failure(status, "new SimpleDateFormat");
3643
3644 UDate dt3 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3645 UnicodeString str3;
3646 str3 = fmt3->format(dt3, str3);
3647 logln(str3);
3648
3649 UDate dt33 = fmt3->parse(str3, status);
3650 failure(status, "fmt->parse");
3651
3652 UnicodeString str33;
3653 str33 = fmt3->format(dt33, str33);
3654 logln(str33);
3655
3656 if (str3 != str33) {
3657 errln((UnicodeString)"FAIL: Different dates str1:" + str3
3658 + " str2:" + str33);
3659 }
3660 delete fmt3;
3661
3662 /////////////////
3663
3664 status = U_ZERO_ERROR;
3665 SimpleDateFormat *fmt4 = new SimpleDateFormat(UnicodeString("y M d"), Locale("en-us"), status);
3666 failure(status, "new SimpleDateFormat");
3667
3668 UDate dt4 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3669 UnicodeString str4;
3670 str4 = fmt4->format(dt4, str4);
3671 logln(str4);
3672
3673 UDate dt44 = fmt4->parse(str4, status);
3674 failure(status, "fmt->parse");
3675
3676 UnicodeString str44;
3677 str44 = fmt4->format(dt44, str44);
3678 logln(str44);
3679
3680 if (str4 != str44) {
3681 errln((UnicodeString)"FAIL: Different dates str1:" + str4
3682 + " str2:" + str44);
3683 }
3684 delete fmt4;
3685
3686 }
3687
Test6726(void)3688 void DateFormatTest::Test6726(void)
3689 {
3690 // status
3691 // UErrorCode status = U_ZERO_ERROR;
3692
3693 // fmtf, fmtl, fmtm, fmts;
3694 UnicodeString strf, strl, strm, strs;
3695 UDate dt = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3696
3697 Locale loc("ja");
3698 DateFormat* fmtf = DateFormat::createDateTimeInstance(DateFormat::FULL, DateFormat::FULL, loc);
3699 DateFormat* fmtl = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::FULL, loc);
3700 DateFormat* fmtm = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, loc);
3701 DateFormat* fmts = DateFormat::createDateTimeInstance(DateFormat::SHORT, DateFormat::FULL, loc);
3702 if (fmtf == NULL || fmtl == NULL || fmtm == NULL || fmts == NULL) {
3703 dataerrln("Unable to create DateFormat. got NULL.");
3704 /* It may not be true that if one is NULL all is NULL. Just to be safe. */
3705 delete fmtf;
3706 delete fmtl;
3707 delete fmtm;
3708 delete fmts;
3709
3710 return;
3711 }
3712 strf = fmtf->format(dt, strf);
3713 strl = fmtl->format(dt, strl);
3714 strm = fmtm->format(dt, strm);
3715 strs = fmts->format(dt, strs);
3716
3717
3718 logln("strm.charAt(10)=%04X wanted 0x20\n", strm.charAt(10));
3719 if (strm.charAt(10) != UChar(0x0020)) {
3720 errln((UnicodeString)"FAIL: Improper formatted date: " + strm );
3721 }
3722 logln("strs.charAt(10)=%04X wanted 0x20\n", strs.charAt(8));
3723 if (strs.charAt(10) != UChar(0x0020)) {
3724 errln((UnicodeString)"FAIL: Improper formatted date: " + strs);
3725 }
3726
3727 delete fmtf;
3728 delete fmtl;
3729 delete fmtm;
3730 delete fmts;
3731
3732 return;
3733 }
3734
3735 /**
3736 * Test DateFormat's parsing of default GMT variants. See ticket#6135
3737 */
TestGMTParsing()3738 void DateFormatTest::TestGMTParsing() {
3739 const char* DATA[] = {
3740 "HH:mm:ss Z",
3741
3742 // pattern, input, expected output (in quotes)
3743 "HH:mm:ss Z", "10:20:30 GMT+03:00", "10:20:30 +0300",
3744 "HH:mm:ss Z", "10:20:30 UT-02:00", "10:20:30 -0200",
3745 "HH:mm:ss Z", "10:20:30 GMT", "10:20:30 +0000",
3746 "HH:mm:ss vvvv", "10:20:30 UT+10:00", "10:20:30 +1000",
3747 "HH:mm:ss zzzz", "10:20:30 UTC", "10:20:30 +0000", // standalone "UTC"
3748 "ZZZZ HH:mm:ss", "UT 10:20:30", "10:20:30 +0000",
3749 "z HH:mm:ss", "UT+0130 10:20:30", "10:20:30 +0130",
3750 "z HH:mm:ss", "UTC+0130 10:20:30", "10:20:30 +0130",
3751 // Note: GMT-1100 no longer works because of the introduction of the short
3752 // localized GMT support. Previous implementation support this level of
3753 // leniency (no separator char in localized GMT format), but the new
3754 // implementation handles GMT-11 as the legitimate short localized GMT format
3755 // and stop at there. Otherwise, roundtrip would be broken.
3756 //"HH mm Z ss", "10 20 GMT-1100 30", "10:20:30 -1100",
3757 "HH mm Z ss", "10 20 GMT-11 30", "10:20:30 -1100",
3758 "HH:mm:ssZZZZZ", "14:25:45Z", "14:25:45 +0000",
3759 "HH:mm:ssZZZZZ", "15:00:00-08:00", "15:00:00 -0800",
3760 };
3761 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
3762 expectParse(DATA, DATA_len, Locale("en"));
3763 }
3764
3765 // Test case for localized GMT format parsing
3766 // with no delimitters in offset format (Chinese locale)
Test6880()3767 void DateFormatTest::Test6880() {
3768 UErrorCode status = U_ZERO_ERROR;
3769 UDate d1, d2, dp1, dp2, dexp1, dexp2;
3770 UnicodeString s1, s2;
3771
3772 TimeZone *tz = TimeZone::createTimeZone("Asia/Shanghai");
3773 GregorianCalendar gcal(*tz, status);
3774 if (failure(status, "construct GregorianCalendar", TRUE)) return;
3775
3776 gcal.clear();
3777 gcal.set(1900, UCAL_JULY, 1, 12, 00); // offset 8:05:43
3778 d1 = gcal.getTime(status);
3779
3780 gcal.clear();
3781 gcal.set(1950, UCAL_JULY, 1, 12, 00); // offset 8:00
3782 d2 = gcal.getTime(status);
3783
3784 gcal.clear();
3785 gcal.set(1970, UCAL_JANUARY, 1, 12, 00);
3786 dexp2 = gcal.getTime(status);
3787 dexp1 = dexp2 - (5*60 + 43)*1000; // subtract 5m43s
3788
3789 if (U_FAILURE(status)) {
3790 errln("FAIL: Gregorian calendar error");
3791 }
3792
3793 DateFormat *fmt = DateFormat::createTimeInstance(DateFormat::kFull, Locale("zh"));
3794 if (fmt == NULL) {
3795 dataerrln("Unable to create DateFormat. Got NULL.");
3796 return;
3797 }
3798 fmt->adoptTimeZone(tz);
3799
3800 fmt->format(d1, s1);
3801 fmt->format(d2, s2);
3802
3803 dp1 = fmt->parse(s1, status);
3804 dp2 = fmt->parse(s2, status);
3805
3806 if (U_FAILURE(status)) {
3807 errln("FAIL: Parse failure");
3808 }
3809
3810 if (dp1 != dexp1) {
3811 errln("FAIL: Failed to parse " + s1 + " parsed: " + dp1 + " expected: " + dexp1);
3812 }
3813 if (dp2 != dexp2) {
3814 errln("FAIL: Failed to parse " + s2 + " parsed: " + dp2 + " expected: " + dexp2);
3815 }
3816
3817 delete fmt;
3818 }
3819
3820 typedef struct {
3821 const char * localeStr;
3822 UBool lenient;
3823 UBool expectFail;
3824 UnicodeString datePattern;
3825 UnicodeString dateString;
3826 } NumAsStringItem;
3827
TestNumberAsStringParsing()3828 void DateFormatTest::TestNumberAsStringParsing()
3829 {
3830 const NumAsStringItem items[] = {
3831 // loc lenient fail? datePattern dateString
3832 { "", FALSE, TRUE, UnicodeString("y MMMM d HH:mm:ss"), UnicodeString("2009 7 14 08:43:57") },
3833 { "", TRUE, FALSE, UnicodeString("y MMMM d HH:mm:ss"), UnicodeString("2009 7 14 08:43:57") },
3834 { "en", FALSE, FALSE, UnicodeString("MMM d, y"), UnicodeString("Jul 14, 2009") },
3835 { "en", TRUE, FALSE, UnicodeString("MMM d, y"), UnicodeString("Jul 14, 2009") },
3836 { "en", FALSE, TRUE, UnicodeString("MMM d, y"), UnicodeString("7 14, 2009") },
3837 { "en", TRUE, FALSE, UnicodeString("MMM d, y"), UnicodeString("7 14, 2009") },
3838 { "ja", FALSE, FALSE, UnicodeString("yyyy/MM/dd"), UnicodeString("2009/07/14") },
3839 { "ja", TRUE, FALSE, UnicodeString("yyyy/MM/dd"), UnicodeString("2009/07/14") },
3840 //{ "ja", FALSE, FALSE, UnicodeString("yyyy/MMMMM/d"), UnicodeString("2009/7/14") }, // #8860 covers test failure
3841 { "ja", TRUE, FALSE, UnicodeString("yyyy/MMMMM/d"), UnicodeString("2009/7/14") },
3842 { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3843 { "ja", TRUE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3844 { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3845 { "ja", TRUE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") }, // #8820 fixes test failure
3846 { "ko", FALSE, FALSE, UnicodeString("yyyy. M. d."), UnicodeString("2009. 7. 14.") },
3847 { "ko", TRUE, FALSE, UnicodeString("yyyy. M. d."), UnicodeString("2009. 7. 14.") },
3848 { "ko", FALSE, FALSE, UnicodeString("yyyy. MMMMM d."), CharsToUnicodeString("2009. 7\\uC6D4 14.") },
3849 { "ko", TRUE, FALSE, UnicodeString("yyyy. MMMMM d."), CharsToUnicodeString("2009. 7\\uC6D4 14.") }, // #8820 fixes test failure
3850 { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3851 { "ko", TRUE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3852 { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3853 { "ko", TRUE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") }, // #8820 fixes test failure
3854 { NULL, FALSE, FALSE, UnicodeString(""), UnicodeString("") }
3855 };
3856 const NumAsStringItem * itemPtr;
3857 for (itemPtr = items; itemPtr->localeStr != NULL; itemPtr++ ) {
3858 Locale locale = Locale::createFromName(itemPtr->localeStr);
3859 UErrorCode status = U_ZERO_ERROR;
3860 SimpleDateFormat *formatter = new SimpleDateFormat(itemPtr->datePattern, locale, status);
3861 if (formatter == NULL || U_FAILURE(status)) {
3862 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3863 return;
3864 }
3865
3866 formatter->setLenient(itemPtr->lenient);
3867 formatter->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->lenient, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->lenient, status);
3868 UDate date1 = formatter->parse(itemPtr->dateString, status);
3869 if (U_FAILURE(status)) {
3870 if (!itemPtr->expectFail) {
3871 errln("FAIL, err when expected success: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3872 ": using pattern \"" + itemPtr->datePattern + "\", could not parse \"" + itemPtr->dateString + "\"; err: " + u_errorName(status) );
3873 }
3874 } else if (itemPtr->expectFail) {
3875 errln("FAIL, expected err but got none: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3876 ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\"." );
3877 } else if (!itemPtr->lenient) {
3878 UnicodeString formatted;
3879 formatter->format(date1, formatted);
3880 if (formatted != itemPtr->dateString) {
3881 errln("FAIL, mismatch formatting parsed date: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3882 ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\", formatted result \"" + formatted + "\".");
3883 }
3884 }
3885
3886 delete formatter;
3887 }
3888 }
3889
TestISOEra()3890 void DateFormatTest::TestISOEra() {
3891
3892 const char* data[] = {
3893 // input, output
3894 "BC 4004-10-23T07:00:00Z", "BC 4004-10-23T07:00:00Z",
3895 "AD 4004-10-23T07:00:00Z", "AD 4004-10-23T07:00:00Z",
3896 "-4004-10-23T07:00:00Z" , "BC 4005-10-23T07:00:00Z",
3897 "4004-10-23T07:00:00Z" , "AD 4004-10-23T07:00:00Z",
3898 };
3899
3900 int32_t numData = 8;
3901
3902 UErrorCode status = U_ZERO_ERROR;
3903
3904 // create formatter
3905 SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("GGG yyyy-MM-dd'T'HH:mm:ss'Z"), status);
3906 failure(status, "new SimpleDateFormat", TRUE);
3907 if (status == U_MISSING_RESOURCE_ERROR) {
3908 if (fmt1 != NULL) {
3909 delete fmt1;
3910 }
3911 return;
3912 }
3913 for(int i=0; i < numData; i+=2) {
3914 // create input string
3915 UnicodeString in = data[i];
3916
3917 // parse string to date
3918 UDate dt1 = fmt1->parse(in, status);
3919 failure(status, "fmt->parse", TRUE);
3920
3921 // format date back to string
3922 UnicodeString out;
3923 out = fmt1->format(dt1, out);
3924 logln(out);
3925
3926 // check that roundtrip worked as expected
3927 UnicodeString expected = data[i+1];
3928 if (out != expected) {
3929 dataerrln((UnicodeString)"FAIL: " + in + " -> " + out + " expected -> " + expected);
3930 }
3931 }
3932
3933 delete fmt1;
3934 }
TestFormalChineseDate()3935 void DateFormatTest::TestFormalChineseDate() {
3936
3937 UErrorCode status = U_ZERO_ERROR;
3938 UnicodeString pattern ("y\\u5e74M\\u6708d\\u65e5", -1, US_INV );
3939 pattern = pattern.unescape();
3940 UnicodeString override ("y=hanidec;M=hans;d=hans", -1, US_INV );
3941
3942 // create formatter
3943 SimpleDateFormat *sdf = new SimpleDateFormat(pattern,override,Locale::getChina(),status);
3944 if (failure(status, "new SimpleDateFormat with override", TRUE)) {
3945 return;
3946 }
3947
3948 UDate thedate = date(2009-1900, UCAL_JULY, 28);
3949 FieldPosition pos(FieldPosition::DONT_CARE);
3950 UnicodeString result;
3951 sdf->format(thedate,result,pos);
3952
3953 UnicodeString expected = "\\u4e8c\\u3007\\u3007\\u4e5d\\u5e74\\u4e03\\u6708\\u4e8c\\u5341\\u516b\\u65e5";
3954 expected = expected.unescape();
3955 if (result != expected) {
3956 dataerrln((UnicodeString)"FAIL: -> " + result + " expected -> " + expected);
3957 }
3958
3959 UDate parsedate = sdf->parse(expected,status);
3960 if ( parsedate != thedate ) {
3961 UnicodeString pat1 ("yyyy-MM-dd'T'HH:mm:ss'Z'", -1, US_INV );
3962 SimpleDateFormat *usf = new SimpleDateFormat(pat1,Locale::getEnglish(),status);
3963 UnicodeString parsedres,expres;
3964 usf->format(parsedate,parsedres,pos);
3965 usf->format(thedate,expres,pos);
3966 dataerrln((UnicodeString)"FAIL: parsed -> " + parsedres + " expected -> " + expres);
3967 delete usf;
3968 }
3969 delete sdf;
3970 }
3971
3972 // Test case for #8675
3973 // Incorrect parse offset with stand alone GMT string on 2nd or later iteration.
TestStandAloneGMTParse()3974 void DateFormatTest::TestStandAloneGMTParse() {
3975 UErrorCode status = U_ZERO_ERROR;
3976 SimpleDateFormat *sdf = new SimpleDateFormat("ZZZZ", Locale(""), status);
3977
3978 if (U_SUCCESS(status)) {
3979
3980 UnicodeString inText("GMT$$$");
3981 for (int32_t i = 0; i < 10; i++) {
3982 ParsePosition pos(0);
3983 sdf->parse(inText, pos);
3984 if (pos.getIndex() != 3) {
3985 errln((UnicodeString)"FAIL: Incorrect output parse position: actual=" + pos.getIndex() + " expected=3");
3986 }
3987 }
3988
3989 delete sdf;
3990 } else {
3991 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3992 }
3993 }
3994
TestParsePosition()3995 void DateFormatTest::TestParsePosition() {
3996 const char* TestData[][4] = {
3997 // {<pattern>, <lead>, <date string>, <trail>}
3998 {"yyyy-MM-dd HH:mm:ssZ", "", "2010-01-10 12:30:00+0500", ""},
3999 {"yyyy-MM-dd HH:mm:ss ZZZZ", "", "2010-01-10 12:30:00 GMT+05:00", ""},
4000 {"Z HH:mm:ss", "", "-0100 13:20:30", ""},
4001 {"y-M-d Z", "", "2011-8-25 -0400", " Foo"},
4002 {"y/M/d H:mm:ss z", "", "2011/7/1 12:34:00 PDT", ""},
4003 {"y/M/d H:mm:ss z", "+123", "2011/7/1 12:34:00 PDT", " PST"},
4004 {"vvvv a h:mm:ss", "", "Pacific Time AM 10:21:45", ""},
4005 {"HH:mm v M/d", "111", "14:15 PT 8/10", " 12345"},
4006 {"'time zone:' VVVV 'date:' yyyy-MM-dd", "xxxx", "time zone: Los Angeles Time date: 2010-02-25", "xxxx"},
4007 {"yG", "", "2012AD", ""},
4008 {"yG", "", "2012", "x"},
4009 {0, 0, 0, 0},
4010 };
4011
4012 for (int32_t i = 0; TestData[i][0]; i++) {
4013 UErrorCode status = U_ZERO_ERROR;
4014 SimpleDateFormat *sdf = new SimpleDateFormat(UnicodeString(TestData[i][0]), status);
4015 if (failure(status, "new SimpleDateFormat", TRUE)) return;
4016
4017 int32_t startPos, resPos;
4018
4019 // lead text
4020 UnicodeString input(TestData[i][1]);
4021 startPos = input.length();
4022
4023 // date string
4024 input += TestData[i][2];
4025 resPos = input.length();
4026
4027 // trail text
4028 input += TestData[i][3];
4029
4030 ParsePosition pos(startPos);
4031 //UDate d = sdf->parse(input, pos);
4032 (void)sdf->parse(input, pos);
4033
4034 if (pos.getIndex() != resPos) {
4035 errln(UnicodeString("FAIL: Parsing [") + input + "] with pattern [" + TestData[i][0] + "] returns position - "
4036 + pos.getIndex() + ", expected - " + resPos);
4037 }
4038
4039 delete sdf;
4040 }
4041 }
4042
4043
4044 typedef struct {
4045 int32_t era;
4046 int32_t year;
4047 int32_t month; // 1-based
4048 int32_t isLeapMonth;
4049 int32_t day;
4050 } ChineseCalTestDate;
4051
4052 #define NUM_TEST_DATES 3
4053
4054 typedef struct {
4055 const char * locale;
4056 int32_t style; // <0 => custom
4057 UnicodeString dateString[NUM_TEST_DATES];
4058 } MonthPatternItem;
4059
TestMonthPatterns()4060 void DateFormatTest::TestMonthPatterns()
4061 {
4062 const ChineseCalTestDate dates[NUM_TEST_DATES] = {
4063 // era yr mo lp da
4064 { 78, 29, 4, 0, 2 }, // (in chinese era 78) gregorian 2012-4-22
4065 { 78, 29, 4, 1, 2 }, // (in chinese era 78) gregorian 2012-5-22
4066 { 78, 29, 5, 0, 2 }, // (in chinese era 78) gregorian 2012-6-20
4067 };
4068
4069 const MonthPatternItem items[] = {
4070 // locale date style; expected formats for the 3 dates above
4071 { "root@calendar=chinese", DateFormat::kLong, { UnicodeString("2012(ren-chen) M04 2"), UnicodeString("2012(ren-chen) M04bis 2"), UnicodeString("2012(ren-chen) M05 2") } },
4072 { "root@calendar=chinese", DateFormat::kShort, { UnicodeString("2012-04-02"), UnicodeString("2012-04bis-02"), UnicodeString("2012-05-02") } },
4073 { "root@calendar=chinese", -1, { UnicodeString("29-4-2"), UnicodeString("29-4bis-2"), UnicodeString("29-5-2") } },
4074 { "root@calendar=chinese", -2, { UnicodeString("78x29-4-2"), UnicodeString("78x29-4bis-2"), UnicodeString("78x29-5-2") } },
4075 { "root@calendar=chinese", -3, { UnicodeString("ren-chen-4-2"), UnicodeString("ren-chen-4bis-2"), UnicodeString("ren-chen-5-2") } },
4076 { "root@calendar=chinese", -4, { UnicodeString("ren-chen M04 2"), UnicodeString("ren-chen M04bis 2"), UnicodeString("ren-chen M05 2") } },
4077 { "en@calendar=gregorian", -3, { UnicodeString("2012-4-22"), UnicodeString("2012-5-22"), UnicodeString("2012-6-20") } },
4078 { "en@calendar=chinese", DateFormat::kLong, { UnicodeString("Fourth Month 2, 2012(ren-chen)"), UnicodeString("Fourth Monthbis 2, 2012(ren-chen)"), UnicodeString("Fifth Month 2, 2012(ren-chen)") } },
4079 { "en@calendar=chinese", DateFormat::kShort, { UnicodeString("4/2/2012"), UnicodeString("4bis/2/2012"), UnicodeString("5/2/2012") } },
4080 { "zh@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4081 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u95F0\\u56DB\\u6708\\u521D\\u4E8C"),
4082 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4083 { "zh@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("2012/4/2"),
4084 CharsToUnicodeString("2012/\\u95F04/2"),
4085 CharsToUnicodeString("2012/5/2") } },
4086 { "zh@calendar=chinese", -3, { CharsToUnicodeString("\\u58EC\\u8FB0-4-2"),
4087 CharsToUnicodeString("\\u58EC\\u8FB0-\\u95F04-2"),
4088 CharsToUnicodeString("\\u58EC\\u8FB0-5-2") } },
4089 { "zh@calendar=chinese", -4, { CharsToUnicodeString("\\u58EC\\u8FB0 \\u56DB\\u6708 2"),
4090 CharsToUnicodeString("\\u58EC\\u8FB0 \\u95F0\\u56DB\\u6708 2"),
4091 CharsToUnicodeString("\\u58EC\\u8FB0 \\u4E94\\u6708 2") } },
4092 { "zh_Hant@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4093 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u958F\\u56DB\\u6708\\u521D\\u4E8C"),
4094 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4095 { "zh_Hant@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("2012/4/2"),
4096 CharsToUnicodeString("2012/\\u958F4/2"),
4097 CharsToUnicodeString("2012/5/2") } },
4098 { "fr@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2 s\\u00ECyu\\u00E8 ren-chen"),
4099 CharsToUnicodeString("2 s\\u00ECyu\\u00E8bis ren-chen"),
4100 CharsToUnicodeString("2 w\\u01D4yu\\u00E8 ren-chen") } },
4101 { "fr@calendar=chinese", DateFormat::kShort, { UnicodeString("2/4/29"), UnicodeString("2/4bis/29"), UnicodeString("2/5/29") } },
4102 { "en@calendar=dangi", DateFormat::kLong, { UnicodeString("Third Monthbis 2, 2012(ren-chen)"), UnicodeString("Fourth Month 2, 2012(ren-chen)"), UnicodeString("Fifth Month 1, 2012(ren-chen)") } },
4103 { "en@calendar=dangi", DateFormat::kShort, { UnicodeString("3bis/2/2012"), UnicodeString("4/2/2012"), UnicodeString("5/1/2012") } },
4104 { "en@calendar=dangi", -2, { UnicodeString("78x29-3bis-2"), UnicodeString("78x29-4-2"), UnicodeString("78x29-5-1") } },
4105 { "ko@calendar=dangi", DateFormat::kLong, { CharsToUnicodeString("\\uC784\\uC9C4\\uB144 \\uC7243\\uC6D4 2\\uC77C"),
4106 CharsToUnicodeString("\\uC784\\uC9C4\\uB144 4\\uC6D4 2\\uC77C"),
4107 CharsToUnicodeString("\\uC784\\uC9C4\\uB144 5\\uC6D4 1\\uC77C") } },
4108 { "ko@calendar=dangi", DateFormat::kShort, { CharsToUnicodeString("29. \\uC7243. 2."),
4109 CharsToUnicodeString("29. 4. 2."),
4110 CharsToUnicodeString("29. 5. 1.") } },
4111 // terminator
4112 { NULL, 0, { UnicodeString(""), UnicodeString(""), UnicodeString("") } }
4113 };
4114
4115 //. style: -1 -2 -3 -4
4116 const UnicodeString customPatterns[] = { "y-Ml-d", "G'x'y-Ml-d", "U-M-d", "U MMM d" }; // like old root pattern, using 'l'
4117
4118 UErrorCode status = U_ZERO_ERROR;
4119 Locale rootChineseCalLocale = Locale::createFromName("root@calendar=chinese");
4120 Calendar * rootChineseCalendar = Calendar::createInstance(rootChineseCalLocale, status);
4121 if (U_SUCCESS(status)) {
4122 const MonthPatternItem * itemPtr;
4123 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4124 Locale locale = Locale::createFromName(itemPtr->locale);
4125 DateFormat * dmft = (itemPtr->style >= 0)?
4126 DateFormat::createDateInstance((DateFormat::EStyle)itemPtr->style, locale):
4127 new SimpleDateFormat(customPatterns[-itemPtr->style - 1], locale, status);
4128 if ( dmft != NULL ) {
4129 if (U_SUCCESS(status)) {
4130 const ChineseCalTestDate * datePtr = dates;
4131 int32_t idate;
4132 for (idate = 0; idate < NUM_TEST_DATES; idate++, datePtr++) {
4133 rootChineseCalendar->clear();
4134 rootChineseCalendar->set(UCAL_ERA, datePtr->era);
4135 rootChineseCalendar->set(datePtr->year, datePtr->month-1, datePtr->day);
4136 rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, datePtr->isLeapMonth);
4137 UnicodeString result;
4138 FieldPosition fpos(FieldPosition::DONT_CARE);
4139 dmft->format(*rootChineseCalendar, result, fpos);
4140 if ( result.compare(itemPtr->dateString[idate]) != 0 ) {
4141 errln( UnicodeString("FAIL: Chinese calendar format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4142 ", expected \"" + itemPtr->dateString[idate] + "\", got \"" + result + "\"");
4143 } else {
4144 // formatted OK, try parse
4145 ParsePosition ppos(0);
4146 // ensure we are really parsing the fields we should be
4147 rootChineseCalendar->set(UCAL_YEAR, 1);
4148 rootChineseCalendar->set(UCAL_MONTH, 0);
4149 rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, 0);
4150 rootChineseCalendar->set(UCAL_DATE, 1);
4151 //
4152 dmft->parse(result, *rootChineseCalendar, ppos);
4153 int32_t year = rootChineseCalendar->get(UCAL_YEAR, status);
4154 int32_t month = rootChineseCalendar->get(UCAL_MONTH, status) + 1;
4155 int32_t isLeapMonth = rootChineseCalendar->get(UCAL_IS_LEAP_MONTH, status);
4156 int32_t day = rootChineseCalendar->get(UCAL_DATE, status);
4157 if ( ppos.getIndex() < result.length() || year != datePtr->year || month != datePtr->month || isLeapMonth != datePtr->isLeapMonth || day != datePtr->day ) {
4158 errln( UnicodeString("FAIL: Chinese calendar parse for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4159 ", string \"" + result + "\", expected " + datePtr->year +"-"+datePtr->month+"("+datePtr->isLeapMonth+")-"+datePtr->day + ", got pos " +
4160 ppos.getIndex() + " " + year +"-"+month+"("+isLeapMonth+")-"+day);
4161 }
4162 }
4163 }
4164 } else {
4165 dataerrln("Error creating SimpleDateFormat for Chinese calendar- %s", u_errorName(status));
4166 }
4167 delete dmft;
4168 } else {
4169 dataerrln("FAIL: Unable to create DateFormat for Chinese calendar- %s", u_errorName(status));
4170 }
4171 }
4172 delete rootChineseCalendar;
4173 } else {
4174 errln(UnicodeString("FAIL: Unable to create Calendar for root@calendar=chinese"));
4175 }
4176 }
4177
4178 typedef struct {
4179 const char * locale;
4180 UnicodeString pattern;
4181 UDisplayContext capitalizationContext;
4182 UnicodeString expectedFormat;
4183 } TestContextItem;
4184
TestContext()4185 void DateFormatTest::TestContext()
4186 {
4187 const UDate july022008 = 1215000001979.0;
4188 const TestContextItem items[] = {
4189 //locale pattern capitalizationContext expected formatted date
4190 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_NONE, UnicodeString("juillet 2008") },
4191 #if !UCONFIG_NO_BREAK_ITERATION
4192 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UnicodeString("juillet 2008") },
4193 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, UnicodeString("Juillet 2008") },
4194 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, UnicodeString("juillet 2008") },
4195 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE, UnicodeString("Juillet 2008") },
4196 #endif
4197 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_NONE, CharsToUnicodeString("\\u010Dervenec 2008") },
4198 #if !UCONFIG_NO_BREAK_ITERATION
4199 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, CharsToUnicodeString("\\u010Dervenec 2008") },
4200 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, CharsToUnicodeString("\\u010Cervenec 2008") },
4201 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, CharsToUnicodeString("\\u010Cervenec 2008") },
4202 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE, CharsToUnicodeString("\\u010Dervenec 2008") },
4203 #endif
4204 // terminator
4205 { NULL, UnicodeString(""), (UDisplayContext)0, UnicodeString("") }
4206 };
4207 UErrorCode status = U_ZERO_ERROR;
4208 Calendar* cal = Calendar::createInstance(status);
4209 if (U_FAILURE(status)) {
4210 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4211 } else {
4212 cal->setTime(july022008, status);
4213 const TestContextItem * itemPtr;
4214 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4215 Locale locale = Locale::createFromName(itemPtr->locale);
4216 status = U_ZERO_ERROR;
4217 SimpleDateFormat * sdmft = new SimpleDateFormat(itemPtr->pattern, locale, status);
4218 if (U_FAILURE(status)) {
4219 dataerrln(UnicodeString("FAIL: Unable to create SimpleDateFormat for specified pattern with locale ") + UnicodeString(itemPtr->locale));
4220 } else {
4221 sdmft->setContext(itemPtr->capitalizationContext, status);
4222 UnicodeString result;
4223 FieldPosition pos(FieldPosition::DONT_CARE);
4224 sdmft->format(*cal, result, pos);
4225 if (result.compare(itemPtr->expectedFormat) != 0) {
4226 errln(UnicodeString("FAIL: format for locale ") + UnicodeString(itemPtr->locale) +
4227 ", status " + (int)status +
4228 ", capitalizationContext " + (int)itemPtr->capitalizationContext +
4229 ", expected " + itemPtr->expectedFormat + ", got " + result);
4230 }
4231 }
4232 if (sdmft) {
4233 delete sdmft;
4234 }
4235 }
4236 }
4237 if (cal) {
4238 delete cal;
4239 }
4240 }
4241
4242 // test item for a particular locale + calendar and date format
4243 typedef struct {
4244 int32_t era;
4245 int32_t year;
4246 int32_t month;
4247 int32_t day;
4248 int32_t hour;
4249 int32_t minute;
4250 UnicodeString formattedDate;
4251 } CalAndFmtTestItem;
4252
4253 // test item giving locale + calendar, date format, and CalAndFmtTestItems
4254 typedef struct {
4255 const char * locale; // with calendar
4256 DateFormat::EStyle style;
4257 UnicodeString pattern; // ignored unless style == DateFormat::kNone
4258 const CalAndFmtTestItem *caftItems;
4259 } TestNonGregoItem;
4260
TestNonGregoFmtParse()4261 void DateFormatTest::TestNonGregoFmtParse()
4262 {
4263 // test items for he@calendar=hebrew, long date format
4264 const CalAndFmtTestItem cafti_he_hebrew_long[] = {
4265 { 0, 4999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05D3\\u05F3\\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4266 { 0, 5100, 0, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05E7\\u05F3") },
4267 { 0, 5774, 5, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05D0\\u05D3\\u05E8 \\u05D0\\u05F3 \\u05EA\\u05E9\\u05E2\\u05F4\\u05D3") },
4268 { 0, 5999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4269 { 0, 6100, 0, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05D5\\u05F3\\u05E7\\u05F3") },
4270 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4271 };
4272 const CalAndFmtTestItem cafti_zh_chinese_custU[] = {
4273 { 78, 31, 0, 1, 12, 0, CharsToUnicodeString("2014\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4274 { 77, 31, 0, 1, 12, 0, CharsToUnicodeString("1954\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4275 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4276 };
4277 const CalAndFmtTestItem cafti_zh_chinese_custNoU[] = {
4278 { 78, 31, 0, 1, 12, 0, CharsToUnicodeString("2014\\u5E74\\u6B63\\u67081") },
4279 { 77, 31, 0, 1, 12, 0, CharsToUnicodeString("1954\\u5E74\\u6B63\\u67081") },
4280 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4281 };
4282 const CalAndFmtTestItem cafti_ja_japanese_custGy[] = {
4283 {235, 26, 2, 5, 12, 0, CharsToUnicodeString("2014(\\u5E73\\u621026)\\u5E743\\u67085\\u65E5") },
4284 {234, 60, 2, 5, 12, 0, CharsToUnicodeString("1985(\\u662D\\u548C60)\\u5E743\\u67085\\u65E5") },
4285 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4286 };
4287 const CalAndFmtTestItem cafti_ja_japanese_custNoGy[] = {
4288 {235, 26, 2, 5, 12, 0, CharsToUnicodeString("2014\\u5E743\\u67085\\u65E5") },
4289 {234, 60, 2, 5, 12, 0, CharsToUnicodeString("1985\\u5E743\\u67085\\u65E5") },
4290 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4291 };
4292 const CalAndFmtTestItem cafti_en_islamic_cust[] = {
4293 { 0, 1384, 0, 1, 12, 0, UnicodeString("1 Muh. 1384 AH, 1964") },
4294 { 0, 1436, 0, 1, 12, 0, UnicodeString("1 Muh. 1436 AH, 2014") },
4295 { 0, 1487, 0, 1, 12, 0, UnicodeString("1 Muh. 1487 AH, 2064") },
4296 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4297 };
4298 // overal test items
4299 const TestNonGregoItem items[] = {
4300 { "he@calendar=hebrew", DateFormat::kLong, UnicodeString(""), cafti_he_hebrew_long },
4301 { "zh@calendar=chinese", DateFormat::kNone, CharsToUnicodeString("rU\\u5E74MMMd"), cafti_zh_chinese_custU },
4302 { "zh@calendar=chinese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74MMMd"), cafti_zh_chinese_custNoU },
4303 { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r(Gy)\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custGy },
4304 { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custNoGy },
4305 { "en@calendar=islamic", DateFormat::kNone, UnicodeString("d MMM y G, r"), cafti_en_islamic_cust },
4306 { NULL, DateFormat::kNone, UnicodeString(""), NULL } // terminator
4307 };
4308 const TestNonGregoItem * itemPtr;
4309 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++) {
4310 Locale locale = Locale::createFromName(itemPtr->locale);
4311 DateFormat * dfmt = NULL;
4312 UErrorCode status = U_ZERO_ERROR;
4313 if (itemPtr->style != DateFormat::kNone) {
4314 dfmt = DateFormat::createDateInstance(itemPtr->style, locale);
4315 } else {
4316 dfmt = new SimpleDateFormat(itemPtr->pattern, locale, status);
4317 }
4318 if (U_FAILURE(status)) {
4319 dataerrln("new SimpleDateFormat fails for locale %s", itemPtr->locale);
4320 } else if (dfmt == NULL) {
4321 dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->locale);
4322 } else {
4323 Calendar * cal = (dfmt->getCalendar())->clone();
4324 if (cal == NULL) {
4325 dataerrln("(DateFormat::getCalendar)->clone() fails for locale %s", itemPtr->locale);
4326 } else {
4327 const CalAndFmtTestItem * caftItemPtr;
4328 for (caftItemPtr = itemPtr->caftItems; caftItemPtr->year != 0; caftItemPtr++) {
4329 cal->clear();
4330 cal->set(UCAL_ERA, caftItemPtr->era);
4331 cal->set(UCAL_YEAR, caftItemPtr->year);
4332 cal->set(UCAL_MONTH, caftItemPtr->month);
4333 cal->set(UCAL_DATE, caftItemPtr->day);
4334 cal->set(UCAL_HOUR_OF_DAY, caftItemPtr->hour);
4335 cal->set(UCAL_MINUTE, caftItemPtr->minute);
4336 UnicodeString result;
4337 FieldPosition fpos(FieldPosition::DONT_CARE);
4338 dfmt->format(*cal, result, fpos);
4339 if ( result.compare(caftItemPtr->formattedDate) != 0 ) {
4340 errln( UnicodeString("FAIL: date format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4341 ", expected \"" + caftItemPtr->formattedDate + "\", got \"" + result + "\"");
4342 } else {
4343 // formatted OK, try parse
4344 ParsePosition ppos(0);
4345 dfmt->parse(result, *cal, ppos);
4346 status = U_ZERO_ERROR;
4347 int32_t era = cal->get(UCAL_ERA, status);
4348 int32_t year = cal->get(UCAL_YEAR, status);
4349 int32_t month = cal->get(UCAL_MONTH, status);
4350 int32_t day = cal->get(UCAL_DATE, status);
4351 if ( U_FAILURE(status) || ppos.getIndex() < result.length() || era != caftItemPtr->era ||
4352 year != caftItemPtr->year || month != caftItemPtr->month || day != caftItemPtr->day ) {
4353 errln( UnicodeString("FAIL: date parse for locale ") + UnicodeString(itemPtr->locale) +
4354 ", style " + itemPtr->style + ", string \"" + result + "\", expected " +
4355 caftItemPtr->era +":"+caftItemPtr->year +"-"+caftItemPtr->month+"-"+caftItemPtr->day + ", got pos " +
4356 ppos.getIndex() + " " + year +"-"+month+"-"+day + " status " + UnicodeString(u_errorName(status)) );
4357 }
4358 }
4359 }
4360 delete cal;
4361 }
4362 delete dfmt;
4363 }
4364 }
4365 }
4366
4367 typedef struct {
4368 const char* localeID;
4369 DateFormat::EStyle style;
4370 UnicodeString expectPattern;
4371 UnicodeString expectFormat;
4372 } TestFmtWithNumSysItem;
4373 enum { kBBufMax = 128 };
TestFormatsWithNumberSystems()4374 void DateFormatTest::TestFormatsWithNumberSystems()
4375 {
4376 LocalPointer<TimeZone> zone(TimeZone::createTimeZone(UnicodeString("UTC")));
4377 const UDate date = 1451556000000.0; // for UTC: grego 31-Dec-2015 10 AM, hebrew 19 tevet 5776, chinese yi-wei 11mo 21day
4378 const TestFmtWithNumSysItem items[] = {
4379 { "haw@calendar=gregorian", DateFormat::kShort, UnicodeString("d/M/yy"), UnicodeString("31/xii/15") },
4380 { "he@calendar=hebrew", DateFormat::kLong, CharsToUnicodeString("d \\u05D1MMMM y"), CharsToUnicodeString("\\u05D9\\u05F4\\u05D8 \\u05D1\\u05D8\\u05D1\\u05EA \\u05EA\\u05E9\\u05E2\\u05F4\\u05D5") },
4381 { "zh@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u5341\\u4E00\\u6708\\u5EFF\\u4E00") },
4382 { "zh_Hant@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u51AC\\u6708\\u5EFF\\u4E00") },
4383 { "ja@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("U\\u5E74MMMd\\u65E5"), CharsToUnicodeString("\\u4E59\\u672A\\u5E74\\u5341\\u4E00\\u6708\\u4E8C\\u4E00\\u65E5") },
4384 { NULL, DateFormat::kNone, UnicodeString(""), UnicodeString("") },
4385 };
4386 const TestFmtWithNumSysItem * itemPtr;
4387 for (itemPtr = items; itemPtr->localeID != NULL; itemPtr++) {
4388 char bExpected[kBBufMax];
4389 char bResult[kBBufMax];
4390 UErrorCode status = U_ZERO_ERROR;
4391 Locale locale = Locale::createFromName(itemPtr->localeID);
4392 LocalPointer<Calendar> cal(Calendar::createInstance(zone.orphan(), locale, status));
4393 if (U_FAILURE(status)) {
4394 dataerrln("Calendar::createInstance fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4395 continue;
4396 }
4397 cal->setTime(date, status);
4398 if (U_FAILURE(status)) {
4399 dataerrln("Calendar::setTime fails for locale %s, date %.1f, status %s", itemPtr->localeID, date, u_errorName(status));
4400 continue;
4401 }
4402 LocalPointer<SimpleDateFormat> sdfmt(static_cast<SimpleDateFormat *>(DateFormat::createDateInstance(itemPtr->style, locale)));
4403 if (sdfmt.isNull()) {
4404 dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->localeID);
4405 continue;
4406 }
4407 UnicodeString getFormat;
4408 sdfmt->format(*(cal.getAlias()), getFormat, NULL, status);
4409 if (U_FAILURE(status)) {
4410 errln("DateFormat::format fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4411 continue;
4412 }
4413 if (getFormat.compare(itemPtr->expectFormat) != 0) {
4414 itemPtr->expectFormat.extract(0, itemPtr->expectFormat.length(), bExpected, kBBufMax);
4415 getFormat.extract(0, getFormat.length(), bResult, kBBufMax);
4416 errln("DateFormat::format for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4417 }
4418 UnicodeString getPattern;
4419 sdfmt->toPattern(getPattern);
4420 if (getPattern.compare(itemPtr->expectPattern) != 0) {
4421 itemPtr->expectPattern.extract(0, itemPtr->expectPattern.length(), bExpected, kBBufMax);
4422 getPattern.extract(0, getPattern.length(), bResult, kBBufMax);
4423 errln("DateFormat::toPattern() for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4424 }
4425 }
4426 }
4427
4428 static const UDate TEST_DATE = 1326585600000.; // 2012-jan-15
4429
TestDotAndAtLeniency()4430 void DateFormatTest::TestDotAndAtLeniency() {
4431 // Test for date/time parsing regression with CLDR 22.1/ICU 50 pattern strings.
4432 // For details see http://bugs.icu-project.org/trac/ticket/9789
4433 static const char *locales[] = { "en", "fr" };
4434 for (int32_t i = 0; i < UPRV_LENGTHOF(locales); ++i) {
4435 Locale locale(locales[i]);
4436
4437 for (DateFormat::EStyle dateStyle = DateFormat::FULL; dateStyle <= DateFormat::SHORT;
4438 dateStyle = static_cast<DateFormat::EStyle>(dateStyle + 1)) {
4439 LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance(dateStyle, locale));
4440
4441 for (DateFormat::EStyle timeStyle = DateFormat::FULL; timeStyle <= DateFormat::SHORT;
4442 timeStyle = static_cast<DateFormat::EStyle>(timeStyle + 1)) {
4443 LocalPointer<DateFormat> format(DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale));
4444 LocalPointer<DateFormat> timeFormat(DateFormat::createTimeInstance(timeStyle, locale));
4445 UnicodeString formattedString;
4446 if (format.isNull()) {
4447 dataerrln("Unable to create DateFormat");
4448 continue;
4449 }
4450 format->format(TEST_DATE, formattedString);
4451
4452 if (!showParse(*format, formattedString)) {
4453 errln(UnicodeString(" with date-time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4454 }
4455
4456 UnicodeString ds, ts;
4457 formattedString = dateFormat->format(TEST_DATE, ds) + " " + timeFormat->format(TEST_DATE, ts);
4458 if (!showParse(*format, formattedString)) {
4459 errln(UnicodeString(" with date sp sp time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4460 }
4461 if (formattedString.indexOf("n ") >= 0) { // will add "." after the end of text ending in 'n', like Jan.
4462 UnicodeString plusDot(formattedString);
4463 plusDot.findAndReplace("n ", "n. ").append(".");
4464 if (!showParse(*format, plusDot)) {
4465 errln(UnicodeString(" with date plus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4466 }
4467 }
4468 if (formattedString.indexOf(". ") >= 0) { // will subtract "." at the end of strings.
4469 UnicodeString minusDot(formattedString);
4470 minusDot.findAndReplace(". ", " ");
4471 if (!showParse(*format, minusDot)) {
4472 errln(UnicodeString(" with date minus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4473 }
4474 }
4475 }
4476 }
4477 }
4478 }
4479
showParse(DateFormat & format,const UnicodeString & formattedString)4480 UBool DateFormatTest::showParse(DateFormat &format, const UnicodeString &formattedString) {
4481 ParsePosition parsePosition;
4482 UDate parsed = format.parse(formattedString, parsePosition);
4483 UBool ok = TEST_DATE == parsed && parsePosition.getIndex() == formattedString.length();
4484 UnicodeString pattern;
4485 static_cast<SimpleDateFormat &>(format).toPattern(pattern);
4486 if (ok) {
4487 logln(pattern + " parsed: " + formattedString);
4488 } else {
4489 errln(pattern + " fails to parse: " + formattedString);
4490 }
4491 return ok;
4492 }
4493
4494
4495 typedef struct {
4496 const char * locale;
4497 UBool leniency;
4498 UnicodeString parseString;
4499 UnicodeString pattern;
4500 UnicodeString expectedResult; // empty string indicates expected error
4501 } TestDateFormatLeniencyItem;
4502
TestDateFormatLeniency()4503 void DateFormatTest::TestDateFormatLeniency() {
4504 // For details see http://bugs.icu-project.org/trac/ticket/10261
4505
4506 const UDate july022008 = 1215000001979.0;
4507 const TestDateFormatLeniencyItem items[] = {
4508 //locale leniency parse String pattern expected result
4509 { "en", true, UnicodeString("2008-07 02"), UnicodeString("yyyy-LLLL dd"), UnicodeString("2008-July 02") },
4510 { "en", false, UnicodeString("2008-07 02"), UnicodeString("yyyy-LLLL dd"), UnicodeString("") },
4511 { "en", true, UnicodeString("2008-Jan 02"), UnicodeString("yyyy-LLL. dd"), UnicodeString("2008-Jan. 02") },
4512 { "en", false, UnicodeString("2008-Jan 02"), UnicodeString("yyyy-LLL. dd"), UnicodeString("") },
4513 { "en", true, UnicodeString("2008-Jan--02"), UnicodeString("yyyy-MMM' -- 'dd"), UnicodeString("2008-Jan -- 02") },
4514 { "en", false, UnicodeString("2008-Jan--02"), UnicodeString("yyyy-MMM' -- 'dd"), UnicodeString("") },
4515 // terminator
4516 { NULL, true, UnicodeString(""), UnicodeString(""), UnicodeString("") }
4517 };
4518 UErrorCode status = U_ZERO_ERROR;
4519 LocalPointer<Calendar> cal(Calendar::createInstance(status));
4520 if (U_FAILURE(status)) {
4521 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4522 return;
4523 }
4524 cal->setTime(july022008, status);
4525 const TestDateFormatLeniencyItem * itemPtr;
4526 LocalPointer<SimpleDateFormat> sdmft;
4527 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4528
4529 Locale locale = Locale::createFromName(itemPtr->locale);
4530 status = U_ZERO_ERROR;
4531 ParsePosition pos(0);
4532 sdmft.adoptInsteadAndCheckErrorCode(new SimpleDateFormat(itemPtr->pattern, locale, status), status);
4533 if (U_FAILURE(status)) {
4534 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4535 continue;
4536 }
4537 sdmft->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->leniency, status).
4538 setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->leniency, status).
4539 setBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, itemPtr->leniency, status);
4540 UDate d = sdmft->parse(itemPtr->parseString, pos);
4541
4542 if(itemPtr->expectedResult.length() == 0) {
4543 if(pos.getErrorIndex() != -1) {
4544 continue;
4545 } else {
4546 errln("error: unexpected parse success - " + itemPtr->parseString +
4547 " - pattern " + itemPtr->pattern +
4548 " - error index " + pos.getErrorIndex() +
4549 " - leniency " + itemPtr->leniency);
4550 continue;
4551 }
4552 }
4553 if(pos.getErrorIndex() != -1) {
4554 errln("error: parse error for string - " + itemPtr->parseString +
4555 " - pattern " + itemPtr->pattern +
4556 " - idx " + pos.getIndex() +
4557 " - error index "+pos.getErrorIndex() +
4558 " - leniency " + itemPtr->leniency);
4559 continue;
4560 }
4561
4562 UnicodeString formatResult("");
4563 sdmft->format(d, formatResult);
4564 if(formatResult.compare(itemPtr->expectedResult) != 0) {
4565 errln("error: unexpected format result. pattern["+itemPtr->pattern+"] expected[" + itemPtr->expectedResult + "] but result was[" + formatResult + "]");
4566 continue;
4567 } else {
4568 logln("formatted results match! - " + formatResult);
4569 }
4570
4571 }
4572 }
4573
4574
4575 typedef struct {
4576 UBool leniency;
4577 UnicodeString parseString;
4578 UnicodeString pattern;
4579 UnicodeString expectedResult; // empty string indicates expected error
4580 } TestMultiPatternMatchItem;
4581
TestParseMultiPatternMatch()4582 void DateFormatTest::TestParseMultiPatternMatch() {
4583 // For details see http://bugs.icu-project.org/trac/ticket/10336
4584 const TestMultiPatternMatchItem items[] = {
4585 // leniency parse String pattern expected result
4586 {true, UnicodeString("2013-Sep 13"), UnicodeString("yyyy-MMM dd"), UnicodeString("2013-Sep 13")},
4587 {true, UnicodeString("2013-September 14"), UnicodeString("yyyy-MMM dd"), UnicodeString("2013-Sep 14")},
4588 {false, UnicodeString("2013-September 15"), UnicodeString("yyyy-MMM dd"), UnicodeString("")},
4589 {false, UnicodeString("2013-September 16"), UnicodeString("yyyy-MMMM dd"), UnicodeString("2013-September 16")},
4590 {true, UnicodeString("2013-Sep 17"), UnicodeString("yyyy-LLL dd"), UnicodeString("2013-Sep 17")},
4591 {true, UnicodeString("2013-September 18"), UnicodeString("yyyy-LLL dd"), UnicodeString("2013-Sep 18")},
4592 {false, UnicodeString("2013-September 19"), UnicodeString("yyyy-LLL dd"), UnicodeString("")},
4593 {false, UnicodeString("2013-September 20"), UnicodeString("yyyy-LLLL dd"), UnicodeString("2013-September 20")},
4594 {true, UnicodeString("2013 Sat Sep 21"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("2013 Sat Sep 21")},
4595 {true, UnicodeString("2013 Sunday Sep 22"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("2013 Sun Sep 22")},
4596 {false, UnicodeString("2013 Monday Sep 23"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("")},
4597 {false, UnicodeString("2013 Tuesday Sep 24"), UnicodeString("yyyy EEEE MMM dd"), UnicodeString("2013 Tuesday Sep 24")},
4598 {true, UnicodeString("2013 Wed Sep 25"), UnicodeString("yyyy eee MMM dd"), UnicodeString("2013 Wed Sep 25")},
4599 {true, UnicodeString("2013 Thu Sep 26"), UnicodeString("yyyy eee MMM dd"), UnicodeString("2013 Thu Sep 26")},
4600 {false, UnicodeString("2013 Friday Sep 27"), UnicodeString("yyyy eee MMM dd"), UnicodeString("")},
4601 {false, UnicodeString("2013 Saturday Sep 28"), UnicodeString("yyyy eeee MMM dd"), UnicodeString("2013 Saturday Sep 28")},
4602 {true, UnicodeString("2013 Sun Sep 29"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("2013 Sun Sep 29")},
4603 {true, UnicodeString("2013 Monday Sep 30"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("2013 Mon Sep 30")},
4604 {false, UnicodeString("2013 Sunday Oct 13"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("")},
4605 {false, UnicodeString("2013 Monday Oct 14"), UnicodeString("yyyy cccc MMM dd"), UnicodeString("2013 Monday Oct 14")},
4606 {true, UnicodeString("2013 Oct 15 Q4"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 15 Q4")},
4607 {true, UnicodeString("2013 Oct 16 4th quarter"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 16 Q4")},
4608 {false, UnicodeString("2013 Oct 17 4th quarter"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("")},
4609 {false, UnicodeString("2013 Oct 18 Q4"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 18 Q4")},
4610 {true, UnicodeString("2013 Oct 19 Q4"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 19 4th quarter")},
4611 {true, UnicodeString("2013 Oct 20 4th quarter"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 20 4th quarter")},
4612 {false, UnicodeString("2013 Oct 21 Q4"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("")},
4613 {false, UnicodeString("2013 Oct 22 4th quarter"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 22 4th quarter")},
4614 {false, UnicodeString("--end--"), UnicodeString(""), UnicodeString("")},
4615 };
4616
4617 UErrorCode status = U_ZERO_ERROR;
4618 LocalPointer<Calendar> cal(Calendar::createInstance(status));
4619 if (U_FAILURE(status)) {
4620 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4621 return;
4622 }
4623 const TestMultiPatternMatchItem * itemPtr;
4624 DateFormat* sdmft = DateFormat::createDateInstance();
4625 if (sdmft == NULL) {
4626 dataerrln(UnicodeString("FAIL: Unable to create DateFormat"));
4627 return;
4628 }
4629 for (itemPtr = items; itemPtr->parseString != "--end--"; itemPtr++ ) {
4630 status = U_ZERO_ERROR;
4631 ParsePosition pos(0);
4632 ((SimpleDateFormat*) sdmft)->applyPattern(itemPtr->pattern);
4633 if (U_FAILURE(status)) {
4634 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4635 continue;
4636 }
4637 sdmft->setBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, itemPtr->leniency, status);
4638 UDate d = sdmft->parse(itemPtr->parseString, pos);
4639
4640 if(itemPtr->expectedResult.length() == 0) {
4641 if(pos.getErrorIndex() != -1) {
4642 continue;
4643 } else {
4644 errln("error: unexpected parse success - " + itemPtr->parseString +
4645 " - error index " + pos.getErrorIndex() +
4646 " - leniency " + itemPtr->leniency);
4647 continue;
4648 }
4649 }
4650 if(pos.getErrorIndex() != -1) {
4651 errln("error: parse error for string - " +itemPtr->parseString + " -- idx["+pos.getIndex()+"] errIdx["+pos.getErrorIndex()+"]");
4652 continue;
4653 }
4654
4655 UnicodeString formatResult("");
4656 sdmft->format(d, formatResult);
4657 if(formatResult.compare(itemPtr->expectedResult) != 0) {
4658 errln("error: unexpected format result. expected[" + itemPtr->expectedResult + "] but result was[" + formatResult + "]");
4659 } else {
4660 logln("formatted results match! - " + formatResult);
4661 }
4662 }
4663 delete sdmft;
4664 }
4665
TestParseLeniencyAPIs()4666 void DateFormatTest::TestParseLeniencyAPIs() {
4667 UErrorCode status = U_ZERO_ERROR;
4668 LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance());
4669 DateFormat *fmt = dateFormat.getAlias();
4670 if (fmt == NULL) {
4671 dataerrln("Failed calling dateFormat.getAlias()");
4672 return;
4673 }
4674
4675 assertTrue("isLenient default", fmt->isLenient());
4676 assertTrue("isCalendarLenient default", fmt->isCalendarLenient());
4677 assertTrue("ALLOW_WHITESPACE default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4678 assertTrue("ALLOW_NUMERIC default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4679 assertTrue("PARTIAL_MATCH default", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4680 assertTrue("MULTIPLE_PATTERNS default", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4681
4682 // Set calendar to strict
4683 fmt->setCalendarLenient(FALSE);
4684
4685 assertFalse("isLeninent after setCalendarLenient(FALSE)", fmt->isLenient());
4686 assertFalse("isCalendarLenient after setCalendarLenient(FALSE)", fmt->isCalendarLenient());
4687 assertTrue("ALLOW_WHITESPACE after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4688 assertTrue("ALLOW_NUMERIC after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4689
4690 // Set to strict
4691 fmt->setLenient(FALSE);
4692
4693 assertFalse("isLeninent after setLenient(FALSE)", fmt->isLenient());
4694 assertFalse("isCalendarLenient after setLenient(FALSE)", fmt->isCalendarLenient());
4695 assertFalse("ALLOW_WHITESPACE after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4696 assertFalse("ALLOW_NUMERIC after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4697 // These two boolean attributes are NOT affected according to the API specification
4698 assertTrue("PARTIAL_MATCH after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4699 assertTrue("MULTIPLE_PATTERNS after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4700
4701 // Allow white space leniency
4702 fmt->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, TRUE, status);
4703
4704 assertFalse("isLeninent after ALLOW_WHITESPACE/TRUE", fmt->isLenient());
4705 assertFalse("isCalendarLenient after ALLOW_WHITESPACE/TRUE", fmt->isCalendarLenient());
4706 assertTrue("ALLOW_WHITESPACE after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4707 assertFalse("ALLOW_NUMERIC after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4708
4709 // Set to lenient
4710 fmt->setLenient(TRUE);
4711
4712 assertTrue("isLenient after setLenient(TRUE)", fmt->isLenient());
4713 assertTrue("isCalendarLenient after setLenient(TRUE)", fmt->isCalendarLenient());
4714 assertTrue("ALLOW_WHITESPACE after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4715 assertTrue("ALLOW_NUMERIC after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4716 }
4717
TestNumberFormatOverride()4718 void DateFormatTest::TestNumberFormatOverride() {
4719 UErrorCode status = U_ZERO_ERROR;
4720 UnicodeString fields = (UnicodeString) "M";
4721
4722 LocalPointer<SimpleDateFormat> fmt;
4723 fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4724 if (!assertSuccess("SimpleDateFormat with pattern MM d", status)) {
4725 return;
4726 }
4727
4728
4729 for(int i=0; i<3; i++){
4730 NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4731 assertSuccess("NumberFormat en_US", status);
4732 fmt->adoptNumberFormat(fields, check_nf, status);
4733 assertSuccess("adoptNumberFormat check_nf", status);
4734
4735 const NumberFormat* get_nf = fmt->getNumberFormatForField((UChar)0x004D /*'M'*/);
4736 if (get_nf != check_nf) errln("FAIL: getter and setter do not work");
4737 }
4738 NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4739 assertSuccess("NumberFormat en_US", status);
4740 fmt->adoptNumberFormat(check_nf); // make sure using the same NF will not crash
4741
4742 const char * DATA [][2] = {
4743 { "", "\\u521D\\u516D \\u5341\\u4E94"},
4744 { "M", "\\u521D\\u516D 15"},
4745 { "Mo", "\\u521D\\u516D 15"},
4746 { "Md", "\\u521D\\u516D \\u5341\\u4E94"},
4747 { "MdMMd", "\\u521D\\u516D \\u5341\\u4E94"},
4748 { "mixed", "\\u521D\\u516D \\u5341\\u4E94"}
4749 };
4750
4751 UDate test_date = date(97, 6 - 1, 15);
4752
4753 for(int i=0; i < UPRV_LENGTHOF(DATA); i++){
4754 fields = DATA[i][0];
4755
4756 LocalPointer<SimpleDateFormat> fmt;
4757 fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4758 assertSuccess("SimpleDateFormat with pattern MM d", status);
4759 NumberFormat* overrideNF = NumberFormat::createInstance(Locale::createFromName("zh@numbers=hanidays"),status);
4760 assertSuccess("NumberFormat zh@numbers=hanidays", status);
4761
4762 if (fields == (UnicodeString) "") { // use the one w/o fields
4763 fmt->adoptNumberFormat(overrideNF);
4764 } else if (fields == (UnicodeString) "mixed") { // set 1 field at first but then full override, both(M & d) should be override
4765 NumberFormat* singleOverrideNF = NumberFormat::createInstance(Locale::createFromName("en@numbers=hebr"),status);
4766 assertSuccess("NumberFormat en@numbers=hebr", status);
4767
4768 fields = (UnicodeString) "M";
4769 fmt->adoptNumberFormat(fields, singleOverrideNF, status);
4770 assertSuccess("adoptNumberFormat singleOverrideNF", status);
4771
4772 fmt->adoptNumberFormat(overrideNF);
4773 } else if (fields == (UnicodeString) "Mo"){ // o is invlid field
4774 fmt->adoptNumberFormat(fields, overrideNF, status);
4775 if(status == U_INVALID_FORMAT_ERROR) {
4776 status = U_ZERO_ERROR;
4777 continue;
4778 }
4779 } else {
4780 fmt->adoptNumberFormat(fields, overrideNF, status);
4781 assertSuccess("adoptNumberFormat overrideNF", status);
4782 }
4783
4784 UnicodeString result;
4785 FieldPosition pos(FieldPosition::DONT_CARE);
4786 fmt->format(test_date,result, pos);
4787
4788 UnicodeString expected = ((UnicodeString)DATA[i][1]).unescape();;
4789
4790 if (result != expected)
4791 errln("FAIL: Expected " + expected + " get: " + result);
4792 }
4793 }
4794
TestCreateInstanceForSkeleton()4795 void DateFormatTest::TestCreateInstanceForSkeleton() {
4796 UErrorCode status = U_ZERO_ERROR;
4797 LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4798 "yMMMMd", "en", status));
4799 if (!assertSuccess("Create with pattern yMMMMd", status)) {
4800 return;
4801 }
4802 UnicodeString result;
4803 FieldPosition pos(FieldPosition::DONT_CARE);
4804 fmt->format(date(98, 5-1, 25), result, pos);
4805 assertEquals("format yMMMMd", "May 25, 1998", result);
4806 fmt.adoptInstead(DateFormat::createInstanceForSkeleton(
4807 "yMd", "en", status));
4808 if (!assertSuccess("Create with pattern yMd", status)) {
4809 return;
4810 }
4811 result.remove();
4812 fmt->format(date(98, 5-1, 25), result, pos);
4813 assertEquals("format yMd", "5/25/1998", result);
4814 }
4815
TestCreateInstanceForSkeletonDefault()4816 void DateFormatTest::TestCreateInstanceForSkeletonDefault() {
4817 UErrorCode status = U_ZERO_ERROR;
4818 Locale savedLocale;
4819 Locale::setDefault(Locale::getUS(), status);
4820 LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4821 "yMMMd", status));
4822 Locale::setDefault(savedLocale, status);
4823 if (!assertSuccess("Create with pattern yMMMd", status)) {
4824 return;
4825 }
4826 UnicodeString result;
4827 FieldPosition pos(FieldPosition::DONT_CARE);
4828 fmt->format(date(98, 5-1, 25), result, pos);
4829 assertEquals("format yMMMd", "May 25, 1998", result);
4830 }
4831
TestCreateInstanceForSkeletonWithCalendar()4832 void DateFormatTest::TestCreateInstanceForSkeletonWithCalendar() {
4833 UErrorCode status = U_ZERO_ERROR;
4834 LocalPointer<DateFormat> fmt(
4835 DateFormat::createInstanceForSkeleton(
4836 Calendar::createInstance(
4837 TimeZone::createTimeZone("GMT-3:00"),
4838 status),
4839 "yMdHm", "en", status));
4840 if (!assertSuccess("Create with pattern yMMMMd", status)) {
4841 return;
4842 }
4843 UnicodeString result;
4844 FieldPosition pos(FieldPosition::DONT_CARE);
4845
4846 LocalPointer<Calendar> cal(Calendar::createInstance(
4847 TimeZone::createTimeZone("GMT-7:00"),
4848 status));
4849 if (!assertSuccess("Creating GMT-7 time zone failed", status)) {
4850 return;
4851 }
4852 cal->clear();
4853 cal->set(1998, 5-1, 25, 0, 0, 0);
4854
4855 // date format time zone should be 4 hours ahead.
4856 fmt->format(cal->getTime(status), result, pos);
4857 assertEquals("format yMdHm", "5/25/1998, 04:00", result);
4858 assertSuccess("", status);
4859 }
4860
TestDFSCreateForLocaleNonGregorianLocale()4861 void DateFormatTest::TestDFSCreateForLocaleNonGregorianLocale() {
4862 UErrorCode status = U_ZERO_ERROR;
4863 Locale fa("fa");
4864 LocalPointer<DateFormatSymbols> sym(
4865 DateFormatSymbols::createForLocale(fa, status));
4866 if (!assertSuccess("", status)) {
4867 return;
4868 }
4869
4870 // Android: All locales default to Gregorian calendar:
4871 int32_t count;
4872 const UnicodeString *months = sym->getShortMonths(count);
4873
4874 // First persian month.
4875 UnicodeString expected("\\u0698\\u0627\\u0646\\u0648\\u06CC\\u0647\\u0654"); // Android-changed
4876 assertEquals("", expected.unescape(), months[0]);
4877 }
4878
TestDFSCreateForLocaleWithCalendarInLocale()4879 void DateFormatTest::TestDFSCreateForLocaleWithCalendarInLocale() {
4880 UErrorCode status = U_ZERO_ERROR;
4881 Locale en_heb("en@calendar=hebrew");
4882 LocalPointer<DateFormatSymbols> sym(
4883 DateFormatSymbols::createForLocale(en_heb, status));
4884 if (!assertSuccess("", status)) {
4885 return;
4886 }
4887
4888 // We should get the months of the hebrew calendar, not the gregorian
4889 // calendar.
4890 int32_t count;
4891 const UnicodeString *months = sym->getShortMonths(count);
4892
4893 // First hebrew month.
4894 UnicodeString expected("Tishri");
4895 assertEquals("", expected, months[0]);
4896 }
4897
TestChangeCalendar()4898 void DateFormatTest::TestChangeCalendar() {
4899 UErrorCode status = U_ZERO_ERROR;
4900 Locale en("en");
4901 Locale en_heb("en@calendar=hebrew");
4902 LocalPointer<DateFormat> fmt(
4903 DateFormat::createInstanceForSkeleton("yMMMd", en, status));
4904 if (!assertSuccess("", status)) {
4905 return;
4906 }
4907 fmt->adoptCalendar(Calendar::createInstance(en_heb, status));
4908 if (!assertSuccess("", status)) {
4909 return;
4910 }
4911 UnicodeString result;
4912 FieldPosition pos(FieldPosition::DONT_CARE);
4913 fmt->format(date(98, 5-1, 25), result, pos);
4914 assertEquals("format yMMMd", "Iyar 29, 5758", result);
4915 }
4916
TestPatternFromSkeleton()4917 void DateFormatTest::TestPatternFromSkeleton() {
4918 static const struct {
4919 const Locale& locale;
4920 const char* const skeleton;
4921 const char* const pattern;
4922 } TESTDATA[] = {
4923 // Ticket #11985
4924 {Locale::getEnglish(), "jjmm", "h:mm a"},
4925 {Locale::getEnglish(), "JJmm", "hh:mm"},
4926 {Locale::getGerman(), "jjmm", "HH:mm"},
4927 {Locale::getGerman(), "JJmm", "HH:mm"}
4928 };
4929
4930 for (size_t i = 0; i < UPRV_LENGTHOF(TESTDATA); i++) {
4931 UErrorCode status = U_ZERO_ERROR;
4932 LocalPointer<DateFormat> fmt(
4933 DateFormat::createInstanceForSkeleton(
4934 TESTDATA[i].skeleton, TESTDATA[i].locale, status));
4935 if (!assertSuccess("createInstanceForSkeleton", status)) {
4936 return;
4937 }
4938 UnicodeString pattern;
4939 static_cast<const SimpleDateFormat*>(fmt.getAlias())->toPattern(pattern);
4940 assertEquals("Format pattern", TESTDATA[i].pattern, pattern);
4941 }
4942 }
4943
TestAmPmMidnightNoon()4944 void DateFormatTest::TestAmPmMidnightNoon() {
4945 // Some times on 2015-11-13 (UTC+0).
4946 UDate k000000 = 1447372800000.0;
4947 UDate k000030 = 1447372830000.0;
4948 UDate k003000 = 1447374600000.0;
4949 UDate k060000 = 1447394400000.0;
4950 UDate k120000 = 1447416000000.0;
4951 UDate k180000 = 1447437600000.0;
4952
4953 UErrorCode errorCode = U_ZERO_ERROR;
4954 SimpleDateFormat sdf(UnicodeString(), errorCode);
4955 if (U_FAILURE(errorCode)) {
4956 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
4957 return;
4958 }
4959 const TimeZone *tz = TimeZone::getGMT();
4960 sdf.setTimeZone(*tz);
4961 UnicodeString out;
4962
4963 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
4964 // For ICU 57 output of "midnight" is temporarily suppressed.
4965
4966 // Short.
4967 sdf.applyPattern(UnicodeString("hh:mm:ss bbb"));
4968
4969 // assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4970 assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4971 assertEquals("hh:mm:ss bbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
4972 assertEquals("hh:mm:ss bbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
4973 assertEquals("hh:mm:ss bbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
4974 assertEquals("hh:mm:ss bbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
4975 assertEquals("hh:mm:ss bbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
4976
4977 sdf.applyPattern(UnicodeString("hh:mm bbb"));
4978
4979 // assertEquals("hh:mm bbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
4980 assertEquals("hh:mm bbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
4981 // assertEquals("hh:mm bbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
4982 assertEquals("hh:mm bbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
4983 assertEquals("hh:mm bbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
4984
4985 sdf.applyPattern(UnicodeString("hh bbb"));
4986
4987 // assertEquals("hh bbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
4988 assertEquals("hh bbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
4989 // assertEquals("hh bbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
4990 assertEquals("hh bbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
4991 // assertEquals("hh bbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
4992 assertEquals("hh bbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
4993
4994 // Wide.
4995 sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
4996
4997 // assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4998 assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4999 assertEquals("hh:mm:ss bbbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
5000 assertEquals("hh:mm:ss bbbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
5001 assertEquals("hh:mm:ss bbbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
5002 assertEquals("hh:mm:ss bbbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5003 assertEquals("hh:mm:ss bbbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
5004
5005 sdf.applyPattern(UnicodeString("hh:mm bbbb"));
5006
5007 // assertEquals("hh:mm bbbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5008 assertEquals("hh:mm bbbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
5009 // assertEquals("hh:mm bbbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5010 assertEquals("hh:mm bbbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
5011 assertEquals("hh:mm bbbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
5012
5013 sdf.applyPattern(UnicodeString("hh bbbb"));
5014
5015 // assertEquals("hh bbbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5016 assertEquals("hh bbbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
5017 // assertEquals("hh bbbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5018 assertEquals("hh bbbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
5019 // assertEquals("hh bbbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5020 assertEquals("hh bbbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
5021
5022 // Narrow.
5023 sdf.applyPattern(UnicodeString("hh:mm:ss bbbbb"));
5024
5025 // assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5026 assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 a", sdf.format(k000000, out.remove()));
5027 assertEquals("hh:mm:ss bbbbb | 00:00:30", "12:00:30 a", sdf.format(k000030, out.remove()));
5028 assertEquals("hh:mm:ss bbbbb | 00:30:00", "12:30:00 a", sdf.format(k003000, out.remove()));
5029 assertEquals("hh:mm:ss bbbbb | 06:00:00", "06:00:00 a", sdf.format(k060000, out.remove()));
5030 assertEquals("hh:mm:ss bbbbb | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5031 assertEquals("hh:mm:ss bbbbb | 18:00:00", "06:00:00 p", sdf.format(k180000, out.remove()));
5032
5033 sdf.applyPattern(UnicodeString("hh:mm bbbbb"));
5034
5035 // assertEquals("hh:mm bbbbb | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5036 assertEquals("hh:mm bbbbb | 00:00:00", "12:00 a", sdf.format(k000000, out.remove()));
5037 // assertEquals("hh:mm bbbbb | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5038 assertEquals("hh:mm bbbbb | 00:00:30", "12:00 a", sdf.format(k000030, out.remove()));
5039 assertEquals("hh:mm bbbbb | 00:30:00", "12:30 a", sdf.format(k003000, out.remove()));
5040
5041 sdf.applyPattern(UnicodeString("hh bbbbb"));
5042
5043 // assertEquals("hh bbbbb | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5044 assertEquals("hh bbbbb | 00:00:00", "12 a", sdf.format(k000000, out.remove()));
5045 // assertEquals("hh bbbbb | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5046 assertEquals("hh bbbbb | 00:00:30", "12 a", sdf.format(k000030, out.remove()));
5047 // assertEquals("hh bbbbb | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5048 assertEquals("hh bbbbb | 00:30:00", "12 a", sdf.format(k003000, out.remove()));
5049 }
5050
TestFlexibleDayPeriod()5051 void DateFormatTest::TestFlexibleDayPeriod() {
5052 // Some times on 2015-11-13 (UTC+0).
5053 UDate k000000 = 1447372800000.0;
5054 UDate k000030 = 1447372830000.0;
5055 UDate k003000 = 1447374600000.0;
5056 UDate k060000 = 1447394400000.0;
5057 UDate k120000 = 1447416000000.0;
5058 UDate k180000 = 1447437600000.0;
5059
5060 UErrorCode errorCode = U_ZERO_ERROR;
5061 SimpleDateFormat sdf(UnicodeString(), errorCode);
5062 if (U_FAILURE(errorCode)) {
5063 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5064 return;
5065 }
5066 const TimeZone *tz = TimeZone::getGMT();
5067 sdf.setTimeZone(*tz);
5068 UnicodeString out;
5069
5070 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5071 // For ICU 57 output of "midnight" is temporarily suppressed.
5072
5073 // Short.
5074 sdf.applyPattern(UnicodeString("hh:mm:ss BBB"));
5075
5076 // assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5077 assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5078 assertEquals("hh:mm:ss BBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5079 assertEquals("hh:mm:ss BBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5080 assertEquals("hh:mm:ss BBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5081 assertEquals("hh:mm:ss BBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5082 assertEquals("hh:mm:ss BBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5083
5084 sdf.applyPattern(UnicodeString("hh:mm BBB"));
5085
5086 // assertEquals("hh:mm BBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5087 assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5088 // assertEquals("hh:mm BBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5089 assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5090 assertEquals("hh:mm BBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5091
5092 sdf.applyPattern(UnicodeString("hh BBB"));
5093
5094 // assertEquals("hh BBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5095 assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5096 // assertEquals("hh BBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5097 assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5098 // assertEquals("hh BBB | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5099 assertEquals("hh BBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5100
5101 // Wide.
5102 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5103
5104 // assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5105 assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5106 assertEquals("hh:mm:ss BBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5107 assertEquals("hh:mm:ss BBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5108 assertEquals("hh:mm:ss BBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5109 assertEquals("hh:mm:ss BBBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5110 assertEquals("hh:mm:ss BBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5111
5112 sdf.applyPattern(UnicodeString("hh:mm BBBB"));
5113
5114 // assertEquals("hh:mm BBBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5115 assertEquals("hh:mm BBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5116 // assertEquals("hh:mm BBBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5117 assertEquals("hh:mm BBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5118 assertEquals("hh:mm BBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5119
5120 sdf.applyPattern(UnicodeString("hh BBBB"));
5121
5122 // assertEquals("hh BBBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5123 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5124 // assertEquals("hh BBBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5125 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5126 // assertEquals("hh BBBB | 00:80:00", "12 midnight", sdf.format(k003000, out.remove()));
5127 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5128
5129 // Narrow.
5130 sdf.applyPattern(UnicodeString("hh:mm:ss BBBBB"));
5131
5132 // assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5133 assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5134 assertEquals("hh:mm:ss BBBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5135 assertEquals("hh:mm:ss BBBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5136 assertEquals("hh:mm:ss BBBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5137 assertEquals("hh:mm:ss BBBBB | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5138 assertEquals("hh:mm:ss BBBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5139
5140 sdf.applyPattern(UnicodeString("hh:mm BBBBB"));
5141
5142 // assertEquals("hh:mm BBBBB | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5143 assertEquals("hh:mm BBBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5144 // assertEquals("hh:mm BBBBB | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5145 assertEquals("hh:mm BBBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5146 assertEquals("hh:mm BBBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5147
5148 sdf.applyPattern(UnicodeString("hh BBBBB"));
5149
5150 // assertEquals("hh BBBBB | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5151 assertEquals("hh BBBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5152 // assertEquals("hh BBBBB | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5153 assertEquals("hh BBBBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5154 // assertEquals("hh BBBBB | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5155 assertEquals("hh BBBBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5156 }
5157
TestDayPeriodWithLocales()5158 void DateFormatTest::TestDayPeriodWithLocales() {
5159 // Some times on 2015-11-13 (UTC+0).
5160 UDate k000000 = 1447372800000.0;
5161 UDate k010000 = 1447376400000.0;
5162 UDate k120000 = 1447416000000.0;
5163 UDate k220000 = 1447452000000.0;
5164
5165 UErrorCode errorCode = U_ZERO_ERROR;
5166 const TimeZone *tz = TimeZone::getGMT();
5167 UnicodeString out;
5168
5169 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5170 // For ICU 57 output of "midnight" and its localized equivalentns is temporarily suppressed.
5171
5172 // Locale de has a word for midnight, but not noon.
5173 SimpleDateFormat sdf(UnicodeString(), Locale::getGermany(), errorCode);
5174 if (U_FAILURE(errorCode)) {
5175 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5176 return;
5177 }
5178 sdf.setTimeZone(*tz);
5179
5180 sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
5181
5182 // assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 Mitternacht",
5183 // sdf.format(k000000, out.remove()));
5184 assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 AM",
5185 sdf.format(k000000, out.remove()));
5186 assertEquals("hh:mm:ss bbbb | 12:00:00 | de", "12:00:00 PM",
5187 sdf.format(k120000, out.remove()));
5188
5189 // Locale ee has a rule that wraps around midnight (21h - 4h).
5190 sdf = SimpleDateFormat(UnicodeString(), Locale("ee"), errorCode);
5191 sdf.setTimeZone(*tz);
5192
5193 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5194
5195 assertEquals("hh:mm:ss BBBB | 22:00:00 | ee", UnicodeString("10:00:00 z\\u00E3").unescape(),
5196 sdf.format(k220000, out.remove()));
5197 assertEquals("hh:mm:ss BBBB | 00:00:00 | ee", UnicodeString("12:00:00 z\\u00E3").unescape(),
5198 sdf.format(k000000, out.remove()));
5199 assertEquals("hh:mm:ss BBBB | 01:00:00 | ee", UnicodeString("01:00:00 z\\u00E3").unescape(),
5200 sdf.format(k010000, out.remove()));
5201
5202 // Locale root has rules for AM/PM only.
5203 sdf = SimpleDateFormat(UnicodeString(), Locale("root"), errorCode);
5204 sdf.setTimeZone(*tz);
5205
5206 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5207
5208 assertEquals("hh:mm:ss BBBB | 00:00:00 | root", "12:00:00 AM",
5209 sdf.format(k000000, out.remove()));
5210 assertEquals("hh:mm:ss BBBB | 12:00:00 | root", "12:00:00 PM",
5211 sdf.format(k120000, out.remove()));
5212
5213 // Empty string should behave exactly as root.
5214 sdf = SimpleDateFormat(UnicodeString(), Locale(""), errorCode);
5215 sdf.setTimeZone(*tz);
5216
5217 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5218
5219 assertEquals("hh:mm:ss BBBB | 00:00:00 | \"\" (root)", "12:00:00 AM",
5220 sdf.format(k000000, out.remove()));
5221 assertEquals("hh:mm:ss BBBB | 12:00:00 | \"\" (root)", "12:00:00 PM",
5222 sdf.format(k120000, out.remove()));
5223
5224 // Locale en_US should fall back to en.
5225 sdf = SimpleDateFormat(UnicodeString(), Locale("en_US"), errorCode);
5226 sdf.setTimeZone(*tz);
5227
5228 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5229
5230 // assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 midnight",
5231 // sdf.format(k000000, out.remove()));
5232 assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 at night",
5233 sdf.format(k000000, out.remove()));
5234 assertEquals("hh:mm:ss BBBB | 01:00:00 | en_US", "01:00:00 at night",
5235 sdf.format(k010000, out.remove()));
5236 assertEquals("hh:mm:ss BBBB | 12:00:00 | en_US", "12:00:00 noon",
5237 sdf.format(k120000, out.remove()));
5238
5239 // Locale es_CO should not fall back to es and should have a
5240 // different string for 1 in the morning.
5241 // (es_CO: "de la manana" (first n has a tilde) vs. es: "de la madrugada")
5242 sdf = SimpleDateFormat(UnicodeString(), Locale("es_CO"), errorCode);
5243 sdf.setTimeZone(*tz);
5244
5245 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5246 assertEquals("hh:mm:ss BBBB | 01:00:00 | es_CO", UnicodeString("01:00:00 de la ma\\u00F1ana").unescape(),
5247 sdf.format(k010000, out.remove()));
5248
5249 sdf = SimpleDateFormat(UnicodeString(), Locale("es"), errorCode);
5250 sdf.setTimeZone(*tz);
5251
5252 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5253 assertEquals("hh:mm:ss BBBB | 01:00:00 | es", "01:00:00 de la madrugada",
5254 sdf.format(k010000, out.remove()));
5255
5256 // #13215: for locales with keywords, check hang in DayPeriodRules""getInstance(const Locale, ...),
5257 // which is called in SimpleDateFormat::format for patterns that include 'B'.
5258 sdf = SimpleDateFormat(UnicodeString(), Locale("en@calendar=buddhist"), errorCode);
5259 sdf.setTimeZone(*tz);
5260
5261 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5262 assertEquals("hh:mm:ss BBBB | 01:00:00 | en@calendar=buddhist", "01:00:00 at night",
5263 sdf.format(k010000, out.remove()));
5264 }
5265
TestMinuteSecondFieldsInOddPlaces()5266 void DateFormatTest::TestMinuteSecondFieldsInOddPlaces() {
5267 // Some times on 2015-11-13 (UTC+0).
5268 UDate k000000 = 1447372800000.0;
5269 UDate k000030 = 1447372830000.0;
5270 UDate k003000 = 1447374600000.0;
5271 UDate k060030 = 1447394430000.0;
5272 UDate k063000 = 1447396200000.0;
5273
5274 UErrorCode errorCode = U_ZERO_ERROR;
5275 const TimeZone *tz = TimeZone::getGMT();
5276 UnicodeString out;
5277
5278 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5279 // For ICU 57 output of "midnight" is temporarily suppressed.
5280
5281 // Seconds field is not present.
5282
5283 // Apply pattern through constructor to make sure parsePattern() is called during initialization.
5284 SimpleDateFormat sdf(UnicodeString("hh:mm 'ss' bbbb"), errorCode);
5285 if (U_FAILURE(errorCode)) {
5286 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5287 return;
5288 }
5289 sdf.setTimeZone(*tz);
5290
5291 // assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss midnight",
5292 // sdf.format(k000030, out.remove()));
5293 assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss AM",
5294 sdf.format(k000030, out.remove()));
5295 assertEquals("hh:mm 'ss' bbbb | 06:00:30", "06:00 ss AM",
5296 sdf.format(k060030, out.remove()));
5297
5298 sdf.applyPattern(UnicodeString("hh:mm 'ss' BBBB"));
5299
5300 // assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss midnight",
5301 // sdf.format(k000030, out.remove()));
5302 assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss at night",
5303 sdf.format(k000030, out.remove()));
5304 assertEquals("hh:mm 'ss' BBBB | 06:00:30", "06:00 ss in the morning",
5305 sdf.format(k060030, out.remove()));
5306
5307 // Minutes field is not present.
5308 sdf.applyPattern(UnicodeString("hh 'mm ss' bbbb"));
5309
5310 // assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss midnight",
5311 // sdf.format(k003000, out.remove()));
5312 assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss AM",
5313 sdf.format(k003000, out.remove()));
5314 assertEquals("hh 'mm ss' bbbb | 06:30:00", "06 mm ss AM",
5315 sdf.format(k063000, out.remove()));
5316
5317 sdf.applyPattern(UnicodeString("hh 'mm ss' BBBB"));
5318
5319 // assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss midnight",
5320 // sdf.format(k003000, out.remove()));
5321 assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss at night",
5322 sdf.format(k003000, out.remove()));
5323 assertEquals("hh 'mm ss' BBBB | 06:30:00", "06 mm ss in the morning",
5324 sdf.format(k063000, out.remove()));
5325
5326 // Minutes and seconds fields appear after day periods.
5327 sdf.applyPattern(UnicodeString("bbbb hh:mm:ss"));
5328
5329 // assertEquals("bbbb hh:mm:ss | 00:00:00", "midnight 12:00:00",
5330 // sdf.format(k000000, out.remove()));
5331 assertEquals("bbbb hh:mm:ss | 00:00:00", "AM 12:00:00",
5332 sdf.format(k000000, out.remove()));
5333 assertEquals("bbbb hh:mm:ss | 00:00:30", "AM 12:00:30",
5334 sdf.format(k000030, out.remove()));
5335 assertEquals("bbbb hh:mm:ss | 00:30:00", "AM 12:30:00",
5336 sdf.format(k003000, out.remove()));
5337
5338 sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5339
5340 // assertEquals("BBBB hh:mm:ss | 00:00:00", "midnight 12:00:00",
5341 // sdf.format(k000000, out.remove()));
5342 assertEquals("BBBB hh:mm:ss | 00:00:00", "at night 12:00:00",
5343 sdf.format(k000000, out.remove()));
5344 assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5345 sdf.format(k000030, out.remove()));
5346 assertEquals("BBBB hh:mm:ss | 00:30:00", "at night 12:30:00",
5347 sdf.format(k003000, out.remove()));
5348
5349 // Confirm applyPattern() reparses the pattern string.
5350 sdf.applyPattern(UnicodeString("BBBB hh"));
5351 // assertEquals("BBBB hh | 00:00:30", "midnight 12",
5352 // sdf.format(k000030, out.remove()));
5353 assertEquals("BBBB hh | 00:00:30", "at night 12",
5354 sdf.format(k000030, out.remove()));
5355
5356 sdf.applyPattern(UnicodeString("BBBB hh:mm:'ss'"));
5357 // assertEquals("BBBB hh:mm:'ss' | 00:00:30", "midnight 12:00:ss",
5358 // sdf.format(k000030, out.remove()));
5359 assertEquals("BBBB hh | 00:00:30", "at night 12:00:ss",
5360 sdf.format(k000030, out.remove()));
5361
5362 sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5363 assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5364 sdf.format(k000030, out.remove()));
5365 }
5366
TestDayPeriodParsing()5367 void DateFormatTest::TestDayPeriodParsing() {
5368 // Some times on 2015-11-13 (UTC+0).
5369 UDate k000000 = 1447372800000.0;
5370 UDate k003700 = 1447375020000.0;
5371 UDate k010000 = 1447376400000.0;
5372 UDate k013000 = 1447378200000.0;
5373 UDate k030000 = 1447383600000.0;
5374 UDate k090000 = 1447405200000.0;
5375 UDate k120000 = 1447416000000.0;
5376 UDate k130000 = 1447419600000.0;
5377 UDate k133700 = 1447421820000.0;
5378 UDate k150000 = 1447426800000.0;
5379 UDate k190000 = 1447441200000.0;
5380 UDate k193000 = 1447443000000.0;
5381 UDate k200000 = 1447444800000.0;
5382 UDate k210000 = 1447448400000.0;
5383
5384 UErrorCode errorCode = U_ZERO_ERROR;
5385 SimpleDateFormat sdf(UnicodeString(), errorCode);
5386 if (U_FAILURE(errorCode)) {
5387 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5388 return;
5389 }
5390 const TimeZone *tz = TimeZone::getGMT();
5391 sdf.setTimeZone(*tz);
5392 UnicodeString out;
5393
5394 // 'B' -- flexible day periods
5395 // A day period on its own parses to the center of that period.
5396 sdf.applyPattern(UnicodeString("yyyy-MM-dd B"));
5397 assertEquals("yyyy-MM-dd B | 2015-11-13 midnight",
5398 k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5399 assertEquals("yyyy-MM-dd B | 2015-11-13 noon",
5400 k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5401 assertEquals("yyyy-MM-dd B | 2015-11-13 in the afternoon",
5402 k150000, sdf.parse(UnicodeString("2015-11-13 in the afternoon"), errorCode));
5403 assertEquals("yyyy-MM-dd B | 2015-11-13 in the evening",
5404 k193000, sdf.parse(UnicodeString("2015-11-13 in the evening"), errorCode));
5405 assertEquals("yyyy-MM-dd B | 2015-11-13 at night",
5406 k013000, sdf.parse(UnicodeString("2015-11-13 at night"), errorCode));
5407
5408 // If time and day period are consistent with each other then time is parsed accordingly.
5409 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5410 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 midnight",
5411 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5412 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 noon",
5413 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5414 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 at night",
5415 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5416 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 in the afternoon",
5417 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5418 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 in the morning",
5419 k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5420 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 at night",
5421 k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5422
5423 // If the hour is 13 thru 23 then day period has no effect on time (since time is assumed
5424 // to be in 24-hour format).
5425 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5426 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 midnight",
5427 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5428 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 noon",
5429 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5430 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5431 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5432 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the afternoon",
5433 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the afternoon"), errorCode));
5434 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the morning",
5435 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the morning"), errorCode));
5436 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5437 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5438
5439 // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5440 // This unfortunately means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5441 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5442 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 midnight",
5443 k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5444 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 noon",
5445 k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5446
5447 // But when parsed with 'H', 0 indicates a 24-hour time, therefore we disregard the day period.
5448 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5449 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 midnight",
5450 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5451 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 noon",
5452 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5453 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5454 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5455 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the afternoon",
5456 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the afternoon"), errorCode));
5457 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the morning",
5458 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the morning"), errorCode));
5459 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5460 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5461
5462 // Even when parsed with 'H', hours 1 thru 12 are considered 12-hour time and takes
5463 // day period into account in parsing.
5464 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5465 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 midnight",
5466 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5467 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 noon",
5468 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5469 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 at night",
5470 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5471 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 in the afternoon",
5472 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5473 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 in the morning",
5474 k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5475 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 at night",
5476 k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5477
5478 // If a 12-hour time and the day period don't agree with each other, time is parsed as close
5479 // to the given day period as possible.
5480 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5481
5482 // AFTERNOON1 is [12, 18), but "7 in the afternoon" parses to 19:00.
5483 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 07:00 in the afternoon",
5484 k190000, sdf.parse(UnicodeString("2015-11-13 07:00 in the afternoon"), errorCode));
5485 // NIGHT1 is [21, 6), but "8 at night" parses to 20:00.
5486 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 08:00 at night",
5487 k200000, sdf.parse(UnicodeString("2015-11-13 08:00 at night"), errorCode));
5488
5489 // 'b' -- fixed day periods (AM, PM, midnight, noon)
5490 // On their own, "midnight" parses to 00:00 and "noon" parses to 12:00.
5491 // AM and PM are handled by the 'a' parser (which doesn't handle this case well).
5492 sdf.applyPattern(UnicodeString("yyyy-MM-dd b"));
5493 assertEquals("yyyy-MM-dd b | 2015-11-13 midnight",
5494 k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5495 assertEquals("yyyy-MM-dd b | 2015-11-13 noon",
5496 k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5497
5498 // For 12-hour times, AM and PM should be parsed as if with pattern character 'a'.
5499 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5500 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 AM",
5501 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 AM"), errorCode));
5502 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 PM",
5503 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 PM"), errorCode));
5504
5505 // 12 midnight parses to 00:00, and 12 noon parses to 12:00.
5506 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 midnight",
5507 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5508 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 noon",
5509 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5510
5511 // Hours 13-23 indicate 24-hour time so we disregard "midnight" or "noon".
5512 // Again, AM and PM are handled by the 'a' parser which doesn't handle this case well.
5513 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5514 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 midnight",
5515 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5516 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 noon",
5517 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5518
5519 // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5520 // Again, this means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5521 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5522 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 midnight",
5523 k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5524 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 noon",
5525 k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5526
5527 // With 'H' though 0 indicates a 24-hour time, therefore we disregard the day period.
5528 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5529 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 midnight",
5530 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5531 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 noon",
5532 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5533
5534 // If "midnight" or "noon" is parsed with a 12-hour time other than 12:00, choose
5535 // the version that's closer to the period given.
5536 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5537 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 midnight",
5538 k030000, sdf.parse(UnicodeString("2015-11-13 03:00 midnight"), errorCode));
5539 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 noon",
5540 k150000, sdf.parse(UnicodeString("2015-11-13 03:00 noon"), errorCode));
5541 }
5542
TestParseRegression13744()5543 void DateFormatTest::TestParseRegression13744() {
5544 LocalPointer<DateFormat> dfmt(DateFormat::createDateTimeInstance(
5545 DateFormat::SHORT, DateFormat::SHORT, Locale("en", "US")));
5546 if (dfmt.isNull()) {
5547 dataerrln("DateFormat::createDateTimeInstance() failed");
5548 return;
5549 }
5550 ParsePosition pos(0);
5551 UnicodeString inDate("4/27/18");
5552 dfmt->parse(inDate, pos);
5553 assertEquals("Error index", inDate.length(), pos.getErrorIndex());
5554 }
5555
5556 #endif /* #if !UCONFIG_NO_FORMATTING */
5557
5558 //eof
5559