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