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