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(TestRoundtripWithCalendar);
92 TESTCASE_AUTO(Test6338);
93 TESTCASE_AUTO(Test6726);
94 TESTCASE_AUTO(TestGMTParsing);
95 TESTCASE_AUTO(Test6880);
96 TESTCASE_AUTO(TestISOEra);
97 TESTCASE_AUTO(TestFormalChineseDate);
98 TESTCASE_AUTO(TestNumberAsStringParsing);
99 TESTCASE_AUTO(TestStandAloneGMTParse);
100 TESTCASE_AUTO(TestParsePosition);
101 TESTCASE_AUTO(TestMonthPatterns);
102 TESTCASE_AUTO(TestContext);
103 TESTCASE_AUTO(TestNonGregoFmtParse);
104 TESTCASE_AUTO(TestFormatsWithNumberSystems);
105 /*
106 TESTCASE_AUTO(TestRelativeError);
107 TESTCASE_AUTO(TestRelativeOther);
108 */
109 TESTCASE_AUTO(TestDotAndAtLeniency);
110 TESTCASE_AUTO(TestDateFormatLeniency);
111 TESTCASE_AUTO(TestParseMultiPatternMatch);
112
113 TESTCASE_AUTO(TestParseLeniencyAPIs);
114 TESTCASE_AUTO(TestNumberFormatOverride);
115 TESTCASE_AUTO(TestCreateInstanceForSkeleton);
116 TESTCASE_AUTO(TestCreateInstanceForSkeletonDefault);
117 TESTCASE_AUTO(TestCreateInstanceForSkeletonWithCalendar);
118 TESTCASE_AUTO(TestDFSCreateForLocaleNonGregorianLocale);
119 TESTCASE_AUTO(TestDFSCreateForLocaleWithCalendarInLocale);
120 TESTCASE_AUTO(TestChangeCalendar);
121
122 TESTCASE_AUTO(TestPatternFromSkeleton);
123
124 TESTCASE_AUTO(TestAmPmMidnightNoon);
125 TESTCASE_AUTO(TestFlexibleDayPeriod);
126 TESTCASE_AUTO(TestDayPeriodWithLocales);
127 TESTCASE_AUTO(TestMinuteSecondFieldsInOddPlaces);
128 TESTCASE_AUTO(TestDayPeriodParsing);
129 TESTCASE_AUTO(TestParseRegression13744);
130 TESTCASE_AUTO(TestAdoptCalendarLeak);
131 TESTCASE_AUTO(Test20741_ABFields);
132
133 TESTCASE_AUTO_END;
134 }
135
TestPatterns()136 void DateFormatTest::TestPatterns() {
137 static const struct {
138 const char *actualPattern;
139 const char *expectedPattern;
140 const char *localeID;
141 const char *expectedLocalPattern;
142 } EXPECTED[] = {
143 {UDAT_YEAR, "y","en","y"},
144
145 {UDAT_QUARTER, "QQQQ", "en", "QQQQ"},
146 {UDAT_ABBR_QUARTER, "QQQ", "en", "QQQ"},
147 {UDAT_YEAR_QUARTER, "yQQQQ", "en", "QQQQ y"},
148 {UDAT_YEAR_ABBR_QUARTER, "yQQQ", "en", "QQQ y"},
149
150 {UDAT_NUM_MONTH, "M", "en", "L"},
151 {UDAT_ABBR_MONTH, "MMM", "en", "LLL"},
152 {UDAT_MONTH, "MMMM", "en", "LLLL"},
153 {UDAT_YEAR_NUM_MONTH, "yM","en","M/y"},
154 {UDAT_YEAR_ABBR_MONTH, "yMMM","en","MMM y"},
155 {UDAT_YEAR_MONTH, "yMMMM","en","MMMM y"},
156
157 {UDAT_DAY, "d","en","d"},
158 {UDAT_YEAR_NUM_MONTH_DAY, "yMd", "en", "M/d/y"},
159 {UDAT_YEAR_ABBR_MONTH_DAY, "yMMMd", "en", "MMM d, y"},
160 {UDAT_YEAR_MONTH_DAY, "yMMMMd", "en", "MMMM d, y"},
161 {UDAT_YEAR_NUM_MONTH_WEEKDAY_DAY, "yMEd", "en", "EEE, M/d/y"},
162 {UDAT_YEAR_ABBR_MONTH_WEEKDAY_DAY, "yMMMEd", "en", "EEE, MMM d, y"},
163 {UDAT_YEAR_MONTH_WEEKDAY_DAY, "yMMMMEEEEd", "en", "EEEE, MMMM d, y"},
164
165 {UDAT_NUM_MONTH_DAY, "Md","en","M/d"},
166 {UDAT_ABBR_MONTH_DAY, "MMMd","en","MMM d"},
167 {UDAT_MONTH_DAY, "MMMMd","en","MMMM d"},
168 {UDAT_NUM_MONTH_WEEKDAY_DAY, "MEd","en","EEE, M/d"},
169 {UDAT_ABBR_MONTH_WEEKDAY_DAY, "MMMEd","en","EEE, MMM d"},
170 {UDAT_MONTH_WEEKDAY_DAY, "MMMMEEEEd","en","EEEE, MMMM d"},
171
172 {UDAT_HOUR, "j", "en", "h a"}, // (fixed expected result per ticket 6872<-6626)
173 {UDAT_HOUR24, "H", "en", "HH"}, // (fixed expected result per ticket 6872<-6626
174
175 {UDAT_MINUTE, "m", "en", "m"},
176 {UDAT_HOUR_MINUTE, "jm","en","h:mm a"}, // (fixed expected result per ticket 6872<-7180)
177 {UDAT_HOUR24_MINUTE, "Hm", "en", "HH:mm"}, // (fixed expected result per ticket 6872<-6626)
178
179 {UDAT_SECOND, "s", "en", "s"},
180 {UDAT_HOUR_MINUTE_SECOND, "jms","en","h:mm:ss a"}, // (fixed expected result per ticket 6872<-7180)
181 {UDAT_HOUR24_MINUTE_SECOND, "Hms","en","HH:mm:ss"}, // (fixed expected result per ticket 6872<-6626)
182 {UDAT_MINUTE_SECOND, "ms", "en", "mm:ss"}, // (fixed expected result per ticket 6872<-6626)
183
184 {UDAT_LOCATION_TZ, "VVVV", "en", "VVVV"},
185 {UDAT_GENERIC_TZ, "vvvv", "en", "vvvv"},
186 {UDAT_ABBR_GENERIC_TZ, "v", "en", "v"},
187 {UDAT_SPECIFIC_TZ, "zzzz", "en", "zzzz"},
188 {UDAT_ABBR_SPECIFIC_TZ, "z", "en", "z"},
189 {UDAT_ABBR_UTC_TZ, "ZZZZ", "en", "ZZZZ"},
190
191 {UDAT_YEAR_NUM_MONTH_DAY UDAT_ABBR_UTC_TZ, "yMdZZZZ", "en", "M/d/y, ZZZZ"},
192 {UDAT_MONTH_DAY UDAT_LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d, VVVV"}
193 };
194
195 IcuTestErrorCode errorCode(*this, "TestPatterns()");
196 for (int32_t i = 0; i < UPRV_LENGTHOF(EXPECTED); i++) {
197 // Verify that patterns have the correct values
198 UnicodeString actualPattern(EXPECTED[i].actualPattern, -1, US_INV);
199 UnicodeString expectedPattern(EXPECTED[i].expectedPattern, -1, US_INV);
200 Locale locale(EXPECTED[i].localeID);
201 if (actualPattern != expectedPattern) {
202 errln("FAILURE! Expected pattern: " + expectedPattern +
203 " but was: " + actualPattern);
204 }
205
206 // Verify that DataFormat instances produced contain the correct
207 // localized patterns
208 // TODO: use DateFormat::getInstanceForSkeleton(), ticket #9029
209 // Java test code:
210 // DateFormat date1 = DateFormat.getPatternInstance(actualPattern,
211 // locale);
212 // DateFormat date2 = DateFormat.getPatternInstance(Calendar.getInstance(locale),
213 // actualPattern, locale);
214 LocalPointer<DateTimePatternGenerator> generator(
215 DateTimePatternGenerator::createInstance(locale, errorCode));
216 if(errorCode.errDataIfFailureAndReset("DateTimePatternGenerator::createInstance() failed for locale ID \"%s\"", EXPECTED[i].localeID)) {
217 continue;
218 }
219 UnicodeString pattern = generator->getBestPattern(actualPattern, errorCode);
220 SimpleDateFormat date1(pattern, locale, errorCode);
221 SimpleDateFormat date2(pattern, locale, errorCode);
222 date2.adoptCalendar(Calendar::createInstance(locale, errorCode));
223 if(errorCode.errIfFailureAndReset("DateFormat::getInstanceForSkeleton() failed")) {
224 errln(" for actualPattern \"%s\" & locale ID \"%s\"",
225 EXPECTED[i].actualPattern, EXPECTED[i].localeID);
226 continue;
227 }
228
229 UnicodeString expectedLocalPattern(EXPECTED[i].expectedLocalPattern, -1, US_INV);
230 UnicodeString actualLocalPattern1;
231 UnicodeString actualLocalPattern2;
232 date1.toLocalizedPattern(actualLocalPattern1, errorCode);
233 date2.toLocalizedPattern(actualLocalPattern2, errorCode);
234 if (actualLocalPattern1 != expectedLocalPattern) {
235 errln("FAILURE! Expected local pattern: " + expectedLocalPattern
236 + " but was: " + actualLocalPattern1);
237 }
238 if (actualLocalPattern2 != expectedLocalPattern) {
239 errln("FAILURE! Expected local pattern: " + expectedLocalPattern
240 + " but was: " + actualLocalPattern2);
241 }
242 }
243 }
244
245 // Test written by Wally Wedel and emailed to me.
TestWallyWedel()246 void DateFormatTest::TestWallyWedel()
247 {
248 UErrorCode status = U_ZERO_ERROR;
249 /*
250 * Instantiate a TimeZone so we can get the ids.
251 */
252 TimeZone *tz = new SimpleTimeZone(7,"");
253 /*
254 * Computational variables.
255 */
256 int32_t offset, hours, minutes, seconds;
257 /*
258 * Instantiate a SimpleDateFormat set up to produce a full time
259 zone name.
260 */
261 SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)"zzzz", status);
262 /*
263 * A String array for the time zone ids.
264 */
265 int32_t ids_length;
266 StringEnumeration* ids = TimeZone::createEnumeration();
267 if (ids == NULL) {
268 dataerrln("Unable to create TimeZone enumeration.");
269 if (sdf != NULL) {
270 delete sdf;
271 }
272 return;
273 }
274 ids_length = ids->count(status);
275 /*
276 * How many ids do we have?
277 */
278 logln("Time Zone IDs size: %d", ids_length);
279 /*
280 * Column headings (sort of)
281 */
282 logln("Ordinal ID offset(h:m) name");
283 /*
284 * Loop through the tzs.
285 */
286 UDate today = Calendar::getNow();
287 Calendar *cal = Calendar::createInstance(status);
288 for (int32_t i = 0; i < ids_length; i++) {
289 // logln(i + " " + ids[i]);
290 const UnicodeString* id = ids->snext(status);
291 TimeZone *ttz = TimeZone::createTimeZone(*id);
292 // offset = ttz.getRawOffset();
293 cal->setTimeZone(*ttz);
294 cal->setTime(today, status);
295 offset = cal->get(UCAL_ZONE_OFFSET, status) + cal->get(UCAL_DST_OFFSET, status);
296 // logln(i + " " + ids[i] + " offset " + offset);
297 const char* sign = "+";
298 if (offset < 0) {
299 sign = "-";
300 offset = -offset;
301 }
302 hours = offset/3600000;
303 minutes = (offset%3600000)/60000;
304 seconds = (offset%60000)/1000;
305 UnicodeString dstOffset = (UnicodeString)"" + sign + (hours < 10 ? "0" : "") +
306 (int32_t)hours + ":" + (minutes < 10 ? "0" : "") + (int32_t)minutes;
307 if (seconds != 0) {
308 dstOffset = dstOffset + ":" + (seconds < 10 ? "0" : "") + seconds;
309 }
310 /*
311 * Instantiate a date so we can display the time zone name.
312 */
313 sdf->setTimeZone(*ttz);
314 /*
315 * Format the output.
316 */
317 UnicodeString fmtOffset;
318 FieldPosition pos(FieldPosition::DONT_CARE);
319 sdf->format(today,fmtOffset, pos);
320 // UnicodeString fmtOffset = tzS.toString();
321 UnicodeString *fmtDstOffset = 0;
322 if (fmtOffset.startsWith("GMT") && fmtOffset.length() != 3)
323 {
324 //fmtDstOffset = fmtOffset->substring(3);
325 fmtDstOffset = new UnicodeString();
326 fmtOffset.extract(3, fmtOffset.length(), *fmtDstOffset);
327 }
328 /*
329 * Show our result.
330 */
331 UBool ok = fmtDstOffset == 0 || *fmtDstOffset == dstOffset;
332 if (ok)
333 {
334 logln(UnicodeString() + i + " " + *id + " " + dstOffset +
335 " " + fmtOffset +
336 (fmtDstOffset != 0 ? " ok" : " ?"));
337 }
338 else
339 {
340 errln(UnicodeString() + i + " " + *id + " " + dstOffset +
341 " " + fmtOffset + " *** FAIL ***");
342 }
343 delete ttz;
344 delete fmtDstOffset;
345 }
346 delete cal;
347 // delete ids; // TODO: BAD API
348 delete ids;
349 delete sdf;
350 delete tz;
351 }
352
353 // -------------------------------------
354
355 /**
356 * Test operator==
357 */
358 void
TestEquals()359 DateFormatTest::TestEquals()
360 {
361 DateFormat* fmtA = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
362 DateFormat* fmtB = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
363 if ( fmtA == NULL || fmtB == NULL){
364 dataerrln("Error calling DateFormat::createDateTimeInstance");
365 delete fmtA;
366 delete fmtB;
367 return;
368 }
369
370 if (!(*fmtA == *fmtB)) errln((UnicodeString)"FAIL");
371 delete fmtA;
372 delete fmtB;
373
374 TimeZone* test = TimeZone::createTimeZone("PDT");
375 delete test;
376 }
377
378 // -------------------------------------
379
380 /**
381 * Test the parsing of 2-digit years.
382 */
383 void
TestTwoDigitYearDSTParse(void)384 DateFormatTest::TestTwoDigitYearDSTParse(void)
385 {
386 UErrorCode status = U_ZERO_ERROR;
387 SimpleDateFormat fullFmt((UnicodeString)"EEE MMM dd HH:mm:ss.SSS zzz yyyy G", status);
388 SimpleDateFormat fmt((UnicodeString)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status);
389 //DateFormat* fmt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, Locale::ENGLISH);
390 UnicodeString s(u"03-Apr-04 2:20:47 o'clock AM PST");
391 LocalPointer<TimeZone> defaultTZ(TimeZone::createDefault());
392 LocalPointer<TimeZone> PST(TimeZone::createTimeZone("PST"));
393 int32_t defaultOffset = defaultTZ->getRawOffset();
394 int32_t PSTOffset = PST->getRawOffset();
395 int32_t hour = 2 + (defaultOffset - PSTOffset) / (60*60*1000);
396 // hour is the expected hour of day, in units of seconds
397 hour = ((hour < 0) ? hour + 24 : hour) * 60*60;
398
399 UnicodeString str;
400
401 if(U_FAILURE(status)) {
402 dataerrln("Could not set up test. exitting - %s", u_errorName(status));
403 return;
404 }
405
406 UDate d = fmt.parse(s, status);
407 logln(s + " P> " + fullFmt.format(d, str));
408 int32_t y, m, day, hr, min, sec;
409 dateToFields(d, y, m, day, hr, min, sec);
410 hour += defaultTZ->inDaylightTime(d, status) ? 1 : 0;
411 hr = hr*60*60;
412 if (hr != hour)
413 errln((UnicodeString)"FAIL: Should parse to hour " + hour + " but got " + hr);
414
415 if (U_FAILURE(status))
416 errln((UnicodeString)"FAIL: " + (int32_t)status);
417 }
418
419 // -------------------------------------
420
toHexString(int32_t i)421 UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
422
423 UnicodeString&
escape(UnicodeString & s)424 DateFormatTest::escape(UnicodeString& s)
425 {
426 UnicodeString buf;
427 for (int32_t i=0; i<s.length(); ++i)
428 {
429 UChar c = s[(int32_t)i];
430 if (c <= (UChar)0x7F) buf += c;
431 else {
432 buf += (UChar)0x5c; buf += (UChar)0x55;
433 buf += toHexString((c & 0xF000) >> 12);
434 buf += toHexString((c & 0x0F00) >> 8);
435 buf += toHexString((c & 0x00F0) >> 4);
436 buf += toHexString(c & 0x000F);
437 }
438 }
439 return (s = buf);
440 }
441
442 // -------------------------------------
443
444 /**
445 * This MUST be kept in sync with DateFormatSymbols.gPatternChars.
446 */
447 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
448 static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:";
449 #else
450 static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB";
451 #endif
452
453 /**
454 * A list of the names of all the fields in DateFormat.
455 * This MUST be kept in sync with DateFormat.
456 */
457 static const char* DATEFORMAT_FIELD_NAMES[] = {
458 "ERA_FIELD",
459 "YEAR_FIELD",
460 "MONTH_FIELD",
461 "DATE_FIELD",
462 "HOUR_OF_DAY1_FIELD",
463 "HOUR_OF_DAY0_FIELD",
464 "MINUTE_FIELD",
465 "SECOND_FIELD",
466 "MILLISECOND_FIELD",
467 "DAY_OF_WEEK_FIELD",
468 "DAY_OF_YEAR_FIELD",
469 "DAY_OF_WEEK_IN_MONTH_FIELD",
470 "WEEK_OF_YEAR_FIELD",
471 "WEEK_OF_MONTH_FIELD",
472 "AM_PM_FIELD",
473 "HOUR1_FIELD",
474 "HOUR0_FIELD",
475 "TIMEZONE_FIELD",
476 "YEAR_WOY_FIELD",
477 "DOW_LOCAL_FIELD",
478 "EXTENDED_YEAR_FIELD",
479 "JULIAN_DAY_FIELD",
480 "MILLISECONDS_IN_DAY_FIELD",
481 "TIMEZONE_RFC_FIELD",
482 "GENERIC_TIMEZONE_FIELD",
483 "STAND_ALONE_DAY_FIELD",
484 "STAND_ALONE_MONTH_FIELD",
485 "QUARTER_FIELD",
486 "STAND_ALONE_QUARTER_FIELD",
487 "TIMEZONE_SPECIAL_FIELD",
488 "YEAR_NAME_FIELD",
489 "TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD",
490 "TIMEZONE_ISO_FIELD",
491 "TIMEZONE_ISO_LOCAL_FIELD",
492 "RELATED_YEAR_FIELD",
493 "AM_PM_MIDNIGHT_NOON_FIELD",
494 "FLEXIBLE_DAY_PERIOD_FIELD",
495 "UDAT_TIME_SEPARATOR_FIELD",
496 };
497
498 static const int32_t DATEFORMAT_FIELD_NAMES_LENGTH =
499 UPRV_LENGTHOF(DATEFORMAT_FIELD_NAMES);
500
501 /**
502 * Verify that returned field position indices are correct.
503 */
TestFieldPosition()504 void DateFormatTest::TestFieldPosition() {
505 UErrorCode ec = U_ZERO_ERROR;
506 int32_t i, j, exp;
507 UnicodeString buf;
508
509 // Verify data
510 DateFormatSymbols rootSyms(Locale(""), ec);
511 if (U_FAILURE(ec)) {
512 dataerrln("Unable to create DateFormatSymbols - %s", u_errorName(ec));
513 return;
514 }
515
516 // local pattern chars data is not longer loaded
517 // from icu locale bundle
518 assertEquals("patternChars", PATTERN_CHARS, rootSyms.getLocalPatternChars(buf));
519 assertEquals("patternChars", PATTERN_CHARS, DateFormatSymbols::getPatternUChars());
520 assertTrue("DATEFORMAT_FIELD_NAMES", DATEFORMAT_FIELD_NAMES_LENGTH == UDAT_FIELD_COUNT);
521 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
522 assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS));
523 #else
524 assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS) + 1); // +1 for missing TIME_SEPARATOR pattern char
525 #endif
526
527 // Create test formatters
528 const int32_t COUNT = 4;
529 DateFormat* dateFormats[COUNT];
530 dateFormats[0] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getUS());
531 dateFormats[1] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getFrance());
532 // Make the pattern "G y M d..."
533 buf.remove().append(PATTERN_CHARS);
534 for (j=buf.length()-1; j>=0; --j) buf.insert(j, (UChar)32/*' '*/);
535 dateFormats[2] = new SimpleDateFormat(buf, Locale::getUS(), ec);
536 // Make the pattern "GGGG yyyy MMMM dddd..."
537 for (j=buf.length()-1; j>=0; j-=2) {
538 for (i=0; i<3; ++i) {
539 buf.insert(j, buf.charAt(j));
540 }
541 }
542 dateFormats[3] = new SimpleDateFormat(buf, Locale::getUS(), ec);
543 if(U_FAILURE(ec)){
544 errln(UnicodeString("Could not create SimpleDateFormat object for locale en_US. Error: " )+ UnicodeString(u_errorName(ec)));
545 return;
546 }
547 UDate aug13 = 871508052513.0;
548
549 // Expected output field values for above DateFormats on aug13
550 // Fields are given in order of DateFormat field number
551 const char* EXPECTED[] = {
552 "", "1997", "August", "13", "", "", "34", "12", "", "Wednesday",
553 "", "", "", "", "PM", "2", "", "Pacific Daylight Time", "", "",
554 "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
555 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
556 ":",
557 #else
558 "",
559 #endif
560
561 "", "1997", "ao\\u00FBt", "13", "", "14", "34", "12", "", "mercredi",
562 "", "", "", "", "", "", "", "heure d\\u2019\\u00E9t\\u00E9 du Pacifique", "", "",
563 "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
564 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
565 ":",
566 #else
567 "",
568 #endif
569
570 "AD", "1997", "8", "13", "14", "14", "34", "12", "5", "Wed",
571 "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4",
572 "1997", "2450674", "52452513", "-0700", "PT", "4", "8", "3", "3", "uslax",
573 "1997", "GMT-7", "-07", "-07", "1997", "PM", "in the afternoon",
574 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
575 ":",
576 #else
577 "",
578 #endif
579
580 "Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130", "Wednesday",
581 "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "Wednesday",
582 "1997", "2450674", "52452513", "GMT-07:00", "Pacific Time", "Wednesday", "August", "3rd quarter", "3rd quarter", "Los Angeles Time",
583 "1997", "GMT-07:00", "-0700", "-0700", "1997", "PM", "in the afternoon",
584 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
585 ":",
586 #else
587 "",
588 #endif
589 };
590
591 const int32_t EXPECTED_LENGTH = UPRV_LENGTHOF(EXPECTED);
592
593 assertTrue("data size", EXPECTED_LENGTH == COUNT * UDAT_FIELD_COUNT);
594
595 TimeZone* PT = TimeZone::createTimeZone("America/Los_Angeles");
596 for (j = 0, exp = 0; j < COUNT; ++j) {
597 // String str;
598 DateFormat* df = dateFormats[j];
599 df->setTimeZone(*PT);
600 SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
601 if (sdtfmt != NULL) {
602 logln(" Pattern = " + sdtfmt->toPattern(buf.remove()));
603 } else {
604 logln(" Pattern = ? (not a SimpleDateFormat)");
605 }
606 logln((UnicodeString)" Result = " + df->format(aug13, buf.remove()));
607
608 int32_t expBase = exp; // save for later
609 for (i = 0; i < UDAT_FIELD_COUNT; ++i, ++exp) {
610 FieldPosition pos(i);
611 buf.remove();
612 df->format(aug13, buf, pos);
613 UnicodeString field;
614 buf.extractBetween(pos.getBeginIndex(), pos.getEndIndex(), field);
615 assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
616 ctou(EXPECTED[exp]), field);
617 }
618
619 // test FieldPositionIterator API
620 logln("FieldPositionIterator");
621 {
622 UErrorCode status = U_ZERO_ERROR;
623 FieldPositionIterator posIter;
624 FieldPosition fp;
625
626 buf.remove();
627 df->format(aug13, buf, &posIter, status);
628 while (posIter.next(fp)) {
629 int32_t i = fp.getField();
630 UnicodeString field;
631 buf.extractBetween(fp.getBeginIndex(), fp.getEndIndex(), field);
632 assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
633 ctou(EXPECTED[expBase + i]), field);
634 }
635
636 }
637 }
638
639
640 // test null posIter
641 buf.remove();
642 UErrorCode status = U_ZERO_ERROR;
643 dateFormats[0]->format(aug13, buf, NULL, status);
644 // if we didn't crash, we succeeded.
645
646 for (i=0; i<COUNT; ++i) {
647 delete dateFormats[i];
648 }
649 delete PT;
650 }
651
652 // -------------------------------------
653
654 /**
655 * General parse/format tests. Add test cases as needed.
656 */
TestGeneral()657 void DateFormatTest::TestGeneral() {
658 const char* DATA[] = {
659 "yyyy MM dd HH:mm:ss.SSS",
660
661 // Milliseconds are left-justified, since they format as fractions of a second
662 "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",
663 "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",
664 "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567",
665 "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",
666 };
667 expect(DATA, UPRV_LENGTHOF(DATA), Locale("en", "", ""));
668 }
669
670 // -------------------------------------
671
672 /**
673 * Verify that strings which contain incomplete specifications are parsed
674 * correctly. In some instances, this means not being parsed at all, and
675 * returning an appropriate error.
676 */
677 void
TestPartialParse994()678 DateFormatTest::TestPartialParse994()
679 {
680 UErrorCode status = U_ZERO_ERROR;
681 SimpleDateFormat* f = new SimpleDateFormat(status);
682 if (U_FAILURE(status)) {
683 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
684 delete f;
685 return;
686 }
687 UDate null = 0;
688 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", date(97, 1 - 1, 17, 10, 11, 42));
689 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null);
690 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null);
691 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null);
692 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null);
693 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
694 delete f;
695 }
696
697 // -------------------------------------
698
699 void
tryPat994(SimpleDateFormat * format,const char * pat,const char * str,UDate expected)700 DateFormatTest::tryPat994(SimpleDateFormat* format, const char* pat, const char* str, UDate expected)
701 {
702 UErrorCode status = U_ZERO_ERROR;
703 UDate null = 0;
704 logln(UnicodeString("Pattern \"") + pat + "\" String \"" + str + "\"");
705 //try {
706 format->applyPattern(pat);
707 UDate date = format->parse(str, status);
708 if (U_FAILURE(status) || date == null)
709 {
710 logln((UnicodeString)"ParseException: " + (int32_t)status);
711 if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
712 }
713 else
714 {
715 UnicodeString f;
716 ((DateFormat*)format)->format(date, f);
717 logln(UnicodeString(" parse(") + str + ") -> " + dateToString(date));
718 logln((UnicodeString)" format -> " + f);
719 if (expected == null ||
720 !(date == expected)) errln((UnicodeString)"FAIL: Expected null");//" + expected);
721 if (!(f == str)) errln(UnicodeString("FAIL: Expected ") + str);
722 }
723 //}
724 //catch(ParseException e) {
725 // logln((UnicodeString)"ParseException: " + e.getMessage());
726 // if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
727 //}
728 //catch(Exception e) {
729 // errln((UnicodeString)"*** Exception:");
730 // e.printStackTrace();
731 //}
732 }
733
734 // -------------------------------------
735
736 /**
737 * Verify the behavior of patterns in which digits for different fields run together
738 * without intervening separators.
739 */
740 void
TestRunTogetherPattern985()741 DateFormatTest::TestRunTogetherPattern985()
742 {
743 UErrorCode status = U_ZERO_ERROR;
744 UnicodeString format("yyyyMMddHHmmssSSS");
745 UnicodeString now, then;
746 //UBool flag;
747 SimpleDateFormat *formatter = new SimpleDateFormat(format, status);
748 if (U_FAILURE(status)) {
749 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
750 delete formatter;
751 return;
752 }
753 UDate date1 = Calendar::getNow();
754 ((DateFormat*)formatter)->format(date1, now);
755 logln(now);
756 ParsePosition pos(0);
757 UDate date2 = formatter->parse(now, pos);
758 if (date2 == 0) then = UnicodeString("Parse stopped at ") + pos.getIndex();
759 else ((DateFormat*)formatter)->format(date2, then);
760 logln(then);
761 if (!(date2 == date1)) errln((UnicodeString)"FAIL");
762 delete formatter;
763 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
764 }
765
766 // -------------------------------------
767
768 /**
769 * Verify the behavior of patterns in which digits for different fields run together
770 * without intervening separators.
771 */
772 void
TestRunTogetherPattern917()773 DateFormatTest::TestRunTogetherPattern917()
774 {
775 UErrorCode status = U_ZERO_ERROR;
776 SimpleDateFormat* fmt;
777 UnicodeString myDate;
778 fmt = new SimpleDateFormat((UnicodeString)"yyyy/MM/dd", status);
779 if (U_FAILURE(status)) {
780 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
781 delete fmt;
782 return;
783 }
784 myDate = "1997/02/03";
785 testIt917(fmt, myDate, date(97, 2 - 1, 3));
786 delete fmt;
787 fmt = new SimpleDateFormat((UnicodeString)"yyyyMMdd", status);
788 myDate = "19970304";
789 testIt917(fmt, myDate, date(97, 3 - 1, 4));
790 delete fmt;
791 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
792 }
793
794 // -------------------------------------
795
796 void
testIt917(SimpleDateFormat * fmt,UnicodeString & str,UDate expected)797 DateFormatTest::testIt917(SimpleDateFormat* fmt, UnicodeString& str, UDate expected)
798 {
799 UErrorCode status = U_ZERO_ERROR;
800 UnicodeString pattern;
801 logln((UnicodeString)"pattern=" + fmt->toPattern(pattern) + " string=" + str);
802 Formattable o;
803 //try {
804 ((Format*)fmt)->parseObject(str, o, status);
805 //}
806 if (U_FAILURE(status)) return;
807 //catch(ParseException e) {
808 // e.printStackTrace();
809 // return;
810 //}
811 logln((UnicodeString)"Parsed object: " + dateToString(o.getDate()));
812 if (!(o.getDate() == expected)) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
813 UnicodeString formatted; ((Format*)fmt)->format(o, formatted, status);
814 logln((UnicodeString)"Formatted string: " + formatted);
815 if (!(formatted == str)) errln((UnicodeString)"FAIL: Expected " + str);
816 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
817 }
818
819 // -------------------------------------
820
821 /**
822 * Verify the handling of Czech June and July, which have the unique attribute that
823 * one is a proper prefix substring of the other.
824 */
825 void
TestCzechMonths459()826 DateFormatTest::TestCzechMonths459()
827 {
828 UErrorCode status = U_ZERO_ERROR;
829 DateFormat* fmt = DateFormat::createDateInstance(DateFormat::FULL, Locale("cs", "", ""));
830 if (fmt == NULL){
831 dataerrln("Error calling DateFormat::createDateInstance()");
832 return;
833 }
834
835 UnicodeString pattern;
836 logln((UnicodeString)"Pattern " + ((SimpleDateFormat*) fmt)->toPattern(pattern));
837 UDate june = date(97, UCAL_JUNE, 15);
838 UDate july = date(97, UCAL_JULY, 15);
839 UnicodeString juneStr; fmt->format(june, juneStr);
840 UnicodeString julyStr; fmt->format(july, julyStr);
841 //try {
842 logln((UnicodeString)"format(June 15 1997) = " + juneStr);
843 UDate d = fmt->parse(juneStr, status);
844 UnicodeString s; fmt->format(d, s);
845 int32_t month,yr,day,hr,min,sec; dateToFields(d,yr,month,day,hr,min,sec);
846 logln((UnicodeString)" -> parse -> " + s + " (month = " + month + ")");
847 if (month != UCAL_JUNE) errln((UnicodeString)"FAIL: Month should be June");
848 logln((UnicodeString)"format(July 15 1997) = " + julyStr);
849 d = fmt->parse(julyStr, status);
850 fmt->format(d, s);
851 dateToFields(d,yr,month,day,hr,min,sec);
852 logln((UnicodeString)" -> parse -> " + s + " (month = " + month + ")");
853 if (month != UCAL_JULY) errln((UnicodeString)"FAIL: Month should be July");
854 //}
855 //catch(ParseException e) {
856 if (U_FAILURE(status))
857 errln((UnicodeString)"Exception: " + (int32_t)status);
858 //}
859 delete fmt;
860 }
861
862 // -------------------------------------
863
864 /**
865 * Test the handling of 'D' in patterns.
866 */
867 void
TestLetterDPattern212()868 DateFormatTest::TestLetterDPattern212()
869 {
870 UErrorCode status = U_ZERO_ERROR;
871 UnicodeString dateString("1995-040.05:01:29");
872 UnicodeString bigD("yyyy-DDD.hh:mm:ss");
873 UnicodeString littleD("yyyy-ddd.hh:mm:ss");
874 UDate expLittleD = date(95, 0, 1, 5, 1, 29);
875 UDate expBigD = expLittleD + 39 * 24 * 3600000.0;
876 expLittleD = expBigD; // Expect the same, with default lenient parsing
877 logln((UnicodeString)"dateString= " + dateString);
878 SimpleDateFormat *formatter = new SimpleDateFormat(bigD, status);
879 if (U_FAILURE(status)) {
880 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
881 delete formatter;
882 return;
883 }
884 ParsePosition pos(0);
885 UDate myDate = formatter->parse(dateString, pos);
886 logln((UnicodeString)"Using " + bigD + " -> " + myDate);
887 if (myDate != expBigD) errln((UnicodeString)"FAIL: bigD - Expected " + dateToString(expBigD));
888 delete formatter;
889 formatter = new SimpleDateFormat(littleD, status);
890 ASSERT_OK(status);
891 pos = ParsePosition(0);
892 myDate = formatter->parse(dateString, pos);
893 logln((UnicodeString)"Using " + littleD + " -> " + dateToString(myDate));
894 if (myDate != expLittleD) errln((UnicodeString)"FAIL: littleD - Expected " + dateToString(expLittleD));
895 delete formatter;
896 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
897 }
898
899 // -------------------------------------
900
901 /**
902 * Test the day of year pattern.
903 */
904 void
TestDayOfYearPattern195()905 DateFormatTest::TestDayOfYearPattern195()
906 {
907 UErrorCode status = U_ZERO_ERROR;
908 UDate today = Calendar::getNow();
909 int32_t year,month,day,hour,min,sec; dateToFields(today,year,month,day,hour,min,sec);
910 UDate expected = date(year, month, day);
911 logln((UnicodeString)"Test Date: " + dateToString(today));
912 SimpleDateFormat* sdf = (SimpleDateFormat*)DateFormat::createDateInstance();
913 if (sdf == NULL){
914 dataerrln("Error calling DateFormat::createDateInstance()");
915 return;
916 }
917 tryPattern(*sdf, today, 0, expected);
918 tryPattern(*sdf, today, "G yyyy DDD", expected);
919 delete sdf;
920 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
921 }
922
923 // -------------------------------------
924
925 void
tryPattern(SimpleDateFormat & sdf,UDate d,const char * pattern,UDate expected)926 DateFormatTest::tryPattern(SimpleDateFormat& sdf, UDate d, const char* pattern, UDate expected)
927 {
928 UErrorCode status = U_ZERO_ERROR;
929 if (pattern != 0) sdf.applyPattern(pattern);
930 UnicodeString thePat;
931 logln((UnicodeString)"pattern: " + sdf.toPattern(thePat));
932 UnicodeString formatResult; (*(DateFormat*)&sdf).format(d, formatResult);
933 logln((UnicodeString)" format -> " + formatResult);
934 // try {
935 UDate d2 = sdf.parse(formatResult, status);
936 logln((UnicodeString)" parse(" + formatResult + ") -> " + dateToString(d2));
937 if (d2 != expected) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
938 UnicodeString format2; (*(DateFormat*)&sdf).format(d2, format2);
939 logln((UnicodeString)" format -> " + format2);
940 if (!(formatResult == format2)) errln((UnicodeString)"FAIL: Round trip drift");
941 //}
942 //catch(Exception e) {
943 if (U_FAILURE(status))
944 errln((UnicodeString)"Error: " + (int32_t)status);
945 //}
946 }
947
948 // -------------------------------------
949
950 /**
951 * Test the handling of single quotes in patterns.
952 */
953 void
TestQuotePattern161()954 DateFormatTest::TestQuotePattern161()
955 {
956 UErrorCode status = U_ZERO_ERROR;
957 SimpleDateFormat* formatter = new SimpleDateFormat((UnicodeString)"MM/dd/yyyy 'at' hh:mm:ss a zzz", status);
958 if (U_FAILURE(status)) {
959 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
960 delete formatter;
961 return;
962 }
963 UDate currentTime_1 = date(97, UCAL_AUGUST, 13, 10, 42, 28);
964 UnicodeString dateString; ((DateFormat*)formatter)->format(currentTime_1, dateString);
965 UnicodeString exp("08/13/1997 at 10:42:28 AM ");
966 logln((UnicodeString)"format(" + dateToString(currentTime_1) + ") = " + dateString);
967 if (0 != dateString.compareBetween(0, exp.length(), exp, 0, exp.length())) errln((UnicodeString)"FAIL: Expected " + exp);
968 delete formatter;
969 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
970 }
971
972 // -------------------------------------
973
974 /**
975 * Verify the correct behavior when handling invalid input strings.
976 */
977 void
TestBadInput135()978 DateFormatTest::TestBadInput135()
979 {
980 UErrorCode status = U_ZERO_ERROR;
981 DateFormat::EStyle looks[] = {
982 DateFormat::SHORT, DateFormat::MEDIUM, DateFormat::LONG, DateFormat::FULL
983 };
984 int32_t looks_length = UPRV_LENGTHOF(looks);
985 const char* strings[] = {
986 "Mar 15", "Mar 15 1997", "asdf", "3/1/97 1:23:", "3/1/00 1:23:45 AM"
987 };
988 int32_t strings_length = UPRV_LENGTHOF(strings);
989 DateFormat *full = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::LONG);
990 if(full==NULL) {
991 dataerrln("could not create date time instance");
992 return;
993 }
994 UnicodeString expected("March 1, 2000 at 1:23:45 AM ");
995 for (int32_t i = 0; i < strings_length;++i) {
996 const char* text = strings[i];
997 for (int32_t j = 0; j < looks_length;++j) {
998 DateFormat::EStyle dateLook = looks[j];
999 for (int32_t k = 0; k < looks_length;++k) {
1000 DateFormat::EStyle timeLook = looks[k];
1001 DateFormat *df = DateFormat::createDateTimeInstance(dateLook, timeLook);
1002 if (df == NULL){
1003 dataerrln("Error calling DateFormat::createDateTimeInstance()");
1004 continue;
1005 }
1006 UnicodeString prefix = UnicodeString(text) + ", " + dateLook + "/" + timeLook + ": ";
1007 //try {
1008 UDate when = df->parse(text, status);
1009 if (when == 0 && U_SUCCESS(status)) {
1010 errln(prefix + "SHOULD NOT HAPPEN: parse returned 0.");
1011 continue;
1012 }
1013 if (U_SUCCESS(status))
1014 {
1015 UnicodeString format;
1016 UnicodeString pattern;
1017 SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
1018 if (sdtfmt != NULL) {
1019 sdtfmt->toPattern(pattern);
1020 }
1021 full->format(when, format);
1022 logln(prefix + "OK: " + format);
1023 if (0!=format.compareBetween(0, expected.length(), expected, 0, expected.length()))
1024 errln((UnicodeString)"FAIL: Parse \"" + text + "\", pattern \"" + pattern + "\", expected " + expected + " got " + format);
1025 }
1026 //}
1027 //catch(ParseException e) {
1028 else
1029 status = U_ZERO_ERROR;
1030 //}
1031 //catch(StringIndexOutOfBoundsException e) {
1032 // errln(prefix + "SHOULD NOT HAPPEN: " + (int)status);
1033 //}
1034 delete df;
1035 }
1036 }
1037 }
1038 delete full;
1039 if (U_FAILURE(status))
1040 errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1041 }
1042
1043 static const char* const parseFormats[] = {
1044 "MMMM d, yyyy",
1045 "MMMM d yyyy",
1046 "M/d/yy",
1047 "d MMMM, yyyy",
1048 "d MMMM yyyy",
1049 "d MMMM",
1050 "MMMM d",
1051 "yyyy",
1052 "h:mm a MMMM d, yyyy"
1053 };
1054
1055 #if 0
1056 // strict inputStrings
1057 static const char* const inputStrings[] = {
1058 "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1059 "April 1, 1997", "April 1, 1997", 0, 0, 0, 0, 0, "April 1", 0, 0,
1060 "Jan 1, 1970", "January 1, 1970", 0, 0, 0, 0, 0, "January 1", 0, 0,
1061 "Jan 1 2037", 0, "January 1 2037", 0, 0, 0, 0, "January 1", 0, 0,
1062 "1/1/70", 0, 0, "1/1/70", 0, 0, 0, 0, "0001", 0,
1063 "5 May 1997", 0, 0, 0, 0, "5 May 1997", "5 May", 0, "0005", 0,
1064 "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1065 "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1066 "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1067 "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1068 "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1069 };
1070 #else
1071 // lenient inputStrings
1072 static const char* const inputStrings[] = {
1073 "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1074 "April 1, 1997", "April 1, 1997", "April 1 1997", "4/1/97", 0, 0, 0, "April 1", 0, 0,
1075 "Jan 1, 1970", "January 1, 1970", "January 1 1970", "1/1/70", 0, 0, 0, "January 1", 0, 0,
1076 "Jan 1 2037", "January 1, 2037", "January 1 2037", "1/1/37", 0, 0, 0, "January 1", 0, 0,
1077 "1/1/70", "January 1, 0070", "January 1 0070", "1/1/70", "1 January, 0070", "1 January 0070", "1 January", "January 1", "0001", 0,
1078 "5 May 1997", 0, 0, 0, "5 May, 1997", "5 May 1997", "5 May", 0, "0005", 0,
1079 "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1080 "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1081 "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1082 "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1083 "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1084 };
1085 #endif
1086
1087 // -------------------------------------
1088
1089 /**
1090 * Verify the correct behavior when parsing an array of inputs against an
1091 * array of patterns, with known results. The results are encoded after
1092 * the input strings in each row.
1093 */
1094 void
TestBadInput135a()1095 DateFormatTest::TestBadInput135a()
1096 {
1097 UErrorCode status = U_ZERO_ERROR;
1098 SimpleDateFormat* dateParse = new SimpleDateFormat(status);
1099 if(U_FAILURE(status)) {
1100 dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1101 delete dateParse;
1102 return;
1103 }
1104 const char* s;
1105 UDate date;
1106 const uint32_t PF_LENGTH = UPRV_LENGTHOF(parseFormats);
1107 const uint32_t INPUT_LENGTH = UPRV_LENGTHOF(inputStrings);
1108
1109 dateParse->applyPattern("d MMMM, yyyy");
1110 dateParse->adoptTimeZone(TimeZone::createDefault());
1111 s = "not parseable";
1112 UnicodeString thePat;
1113 logln(UnicodeString("Trying to parse \"") + s + "\" with " + dateParse->toPattern(thePat));
1114 //try {
1115 date = dateParse->parse(s, status);
1116 if (U_SUCCESS(status))
1117 errln((UnicodeString)"FAIL: Expected exception during parse");
1118 //}
1119 //catch(Exception ex) {
1120 else
1121 logln((UnicodeString)"Exception during parse: " + (int32_t)status);
1122 status = U_ZERO_ERROR;
1123 //}
1124 for (uint32_t i = 0; i < INPUT_LENGTH; i += (PF_LENGTH + 1)) {
1125 ParsePosition parsePosition(0);
1126 UnicodeString s( inputStrings[i]);
1127 for (uint32_t index = 0; index < PF_LENGTH;++index) {
1128 const char* expected = inputStrings[i + 1 + index];
1129 dateParse->applyPattern(parseFormats[index]);
1130 dateParse->adoptTimeZone(TimeZone::createDefault());
1131 //try {
1132 parsePosition.setIndex(0);
1133 date = dateParse->parse(s, parsePosition);
1134 if (parsePosition.getIndex() != 0) {
1135 UnicodeString s1, s2;
1136 s.extract(0, parsePosition.getIndex(), s1);
1137 s.extract(parsePosition.getIndex(), s.length(), s2);
1138 if (date == 0) {
1139 errln((UnicodeString)"ERROR: null result fmt=\"" +
1140 parseFormats[index] +
1141 "\" pos=" + parsePosition.getIndex() + " " +
1142 s1 + "|" + s2);
1143 }
1144 else {
1145 UnicodeString result;
1146 ((DateFormat*)dateParse)->format(date, result);
1147 logln((UnicodeString)"Parsed \"" + s + "\" using \"" + dateParse->toPattern(thePat) + "\" to: " + result);
1148 if (expected == 0)
1149 errln((UnicodeString)"FAIL: Expected parse failure, got " + result);
1150 else if (!(result == expected))
1151 errln(UnicodeString("FAIL: Parse \"") + s + UnicodeString("\", expected ") + expected + UnicodeString(", got ") + result);
1152 }
1153 }
1154 else if (expected != 0) {
1155 errln(UnicodeString("FAIL: Expected ") + expected + " from \"" +
1156 s + "\" with \"" + dateParse->toPattern(thePat) + "\"");
1157 }
1158 //}
1159 //catch(Exception ex) {
1160 if (U_FAILURE(status))
1161 errln((UnicodeString)"An exception was thrown during parse: " + (int32_t)status);
1162 //}
1163 }
1164 }
1165 delete dateParse;
1166 if (U_FAILURE(status))
1167 errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1168 }
1169
1170 // -------------------------------------
1171
1172 /**
1173 * Test the parsing of two-digit years.
1174 */
1175 void
TestTwoDigitYear()1176 DateFormatTest::TestTwoDigitYear()
1177 {
1178 UErrorCode ec = U_ZERO_ERROR;
1179 SimpleDateFormat fmt("dd/MM/yy", Locale::getUK(), ec);
1180 if (U_FAILURE(ec)) {
1181 dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1182 return;
1183 }
1184 parse2DigitYear(fmt, "5/6/30", date(130, UCAL_JUNE, 5));
1185 parse2DigitYear(fmt, "4/6/50", date(50, UCAL_JUNE, 4));
1186 }
1187
1188 // -------------------------------------
1189
1190 void
parse2DigitYear(DateFormat & fmt,const char * str,UDate expected)1191 DateFormatTest::parse2DigitYear(DateFormat& fmt, const char* str, UDate expected)
1192 {
1193 UErrorCode status = U_ZERO_ERROR;
1194 //try {
1195 UDate d = fmt.parse(str, status);
1196 UnicodeString thePat;
1197 logln(UnicodeString("Parsing \"") + str + "\" with " + ((SimpleDateFormat*)&fmt)->toPattern(thePat) +
1198 " => " + dateToString(d));
1199 if (d != expected) errln((UnicodeString)"FAIL: Expected " + expected);
1200 //}
1201 //catch(ParseException e) {
1202 if (U_FAILURE(status))
1203 errln((UnicodeString)"FAIL: Got exception");
1204 //}
1205 }
1206
1207 // -------------------------------------
1208
1209 /**
1210 * Test the formatting of time zones.
1211 */
1212 void
TestDateFormatZone061()1213 DateFormatTest::TestDateFormatZone061()
1214 {
1215 UErrorCode status = U_ZERO_ERROR;
1216 UDate date;
1217 DateFormat *formatter;
1218 date= 859248000000.0;
1219 logln((UnicodeString)"Date 1997/3/25 00:00 GMT: " + date);
1220 formatter = new SimpleDateFormat((UnicodeString)"dd-MMM-yyyyy HH:mm", Locale::getUK(), status);
1221 if(U_FAILURE(status)) {
1222 dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1223 delete formatter;
1224 return;
1225 }
1226 formatter->adoptTimeZone(TimeZone::createTimeZone("GMT"));
1227 UnicodeString temp; formatter->format(date, temp);
1228 logln((UnicodeString)"Formatted in GMT to: " + temp);
1229 //try {
1230 UDate tempDate = formatter->parse(temp, status);
1231 logln((UnicodeString)"Parsed to: " + dateToString(tempDate));
1232 if (tempDate != date) errln((UnicodeString)"FAIL: Expected " + dateToString(date));
1233 //}
1234 //catch(Throwable t) {
1235 if (U_FAILURE(status))
1236 errln((UnicodeString)"Date Formatter throws: " + (int32_t)status);
1237 //}
1238 delete formatter;
1239 }
1240
1241 // -------------------------------------
1242
1243 /**
1244 * Test the formatting of time zones.
1245 */
1246 void
TestDateFormatZone146()1247 DateFormatTest::TestDateFormatZone146()
1248 {
1249 TimeZone *saveDefault = TimeZone::createDefault();
1250
1251 //try {
1252 TimeZone *thedefault = TimeZone::createTimeZone("GMT");
1253 TimeZone::setDefault(*thedefault);
1254 // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
1255
1256 // check to be sure... its GMT all right
1257 TimeZone *testdefault = TimeZone::createDefault();
1258 UnicodeString testtimezone;
1259 testdefault->getID(testtimezone);
1260 if (testtimezone == "GMT")
1261 logln("Test timezone = " + testtimezone);
1262 else
1263 dataerrln("Test timezone should be GMT, not " + testtimezone);
1264
1265 UErrorCode status = U_ZERO_ERROR;
1266 // now try to use the default GMT time zone
1267 GregorianCalendar *greenwichcalendar =
1268 new GregorianCalendar(1997, 3, 4, 23, 0, status);
1269 if (U_FAILURE(status)) {
1270 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
1271 } else {
1272 //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
1273 //greenwichcalendar.set(1997, 3, 4, 23, 0);
1274 // try anything to set hour to 23:00 !!!
1275 greenwichcalendar->set(UCAL_HOUR_OF_DAY, 23);
1276 // get time
1277 UDate greenwichdate = greenwichcalendar->getTime(status);
1278 // format every way
1279 UnicodeString DATA [] = {
1280 UnicodeString("simple format: "), UnicodeString("04/04/97 23:00 GMT"),
1281 UnicodeString("MM/dd/yy HH:mm z"),
1282 UnicodeString("full format: "), UnicodeString("Friday, April 4, 1997 11:00:00 o'clock PM GMT"),
1283 UnicodeString("EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z"),
1284 UnicodeString("long format: "), UnicodeString("April 4, 1997 11:00:00 PM GMT"),
1285 UnicodeString("MMMM d, yyyy h:mm:ss a z"),
1286 UnicodeString("default format: "), UnicodeString("04-Apr-97 11:00:00 PM"),
1287 UnicodeString("dd-MMM-yy h:mm:ss a"),
1288 UnicodeString("short format: "), UnicodeString("4/4/97 11:00 PM"),
1289 UnicodeString("M/d/yy h:mm a")
1290 };
1291 int32_t DATA_length = UPRV_LENGTHOF(DATA);
1292
1293 for (int32_t i=0; i<DATA_length; i+=3) {
1294 SimpleDateFormat fmt(DATA[i+2], Locale::getEnglish(), status);
1295 if (U_FAILURE(status)) {
1296 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
1297 break;
1298 }
1299 fmt.setCalendar(*greenwichcalendar);
1300 UnicodeString result;
1301 result = fmt.format(greenwichdate, result);
1302 logln(DATA[i] + result);
1303 if (result != DATA[i+1])
1304 errln("FAIL: Expected " + DATA[i+1] + ", got " + result);
1305 }
1306 }
1307 //}
1308 //finally {
1309 TimeZone::adoptDefault(saveDefault);
1310 //}
1311 delete testdefault;
1312 delete greenwichcalendar;
1313 delete thedefault;
1314
1315
1316 }
1317
1318 // -------------------------------------
1319
1320 /**
1321 * Test the formatting of dates in different locales.
1322 */
1323 void
TestLocaleDateFormat()1324 DateFormatTest::TestLocaleDateFormat() // Bug 495
1325 {
1326 UDate testDate = date(97, UCAL_SEPTEMBER, 15);
1327 DateFormat *dfFrench = DateFormat::createDateTimeInstance(DateFormat::FULL,
1328 DateFormat::FULL, Locale::getFrench());
1329 DateFormat *dfUS = DateFormat::createDateTimeInstance(DateFormat::FULL,
1330 DateFormat::FULL, Locale::getUS());
1331 UnicodeString expectedFRENCH ( "lundi 15 septembre 1997 \\u00E0 00:00:00 heure d\\u2019\\u00E9t\\u00E9 du Pacifique", -1, US_INV );
1332 expectedFRENCH = expectedFRENCH.unescape();
1333 UnicodeString expectedUS ( "Monday, September 15, 1997 at 12:00:00 AM Pacific Daylight Time" );
1334 logln((UnicodeString)"Date set to : " + dateToString(testDate));
1335 UnicodeString out;
1336 if (dfUS == NULL || dfFrench == NULL){
1337 dataerrln("Error calling DateFormat::createDateTimeInstance)");
1338 delete dfUS;
1339 delete dfFrench;
1340 return;
1341 }
1342
1343 dfFrench->format(testDate, out);
1344 logln((UnicodeString)"Date Formated with French Locale " + out);
1345 if (!(out == expectedFRENCH))
1346 errln((UnicodeString)"FAIL: Expected " + expectedFRENCH);
1347 out.truncate(0);
1348 dfUS->format(testDate, out);
1349 logln((UnicodeString)"Date Formated with US Locale " + out);
1350 if (!(out == expectedUS))
1351 errln((UnicodeString)"FAIL: Expected " + expectedUS);
1352 delete dfUS;
1353 delete dfFrench;
1354 }
1355
1356 void
TestFormattingLocaleTimeSeparator()1357 DateFormatTest::TestFormattingLocaleTimeSeparator()
1358 {
1359 // This test not as useful as it once was, since timeSeparator
1360 // in the Arabic locale is changed back to ":" in CLDR 28.
1361 const UDate testDate = 874266720000.; // Sun Sep 14 21:52:00 CET 1997
1362 logln((UnicodeString)"Date set to : " + dateToString(testDate));
1363
1364 const LocalPointer<const TimeZone> tz(TimeZone::createTimeZone("CET"));
1365
1366 const LocalPointer<DateFormat> dfArab(DateFormat::createTimeInstance(
1367 DateFormat::SHORT, Locale("ar", "EG")));
1368
1369 const LocalPointer<DateFormat> dfLatn(DateFormat::createTimeInstance(
1370 DateFormat::SHORT, Locale("ar", "EG", NULL, "numbers=latn")));
1371
1372 if (dfLatn.isNull() || dfArab.isNull()) {
1373 dataerrln("Error calling DateFormat::createTimeInstance()");
1374 return;
1375 }
1376
1377 dfArab->setTimeZone(*tz);
1378 dfLatn->setTimeZone(*tz);
1379
1380 const UnicodeString expectedArab = UnicodeString(
1381 "\\u0669:\\u0665\\u0662 \\u0645", -1, US_INV).unescape();
1382
1383 const UnicodeString expectedLatn = UnicodeString(
1384 "9:52 \\u0645", -1, US_INV).unescape();
1385
1386 UnicodeString actualArab;
1387 UnicodeString actualLatn;
1388
1389 dfArab->format(testDate, actualArab);
1390 dfLatn->format(testDate, actualLatn);
1391
1392 assertEquals("Arab", expectedArab, actualArab);
1393 assertEquals("Latn", expectedLatn, actualLatn);
1394 }
1395
1396 /**
1397 * Test DateFormat(Calendar) API
1398 */
TestDateFormatCalendar()1399 void DateFormatTest::TestDateFormatCalendar() {
1400 DateFormat *date=0, *time=0, *full=0;
1401 Calendar *cal=0;
1402 UnicodeString str;
1403 ParsePosition pos;
1404 UDate when;
1405 UErrorCode ec = U_ZERO_ERROR;
1406
1407 /* Create a formatter for date fields. */
1408 date = DateFormat::createDateInstance(DateFormat::kShort, Locale::getUS());
1409 if (date == NULL) {
1410 dataerrln("FAIL: createDateInstance failed");
1411 goto FAIL;
1412 }
1413
1414 /* Create a formatter for time fields. */
1415 time = DateFormat::createTimeInstance(DateFormat::kShort, Locale::getUS());
1416 if (time == NULL) {
1417 errln("FAIL: createTimeInstance failed");
1418 goto FAIL;
1419 }
1420
1421 /* Create a full format for output */
1422 full = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull,
1423 Locale::getUS());
1424 if (full == NULL) {
1425 errln("FAIL: createInstance failed");
1426 goto FAIL;
1427 }
1428
1429 /* Create a calendar */
1430 cal = Calendar::createInstance(Locale::getUS(), ec);
1431 if (cal == NULL || U_FAILURE(ec)) {
1432 errln((UnicodeString)"FAIL: Calendar::createInstance failed with " +
1433 u_errorName(ec));
1434 goto FAIL;
1435 }
1436
1437 /* Parse the date */
1438 cal->clear();
1439 str = UnicodeString("4/5/2001", "");
1440 pos.setIndex(0);
1441 date->parse(str, *cal, pos);
1442 if (pos.getIndex() != str.length()) {
1443 errln((UnicodeString)"FAIL: DateFormat::parse(4/5/2001) failed at " +
1444 pos.getIndex());
1445 goto FAIL;
1446 }
1447
1448 /* Parse the time */
1449 str = UnicodeString("5:45 PM", "");
1450 pos.setIndex(0);
1451 time->parse(str, *cal, pos);
1452 if (pos.getIndex() != str.length()) {
1453 errln((UnicodeString)"FAIL: DateFormat::parse(17:45) failed at " +
1454 pos.getIndex());
1455 goto FAIL;
1456 }
1457
1458 /* Check result */
1459 when = cal->getTime(ec);
1460 if (U_FAILURE(ec)) {
1461 errln((UnicodeString)"FAIL: cal->getTime() failed with " + u_errorName(ec));
1462 goto FAIL;
1463 }
1464 str.truncate(0);
1465 full->format(when, str);
1466 // Thursday, April 5, 2001 5:45:00 PM PDT 986517900000
1467 if (when == 986517900000.0) {
1468 logln("Ok: Parsed result: " + str);
1469 } else {
1470 errln("FAIL: Parsed result: " + str + ", exp 4/5/2001 5:45 PM");
1471 }
1472
1473 FAIL:
1474 delete date;
1475 delete time;
1476 delete full;
1477 delete cal;
1478 }
1479
1480 /**
1481 * Test DateFormat's parsing of space characters. See jitterbug 1916.
1482 */
TestSpaceParsing()1483 void DateFormatTest::TestSpaceParsing() {
1484 const char* DATA[] = {
1485 "yyyy MM dd HH:mm:ss",
1486
1487 // pattern, input, expected parse or NULL if expect parse failure
1488 "MMMM d yy", " 04 05 06", "2006 04 05 00:00:00",
1489 NULL, "04 05 06", "2006 04 05 00:00:00",
1490
1491 "MM d yy", " 04 05 06", "2006 04 05 00:00:00",
1492 NULL, "04 05 06", "2006 04 05 00:00:00",
1493 NULL, "04/05/06", "2006 04 05 00:00:00",
1494 NULL, "04-05-06", "2006 04 05 00:00:00",
1495 NULL, "04.05.06", "2006 04 05 00:00:00",
1496 NULL, "04 / 05 / 06", "2006 04 05 00:00:00",
1497 NULL, "Apr / 05/ 06", "2006 04 05 00:00:00",
1498 NULL, "Apr-05-06", "2006 04 05 00:00:00",
1499 NULL, "Apr 05, 2006", "2006 04 05 00:00:00",
1500
1501 "MMMM d yy", " Apr 05 06", "2006 04 05 00:00:00",
1502 NULL, "Apr 05 06", "2006 04 05 00:00:00",
1503 NULL, "Apr05 06", "2006 04 05 00:00:00",
1504
1505 "hh:mm:ss a", "12:34:56 PM", "1970 01 01 12:34:56",
1506 NULL, "12:34:56PM", "1970 01 01 12:34:56",
1507 NULL, "12.34.56PM", "1970 01 01 12:34:56",
1508 NULL, "12 : 34 : 56 PM", "1970 01 01 12:34:56",
1509
1510 "MM d yy 'at' hh:mm:ss a", "04/05/06 12:34:56 PM", "2006 04 05 12:34:56",
1511
1512 "MMMM dd yyyy hh:mm a", "September 27, 1964 21:56 PM", "1964 09 28 09:56:00",
1513 NULL, "November 4, 2008 0:13 AM", "2008 11 04 00:13:00",
1514
1515 "HH'h'mm'min'ss's'", "12h34min56s", "1970 01 01 12:34:56",
1516 NULL, "12h34mi56s", "1970 01 01 12:34:56",
1517 NULL, "12h34m56s", "1970 01 01 12:34:56",
1518 NULL, "12:34:56", "1970 01 01 12:34:56"
1519 };
1520 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1521
1522 expectParse(DATA, DATA_len, Locale("en"));
1523 }
1524
1525 /**
1526 * Test handling of "HHmmss" pattern.
1527 */
TestExactCountFormat()1528 void DateFormatTest::TestExactCountFormat() {
1529 const char* DATA[] = {
1530 "yyyy MM dd HH:mm:ss",
1531
1532 // pattern, input, expected parse or NULL if expect parse failure
1533 "HHmmss", "123456", "1970 01 01 12:34:56",
1534 NULL, "12345", "1970 01 01 01:23:45",
1535 NULL, "1234", NULL,
1536 NULL, "00-05", NULL,
1537 NULL, "12-34", NULL,
1538 NULL, "00+05", NULL,
1539 "ahhmm", "PM730", "1970 01 01 19:30:00",
1540 };
1541 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1542
1543 expectParse(DATA, DATA_len, Locale("en"));
1544 }
1545
1546 /**
1547 * Test handling of white space.
1548 */
TestWhiteSpaceParsing()1549 void DateFormatTest::TestWhiteSpaceParsing() {
1550 const char* DATA[] = {
1551 "yyyy MM dd",
1552
1553 // pattern, input, expected parse or null if expect parse failure
1554
1555 // Pattern space run should parse input text space run
1556 "MM d yy", " 04 01 03", "2003 04 01",
1557 NULL, " 04 01 03 ", "2003 04 01",
1558 };
1559 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1560
1561 expectParse(DATA, DATA_len, Locale("en"));
1562 }
1563
1564
TestInvalidPattern()1565 void DateFormatTest::TestInvalidPattern() {
1566 UErrorCode ec = U_ZERO_ERROR;
1567 SimpleDateFormat f(UnicodeString("Yesterday"), ec);
1568 if (U_FAILURE(ec)) {
1569 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1570 return;
1571 }
1572 UnicodeString out;
1573 FieldPosition pos;
1574 f.format((UDate)0, out, pos);
1575 logln(out);
1576 // The bug is that the call to format() will crash. By not
1577 // crashing, the test passes.
1578 }
1579
TestGreekMay()1580 void DateFormatTest::TestGreekMay() {
1581 UErrorCode ec = U_ZERO_ERROR;
1582 UDate date = -9896080848000.0;
1583 SimpleDateFormat fmt("EEEE, dd MMMM yyyy h:mm:ss a", Locale("el", "", ""), ec);
1584 if (U_FAILURE(ec)) {
1585 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1586 return;
1587 }
1588 UnicodeString str;
1589 fmt.format(date, str);
1590 ParsePosition pos(0);
1591 UDate d2 = fmt.parse(str, pos);
1592 if (date != d2) {
1593 errln("FAIL: unable to parse strings where case-folding changes length");
1594 }
1595 }
1596
TestStandAloneMonths()1597 void DateFormatTest::TestStandAloneMonths()
1598 {
1599 const char *EN_DATA[] = {
1600 "yyyy MM dd HH:mm:ss",
1601
1602 "yyyy LLLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 March 10 16:36:31", "2004 03 10 16:36:31",
1603 "yyyy LLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31",
1604 "yyyy LLLL dd H:mm:ss", "F", "2004 03 10 16:36:31", "2004 March 10 16:36:31",
1605 "yyyy LLL dd H:mm:ss", "pf", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31",
1606
1607 "LLLL", "fp", "1970 01 01 0:00:00", "January", "1970 01 01 0:00:00",
1608 "LLLL", "fp", "1970 02 01 0:00:00", "February", "1970 02 01 0:00:00",
1609 "LLLL", "fp", "1970 03 01 0:00:00", "March", "1970 03 01 0:00:00",
1610 "LLLL", "fp", "1970 04 01 0:00:00", "April", "1970 04 01 0:00:00",
1611 "LLLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1612 "LLLL", "fp", "1970 06 01 0:00:00", "June", "1970 06 01 0:00:00",
1613 "LLLL", "fp", "1970 07 01 0:00:00", "July", "1970 07 01 0:00:00",
1614 "LLLL", "fp", "1970 08 01 0:00:00", "August", "1970 08 01 0:00:00",
1615 "LLLL", "fp", "1970 09 01 0:00:00", "September", "1970 09 01 0:00:00",
1616 "LLLL", "fp", "1970 10 01 0:00:00", "October", "1970 10 01 0:00:00",
1617 "LLLL", "fp", "1970 11 01 0:00:00", "November", "1970 11 01 0:00:00",
1618 "LLLL", "fp", "1970 12 01 0:00:00", "December", "1970 12 01 0:00:00",
1619
1620 "LLL", "fp", "1970 01 01 0:00:00", "Jan", "1970 01 01 0:00:00",
1621 "LLL", "fp", "1970 02 01 0:00:00", "Feb", "1970 02 01 0:00:00",
1622 "LLL", "fp", "1970 03 01 0:00:00", "Mar", "1970 03 01 0:00:00",
1623 "LLL", "fp", "1970 04 01 0:00:00", "Apr", "1970 04 01 0:00:00",
1624 "LLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1625 "LLL", "fp", "1970 06 01 0:00:00", "Jun", "1970 06 01 0:00:00",
1626 "LLL", "fp", "1970 07 01 0:00:00", "Jul", "1970 07 01 0:00:00",
1627 "LLL", "fp", "1970 08 01 0:00:00", "Aug", "1970 08 01 0:00:00",
1628 "LLL", "fp", "1970 09 01 0:00:00", "Sep", "1970 09 01 0:00:00",
1629 "LLL", "fp", "1970 10 01 0:00:00", "Oct", "1970 10 01 0:00:00",
1630 "LLL", "fp", "1970 11 01 0:00:00", "Nov", "1970 11 01 0:00:00",
1631 "LLL", "fp", "1970 12 01 0:00:00", "Dec", "1970 12 01 0:00:00",
1632 };
1633
1634 const char *CS_DATA[] = {
1635 "yyyy MM dd HH:mm:ss",
1636
1637 "yyyy LLLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 duben 10 16:36:31", "2004 04 10 16:36:31",
1638 "yyyy MMMM dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31",
1639 "yyyy LLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 dub 10 16:36:31", "2004 04 10 16:36:31",
1640 "yyyy LLLL dd H:mm:ss", "F", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1641 "yyyy MMMM dd H:mm:ss", "F", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1642 "yyyy LLLL dd H:mm:ss", "pf", "2004 duben 10 16:36:31", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1643 "yyyy MMMM dd H:mm:ss", "pf", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1644
1645 "LLLL", "fp", "1970 01 01 0:00:00", "leden", "1970 01 01 0:00:00",
1646 "LLLL", "fp", "1970 02 01 0:00:00", "\\u00FAnor", "1970 02 01 0:00:00",
1647 "LLLL", "fp", "1970 03 01 0:00:00", "b\\u0159ezen", "1970 03 01 0:00:00",
1648 "LLLL", "fp", "1970 04 01 0:00:00", "duben", "1970 04 01 0:00:00",
1649 "LLLL", "fp", "1970 05 01 0:00:00", "kv\\u011Bten", "1970 05 01 0:00:00",
1650 "LLLL", "fp", "1970 06 01 0:00:00", "\\u010Derven", "1970 06 01 0:00:00",
1651 "LLLL", "fp", "1970 07 01 0:00:00", "\\u010Dervenec", "1970 07 01 0:00:00",
1652 "LLLL", "fp", "1970 08 01 0:00:00", "srpen", "1970 08 01 0:00:00",
1653 "LLLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159\\u00ED", "1970 09 01 0:00:00",
1654 "LLLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDjen", "1970 10 01 0:00:00",
1655 "LLLL", "fp", "1970 11 01 0:00:00", "listopad", "1970 11 01 0:00:00",
1656 "LLLL", "fp", "1970 12 01 0:00:00", "prosinec", "1970 12 01 0:00:00",
1657
1658 "LLL", "fp", "1970 01 01 0:00:00", "led", "1970 01 01 0:00:00",
1659 "LLL", "fp", "1970 02 01 0:00:00", "\\u00FAno", "1970 02 01 0:00:00",
1660 "LLL", "fp", "1970 03 01 0:00:00", "b\\u0159e", "1970 03 01 0:00:00",
1661 "LLL", "fp", "1970 04 01 0:00:00", "dub", "1970 04 01 0:00:00",
1662 "LLL", "fp", "1970 05 01 0:00:00", "kv\\u011B", "1970 05 01 0:00:00",
1663 "LLL", "fp", "1970 06 01 0:00:00", "\\u010Dvn", "1970 06 01 0:00:00",
1664 "LLL", "fp", "1970 07 01 0:00:00", "\\u010Dvc", "1970 07 01 0:00:00",
1665 "LLL", "fp", "1970 08 01 0:00:00", "srp", "1970 08 01 0:00:00",
1666 "LLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159", "1970 09 01 0:00:00",
1667 "LLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDj", "1970 10 01 0:00:00",
1668 "LLL", "fp", "1970 11 01 0:00:00", "lis", "1970 11 01 0:00:00",
1669 "LLL", "fp", "1970 12 01 0:00:00", "pro", "1970 12 01 0:00:00",
1670 };
1671
1672 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1673 expect(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1674 }
1675
TestStandAloneDays()1676 void DateFormatTest::TestStandAloneDays()
1677 {
1678 const char *EN_DATA[] = {
1679 "yyyy MM dd HH:mm:ss",
1680
1681 "cccc", "fp", "1970 01 04 0:00:00", "Sunday", "1970 01 04 0:00:00",
1682 "cccc", "fp", "1970 01 05 0:00:00", "Monday", "1970 01 05 0:00:00",
1683 "cccc", "fp", "1970 01 06 0:00:00", "Tuesday", "1970 01 06 0:00:00",
1684 "cccc", "fp", "1970 01 07 0:00:00", "Wednesday", "1970 01 07 0:00:00",
1685 "cccc", "fp", "1970 01 01 0:00:00", "Thursday", "1970 01 01 0:00:00",
1686 "cccc", "fp", "1970 01 02 0:00:00", "Friday", "1970 01 02 0:00:00",
1687 "cccc", "fp", "1970 01 03 0:00:00", "Saturday", "1970 01 03 0:00:00",
1688
1689 "ccc", "fp", "1970 01 04 0:00:00", "Sun", "1970 01 04 0:00:00",
1690 "ccc", "fp", "1970 01 05 0:00:00", "Mon", "1970 01 05 0:00:00",
1691 "ccc", "fp", "1970 01 06 0:00:00", "Tue", "1970 01 06 0:00:00",
1692 "ccc", "fp", "1970 01 07 0:00:00", "Wed", "1970 01 07 0:00:00",
1693 "ccc", "fp", "1970 01 01 0:00:00", "Thu", "1970 01 01 0:00:00",
1694 "ccc", "fp", "1970 01 02 0:00:00", "Fri", "1970 01 02 0:00:00",
1695 "ccc", "fp", "1970 01 03 0:00:00", "Sat", "1970 01 03 0:00:00",
1696 };
1697
1698 const char *CS_DATA[] = {
1699 "yyyy MM dd HH:mm:ss",
1700
1701 "cccc", "fp", "1970 01 04 0:00:00", "ned\\u011Ble", "1970 01 04 0:00:00",
1702 "cccc", "fp", "1970 01 05 0:00:00", "pond\\u011Bl\\u00ED", "1970 01 05 0:00:00",
1703 "cccc", "fp", "1970 01 06 0:00:00", "\\u00FAter\\u00FD", "1970 01 06 0:00:00",
1704 "cccc", "fp", "1970 01 07 0:00:00", "st\\u0159eda", "1970 01 07 0:00:00",
1705 "cccc", "fp", "1970 01 01 0:00:00", "\\u010Dtvrtek", "1970 01 01 0:00:00",
1706 "cccc", "fp", "1970 01 02 0:00:00", "p\\u00E1tek", "1970 01 02 0:00:00",
1707 "cccc", "fp", "1970 01 03 0:00:00", "sobota", "1970 01 03 0:00:00",
1708
1709 "ccc", "fp", "1970 01 04 0:00:00", "ne", "1970 01 04 0:00:00",
1710 "ccc", "fp", "1970 01 05 0:00:00", "po", "1970 01 05 0:00:00",
1711 "ccc", "fp", "1970 01 06 0:00:00", "\\u00FAt", "1970 01 06 0:00:00",
1712 "ccc", "fp", "1970 01 07 0:00:00", "st", "1970 01 07 0:00:00",
1713 "ccc", "fp", "1970 01 01 0:00:00", "\\u010Dt", "1970 01 01 0:00:00",
1714 "ccc", "fp", "1970 01 02 0:00:00", "p\\u00E1", "1970 01 02 0:00:00",
1715 "ccc", "fp", "1970 01 03 0:00:00", "so", "1970 01 03 0:00:00",
1716 };
1717
1718 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1719 expect(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1720 }
1721
TestShortDays()1722 void DateFormatTest::TestShortDays()
1723 {
1724 const char *EN_DATA[] = {
1725 "yyyy MM dd HH:mm:ss",
1726
1727 "EEEEEE, MMM d y", "fp", "2013 01 13 0:00:00", "Su, Jan 13 2013", "2013 01 13 0:00:00",
1728 "EEEEEE, MMM d y", "fp", "2013 01 16 0:00:00", "We, Jan 16 2013", "2013 01 16 0:00:00",
1729 "EEEEEE d", "fp", "1970 01 17 0:00:00", "Sa 17", "1970 01 17 0:00:00",
1730 "cccccc d", "fp", "1970 01 17 0:00:00", "Sa 17", "1970 01 17 0:00:00",
1731 "cccccc", "fp", "1970 01 03 0:00:00", "Sa", "1970 01 03 0:00:00",
1732 };
1733 const char *SV_DATA[] = {
1734 "yyyy MM dd HH:mm:ss",
1735
1736 "EEEEEE d MMM y", "fp", "2013 01 13 0:00:00", "s\\u00F6 13 jan. 2013", "2013 01 13 0:00:00",
1737 "EEEEEE d MMM y", "fp", "2013 01 16 0:00:00", "on 16 jan. 2013", "2013 01 16 0:00:00",
1738 "EEEEEE d", "fp", "1970 01 17 0:00:00", "l\\u00F6 17", "1970 01 17 0:00:00",
1739 "cccccc d", "fp", "1970 01 17 0:00:00", "l\\u00F6 17", "1970 01 17 0:00:00",
1740 "cccccc", "fp", "1970 01 03 0:00:00", "l\\u00F6", "1970 01 03 0:00:00",
1741 };
1742 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1743 expect(SV_DATA, UPRV_LENGTHOF(SV_DATA), Locale("sv", "", ""));
1744 }
1745
TestNarrowNames()1746 void DateFormatTest::TestNarrowNames()
1747 {
1748 const char *EN_DATA[] = {
1749 "yyyy MM dd HH:mm:ss",
1750
1751 "yyyy MMMMM dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1752 "yyyy LLLLL dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1753
1754 "MMMMM", "1970 01 01 0:00:00", "J",
1755 "MMMMM", "1970 02 01 0:00:00", "F",
1756 "MMMMM", "1970 03 01 0:00:00", "M",
1757 "MMMMM", "1970 04 01 0:00:00", "A",
1758 "MMMMM", "1970 05 01 0:00:00", "M",
1759 "MMMMM", "1970 06 01 0:00:00", "J",
1760 "MMMMM", "1970 07 01 0:00:00", "J",
1761 "MMMMM", "1970 08 01 0:00:00", "A",
1762 "MMMMM", "1970 09 01 0:00:00", "S",
1763 "MMMMM", "1970 10 01 0:00:00", "O",
1764 "MMMMM", "1970 11 01 0:00:00", "N",
1765 "MMMMM", "1970 12 01 0:00:00", "D",
1766
1767 "LLLLL", "1970 01 01 0:00:00", "J",
1768 "LLLLL", "1970 02 01 0:00:00", "F",
1769 "LLLLL", "1970 03 01 0:00:00", "M",
1770 "LLLLL", "1970 04 01 0:00:00", "A",
1771 "LLLLL", "1970 05 01 0:00:00", "M",
1772 "LLLLL", "1970 06 01 0:00:00", "J",
1773 "LLLLL", "1970 07 01 0:00:00", "J",
1774 "LLLLL", "1970 08 01 0:00:00", "A",
1775 "LLLLL", "1970 09 01 0:00:00", "S",
1776 "LLLLL", "1970 10 01 0:00:00", "O",
1777 "LLLLL", "1970 11 01 0:00:00", "N",
1778 "LLLLL", "1970 12 01 0:00:00", "D",
1779
1780 "EEEEE", "1970 01 04 0:00:00", "S",
1781 "EEEEE", "1970 01 05 0:00:00", "M",
1782 "EEEEE", "1970 01 06 0:00:00", "T",
1783 "EEEEE", "1970 01 07 0:00:00", "W",
1784 "EEEEE", "1970 01 01 0:00:00", "T",
1785 "EEEEE", "1970 01 02 0:00:00", "F",
1786 "EEEEE", "1970 01 03 0:00:00", "S",
1787
1788 "ccccc", "1970 01 04 0:00:00", "S",
1789 "ccccc", "1970 01 05 0:00:00", "M",
1790 "ccccc", "1970 01 06 0:00:00", "T",
1791 "ccccc", "1970 01 07 0:00:00", "W",
1792 "ccccc", "1970 01 01 0:00:00", "T",
1793 "ccccc", "1970 01 02 0:00:00", "F",
1794 "ccccc", "1970 01 03 0:00:00", "S",
1795
1796 "h:mm a", "2015 01 01 10:00:00", "10:00 AM",
1797 "h:mm a", "2015 01 01 22:00:00", "10:00 PM",
1798 "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a",
1799 "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p",
1800 };
1801
1802 const char *CS_DATA[] = {
1803 "yyyy MM dd HH:mm:ss",
1804
1805 "yyyy LLLLL dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1806 "yyyy MMMMM dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1807
1808 "MMMMM", "1970 01 01 0:00:00", "1",
1809 "MMMMM", "1970 02 01 0:00:00", "2",
1810 "MMMMM", "1970 03 01 0:00:00", "3",
1811 "MMMMM", "1970 04 01 0:00:00", "4",
1812 "MMMMM", "1970 05 01 0:00:00", "5",
1813 "MMMMM", "1970 06 01 0:00:00", "6",
1814 "MMMMM", "1970 07 01 0:00:00", "7",
1815 "MMMMM", "1970 08 01 0:00:00", "8",
1816 "MMMMM", "1970 09 01 0:00:00", "9",
1817 "MMMMM", "1970 10 01 0:00:00", "10",
1818 "MMMMM", "1970 11 01 0:00:00", "11",
1819 "MMMMM", "1970 12 01 0:00:00", "12",
1820
1821 "LLLLL", "1970 01 01 0:00:00", "1",
1822 "LLLLL", "1970 02 01 0:00:00", "2",
1823 "LLLLL", "1970 03 01 0:00:00", "3",
1824 "LLLLL", "1970 04 01 0:00:00", "4",
1825 "LLLLL", "1970 05 01 0:00:00", "5",
1826 "LLLLL", "1970 06 01 0:00:00", "6",
1827 "LLLLL", "1970 07 01 0:00:00", "7",
1828 "LLLLL", "1970 08 01 0:00:00", "8",
1829 "LLLLL", "1970 09 01 0:00:00", "9",
1830 "LLLLL", "1970 10 01 0:00:00", "10",
1831 "LLLLL", "1970 11 01 0:00:00", "11",
1832 "LLLLL", "1970 12 01 0:00:00", "12",
1833
1834 "EEEEE", "1970 01 04 0:00:00", "N",
1835 "EEEEE", "1970 01 05 0:00:00", "P",
1836 "EEEEE", "1970 01 06 0:00:00", "\\u00DA",
1837 "EEEEE", "1970 01 07 0:00:00", "S",
1838 "EEEEE", "1970 01 01 0:00:00", "\\u010C",
1839 "EEEEE", "1970 01 02 0:00:00", "P",
1840 "EEEEE", "1970 01 03 0:00:00", "S",
1841
1842 "ccccc", "1970 01 04 0:00:00", "N",
1843 "ccccc", "1970 01 05 0:00:00", "P",
1844 "ccccc", "1970 01 06 0:00:00", "\\u00DA",
1845 "ccccc", "1970 01 07 0:00:00", "S",
1846 "ccccc", "1970 01 01 0:00:00", "\\u010C",
1847 "ccccc", "1970 01 02 0:00:00", "P",
1848 "ccccc", "1970 01 03 0:00:00", "S",
1849
1850 "h:mm a", "2015 01 01 10:00:00", "10:00 dop.",
1851 "h:mm a", "2015 01 01 22:00:00", "10:00 odp.",
1852 "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 dop.",
1853 "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 odp.",
1854 };
1855
1856 const char *CA_DATA[] = {
1857 "yyyy MM dd HH:mm:ss",
1858
1859 "h:mm a", "2015 01 01 10:00:00", "10:00 a.\\u00A0m.",
1860 "h:mm a", "2015 01 01 22:00:00", "10:00 p.\\u00A0m.",
1861 "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a.\\u00A0m.",
1862 "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p.\\u00A0m.",
1863 };
1864
1865 expectFormat(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1866 expectFormat(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1867 expectFormat(CA_DATA, UPRV_LENGTHOF(CA_DATA), Locale("ca", "", ""));
1868 }
1869
TestEras()1870 void DateFormatTest::TestEras()
1871 {
1872 const char *EN_DATA[] = {
1873 "yyyy MM dd",
1874
1875 "MMMM dd yyyy G", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1876 "MMMM dd yyyy GG", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1877 "MMMM dd yyyy GGG", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1878 "MMMM dd yyyy GGGG", "fp", "1951 07 17", "July 17 1951 Anno Domini", "1951 07 17",
1879
1880 "MMMM dd yyyy G", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1881 "MMMM dd yyyy GG", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1882 "MMMM dd yyyy GGG", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1883 "MMMM dd yyyy GGGG", "fp", "-438 07 17", "July 17 0439 Before Christ", "-438 07 17",
1884 };
1885
1886 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1887 }
1888
TestQuarters()1889 void DateFormatTest::TestQuarters()
1890 {
1891 const char *EN_DATA[] = {
1892 "yyyy MM dd",
1893
1894 "Q", "fp", "1970 01 01", "1", "1970 01 01",
1895 "QQ", "fp", "1970 04 01", "02", "1970 04 01",
1896 "QQQ", "fp", "1970 07 01", "Q3", "1970 07 01",
1897 "QQQQ", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1898
1899 "q", "fp", "1970 01 01", "1", "1970 01 01",
1900 "qq", "fp", "1970 04 01", "02", "1970 04 01",
1901 "qqq", "fp", "1970 07 01", "Q3", "1970 07 01",
1902 "qqqq", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1903
1904 "Qyy", "fp", "2015 04 01", "215", "2015 04 01",
1905 "QQyy", "fp", "2015 07 01", "0315", "2015 07 01",
1906 };
1907
1908 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1909 }
1910
1911 /**
1912 * Test parsing. Input is an array that starts with the following
1913 * header:
1914 *
1915 * [0] = pattern string to parse [i+2] with
1916 *
1917 * followed by test cases, each of which is 3 array elements:
1918 *
1919 * [i] = pattern, or NULL to reuse prior pattern
1920 * [i+1] = input string
1921 * [i+2] = expected parse result (parsed with pattern [0])
1922 *
1923 * If expect parse failure, then [i+2] should be NULL.
1924 */
expectParse(const char ** data,int32_t data_length,const Locale & loc)1925 void DateFormatTest::expectParse(const char** data, int32_t data_length,
1926 const Locale& loc) {
1927 const UDate FAIL = (UDate) -1;
1928 const UnicodeString FAIL_STR("parse failure");
1929 int32_t i = 0;
1930
1931 UErrorCode ec = U_ZERO_ERROR;
1932 SimpleDateFormat fmt("", loc, ec);
1933 SimpleDateFormat ref(data[i++], loc, ec);
1934 SimpleDateFormat gotfmt("G yyyy MM dd HH:mm:ss z", loc, ec);
1935 if (U_FAILURE(ec)) {
1936 dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1937 return;
1938 }
1939
1940 const char* currentPat = NULL;
1941 while (i<data_length) {
1942 const char* pattern = data[i++];
1943 const char* input = data[i++];
1944 const char* expected = data[i++];
1945
1946 ec = U_ZERO_ERROR;
1947 if (pattern != NULL) {
1948 fmt.applyPattern(pattern);
1949 currentPat = pattern;
1950 }
1951 UDate got = fmt.parse(input, ec);
1952 UnicodeString gotstr(FAIL_STR);
1953 if (U_FAILURE(ec)) {
1954 got = FAIL;
1955 } else {
1956 gotstr.remove();
1957 gotfmt.format(got, gotstr);
1958 }
1959
1960 UErrorCode ec2 = U_ZERO_ERROR;
1961 UDate exp = FAIL;
1962 UnicodeString expstr(FAIL_STR);
1963 if (expected != NULL) {
1964 expstr = expected;
1965 exp = ref.parse(expstr, ec2);
1966 if (U_FAILURE(ec2)) {
1967 // This only happens if expected is in wrong format --
1968 // should never happen once test is debugged.
1969 errln("FAIL: Internal test error");
1970 return;
1971 }
1972 }
1973
1974 if (got == exp) {
1975 logln((UnicodeString)"Ok: " + input + " x " +
1976 currentPat + " => " + gotstr);
1977 } else {
1978 errln((UnicodeString)"FAIL: " + input + " x " +
1979 currentPat + " => " + gotstr + ", expected " +
1980 expstr);
1981 }
1982 }
1983 }
1984
1985 /**
1986 * Test formatting and parsing. Input is an array that starts
1987 * with the following header:
1988 *
1989 * [0] = pattern string to parse [i+2] with
1990 *
1991 * followed by test cases, each of which is 3 array elements:
1992 *
1993 * [i] = pattern, or null to reuse prior pattern
1994 * [i+1] = control string, either "fp", "pf", or "F".
1995 * [i+2..] = data strings
1996 *
1997 * The number of data strings depends on the control string.
1998 * Examples:
1999 * 1. "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.56", "2004 03 10 16:36:31.560",
2000 * 'f': Format date [i+2] (as parsed using pattern [0]) and expect string [i+3].
2001 * 'p': Parse string [i+3] and expect date [i+4].
2002 *
2003 * 2. "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567"
2004 * 'F': Format date [i+2] and expect string [i+3],
2005 * then parse string [i+3] and expect date [i+2].
2006 *
2007 * 3. "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5670",
2008 * 'p': Parse string [i+2] and expect date [i+3].
2009 * 'f': Format date [i+3] and expect string [i+4].
2010 */
expect(const char ** data,int32_t data_length,const Locale & loc)2011 void DateFormatTest::expect(const char** data, int32_t data_length,
2012 const Locale& loc) {
2013 int32_t i = 0;
2014 UErrorCode ec = U_ZERO_ERROR;
2015 UnicodeString str, str2;
2016 SimpleDateFormat fmt("", loc, ec);
2017 SimpleDateFormat ref(data[i++], loc, ec);
2018 SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2019 if (U_FAILURE(ec)) {
2020 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2021 return;
2022 }
2023
2024 UnicodeString currentPat;
2025 while (i<data_length) {
2026 const char* pattern = data[i++];
2027 if (pattern != NULL) {
2028 fmt.applyPattern(pattern);
2029 currentPat = pattern;
2030 }
2031
2032 const char* control = data[i++];
2033
2034 if (uprv_strcmp(control, "fp") == 0) {
2035 // 'f'
2036 const char* datestr = data[i++];
2037 const char* string = data[i++];
2038 UDate date = ref.parse(ctou(datestr), ec);
2039 if (!assertSuccess("parse", ec)) return;
2040 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2041 ctou(string),
2042 fmt.format(date, str.remove()));
2043 // 'p'
2044 datestr = data[i++];
2045 date = ref.parse(ctou(datestr), ec);
2046 if (!assertSuccess("parse", ec)) return;
2047 UDate parsedate = fmt.parse(ctou(string), ec);
2048 if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2049 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2050 univ.format(date, str.remove()),
2051 univ.format(parsedate, str2.remove()));
2052 }
2053 }
2054
2055 else if (uprv_strcmp(control, "pf") == 0) {
2056 // 'p'
2057 const char* string = data[i++];
2058 const char* datestr = data[i++];
2059 UDate date = ref.parse(ctou(datestr), ec);
2060 if (!assertSuccess("parse", ec)) return;
2061 UDate parsedate = fmt.parse(ctou(string), ec);
2062 if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2063 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2064 univ.format(date, str.remove()),
2065 univ.format(parsedate, str2.remove()));
2066 }
2067 // 'f'
2068 string = data[i++];
2069 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2070 ctou(string),
2071 fmt.format(date, str.remove()));
2072 }
2073
2074 else if (uprv_strcmp(control, "F") == 0) {
2075 const char* datestr = data[i++];
2076 const char* string = data[i++];
2077 UDate date = ref.parse(ctou(datestr), ec);
2078 if (!assertSuccess("parse", ec)) return;
2079 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2080 ctou(string),
2081 fmt.format(date, str.remove()));
2082
2083 UDate parsedate = fmt.parse(string, ec);
2084 if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2085 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2086 univ.format(date, str.remove()),
2087 univ.format(parsedate, str2.remove()));
2088 }
2089 }
2090
2091 else {
2092 errln((UnicodeString)"FAIL: Invalid control string " + control);
2093 return;
2094 }
2095 }
2096 }
2097
2098 /**
2099 * Test formatting. Input is an array that starts
2100 * with the following header:
2101 *
2102 * [0] = pattern string to parse [i+2] with
2103 *
2104 * followed by test cases, each of which is 3 array elements:
2105 *
2106 * [i] = pattern, or null to reuse prior pattern
2107 * [i+1] = data string a
2108 * [i+2] = data string b
2109 *
2110 * Examples:
2111 * Format date [i+1] and expect string [i+2].
2112 *
2113 * "y/M/d H:mm:ss.SSSS", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567"
2114 */
expectFormat(const char ** data,int32_t data_length,const Locale & loc)2115 void DateFormatTest::expectFormat(const char** data, int32_t data_length,
2116 const Locale& loc) {
2117 int32_t i = 0;
2118 UErrorCode ec = U_ZERO_ERROR;
2119 UnicodeString str, str2;
2120 SimpleDateFormat fmt("", loc, ec);
2121 SimpleDateFormat ref(data[i++], loc, ec);
2122 SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2123 if (U_FAILURE(ec)) {
2124 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2125 return;
2126 }
2127
2128 UnicodeString currentPat;
2129
2130 while (i<data_length) {
2131 const char* pattern = data[i++];
2132 if (pattern != NULL) {
2133 fmt.applyPattern(pattern);
2134 currentPat = pattern;
2135 }
2136
2137 const char* datestr = data[i++];
2138 const char* string = data[i++];
2139 UDate date = ref.parse(ctou(datestr), ec);
2140 if (!assertSuccess("parse", ec)) return;
2141 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2142 ctou(string),
2143 fmt.format(date, str.remove()));
2144 }
2145 }
2146
TestGenericTime()2147 void DateFormatTest::TestGenericTime() {
2148 const Locale en("en");
2149 // Note: We no longer parse strings in different styles.
2150 /*
2151 const char* ZDATA[] = {
2152 "yyyy MM dd HH:mm zzz",
2153 // round trip
2154 "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2155 "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2156 "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2157 "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2158 // non-generic timezone string influences dst offset even if wrong for date/time
2159 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
2160 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 Pacific Time",
2161 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
2162 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 Pacific Time",
2163 // generic timezone generates dst offset appropriate for local time
2164 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2165 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2166 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2167 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2168 // daylight savings time transition edge cases.
2169 // time to parse does not really exist, PT interpreted as earlier time
2170 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2171 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2172 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
2173 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2174 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2175 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT",
2176 "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2177 // time to parse is ambiguous, PT interpreted as later time
2178 "y/M/d H:mm zzz", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PST",
2179 "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PT",
2180 "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2181
2182 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2183 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2184 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
2185 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2186 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2187 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PT",
2188 "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2189 };
2190 */
2191 const char* ZDATA[] = {
2192 "yyyy MM dd HH:mm zzz",
2193 // round trip
2194 "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2195 "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2196 "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2197 "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2198 // non-generic timezone string influences dst offset even if wrong for date/time
2199 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
2200 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
2201 // generic timezone generates dst offset appropriate for local time
2202 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PST", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2203 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 Pacific Time", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2204 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2205 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 Pacific Time", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2206 // daylight savings time transition edge cases.
2207 // time to parse does not really exist, PT interpreted as earlier time
2208 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2209 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
2210 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2211 "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2212 // time to parse is ambiguous, PT interpreted as later time
2213 "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PT",
2214 "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2215
2216 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2217 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
2218 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2219 "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2220 };
2221
2222 const int32_t ZDATA_length = UPRV_LENGTHOF(ZDATA);
2223 expect(ZDATA, ZDATA_length, en);
2224
2225 UErrorCode status = U_ZERO_ERROR;
2226
2227 logln("cross format/parse tests"); // Note: We no longer support cross format/parse
2228 UnicodeString basepat("yy/MM/dd H:mm ");
2229 SimpleDateFormat formats[] = {
2230 SimpleDateFormat(basepat + "vvv", en, status),
2231 SimpleDateFormat(basepat + "vvvv", en, status),
2232 SimpleDateFormat(basepat + "zzz", en, status),
2233 SimpleDateFormat(basepat + "zzzz", en, status)
2234 };
2235 if (U_FAILURE(status)) {
2236 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(status));
2237 return;
2238 }
2239 const int32_t formats_length = UPRV_LENGTHOF(formats);
2240
2241 UnicodeString test;
2242 SimpleDateFormat univ("yyyy MM dd HH:mm zzz", en, status);
2243 ASSERT_OK(status);
2244 const UnicodeString times[] = {
2245 "2004 01 02 03:04 PST",
2246 "2004 07 08 09:10 PDT"
2247 };
2248 int32_t times_length = UPRV_LENGTHOF(times);
2249 for (int i = 0; i < times_length; ++i) {
2250 UDate d = univ.parse(times[i], status);
2251 logln(UnicodeString("\ntime: ") + d);
2252 for (int j = 0; j < formats_length; ++j) {
2253 test.remove();
2254 formats[j].format(d, test);
2255 logln("\ntest: '" + test + "'");
2256 for (int k = 0; k < formats_length; ++k) {
2257 UDate t = formats[k].parse(test, status);
2258 if (U_SUCCESS(status)) {
2259 if (d != t) {
2260 errln((UnicodeString)"FAIL: format " + k +
2261 " incorrectly parsed output of format " + j +
2262 " (" + test + "), returned " +
2263 dateToString(t) + " instead of " + dateToString(d));
2264 } else {
2265 logln((UnicodeString)"OK: format " + k + " parsed ok");
2266 }
2267 } else if (status == U_PARSE_ERROR) {
2268 errln((UnicodeString)"FAIL: format " + k +
2269 " could not parse output of format " + j +
2270 " (" + test + ")");
2271 }
2272 }
2273 }
2274 }
2275 }
2276
TestGenericTimeZoneOrder()2277 void DateFormatTest::TestGenericTimeZoneOrder() {
2278 // generic times should parse the same no matter what the placement of the time zone string
2279
2280 // Note: We no longer support cross style format/parse
2281
2282 //const char* XDATA[] = {
2283 // "yyyy MM dd HH:mm zzz",
2284 // // standard time, explicit daylight/standard
2285 // "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2286 // "y/M/d zzz H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
2287 // "zzz y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
2288
2289 // // standard time, generic
2290 // "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2291 // "y/M/d vvvv H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
2292 // "vvvv y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
2293
2294 // // dahylight time, explicit daylight/standard
2295 // "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2296 // "y/M/d zzz H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
2297 // "zzz y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
2298
2299 // // daylight time, generic
2300 // "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2301 // "y/M/d vvvv H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 Pacific Time 1:00",
2302 // "vvvv y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "Pacific Time 2004/7/1 1:00",
2303 //};
2304 const char* XDATA[] = {
2305 "yyyy MM dd HH:mm zzz",
2306 // standard time, explicit daylight/standard
2307 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PST", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2308 "y/M/d zzz H:mm", "pf", "2004/1/1 PST 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
2309 "zzz y/M/d H:mm", "pf", "PST 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
2310
2311 // standard time, generic
2312 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 Pacific Time", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2313 "y/M/d vvvv H:mm", "pf", "2004/1/1 Pacific Time 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
2314 "vvvv y/M/d H:mm", "pf", "Pacific Time 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
2315
2316 // dahylight time, explicit daylight/standard
2317 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2318 "y/M/d zzz H:mm", "pf", "2004/7/1 PDT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
2319 "zzz y/M/d H:mm", "pf", "PDT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
2320
2321 // daylight time, generic
2322 "y/M/d H:mm v", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PT",
2323 "y/M/d v H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PT 1:00",
2324 "v y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PT 2004/7/1 1:00",
2325 };
2326 const int32_t XDATA_length = UPRV_LENGTHOF(XDATA);
2327 Locale en("en");
2328 expect(XDATA, XDATA_length, en);
2329 }
2330
TestZTimeZoneParsing(void)2331 void DateFormatTest::TestZTimeZoneParsing(void) {
2332 UErrorCode status = U_ZERO_ERROR;
2333 const Locale en("en");
2334 UnicodeString test;
2335 //SimpleDateFormat univ("yyyy-MM-dd'T'HH:mm Z", en, status);
2336 SimpleDateFormat univ("HH:mm Z", en, status);
2337 if (failure(status, "construct SimpleDateFormat", TRUE)) return;
2338 const TimeZone *t = TimeZone::getGMT();
2339 univ.setTimeZone(*t);
2340
2341 univ.setLenient(false);
2342 ParsePosition pp(0);
2343 struct {
2344 UnicodeString input;
2345 UnicodeString expected_result;
2346 } tests[] = {
2347 { "11:00 -0200", "13:00 +0000" },
2348 { "11:00 +0200", "09:00 +0000" },
2349 { "11:00 +0400", "07:00 +0000" },
2350 { "11:00 +0530", "05:30 +0000" }
2351 };
2352
2353 UnicodeString result;
2354 int32_t tests_length = UPRV_LENGTHOF(tests);
2355 for (int i = 0; i < tests_length; ++i) {
2356 pp.setIndex(0);
2357 UDate d = univ.parse(tests[i].input, pp);
2358 if(pp.getIndex() != tests[i].input.length()){
2359 errln("Test %i: setZoneString() did not succeed. Consumed: %i instead of %i",
2360 i, pp.getIndex(), tests[i].input.length());
2361 return;
2362 }
2363 result.remove();
2364 univ.format(d, result);
2365 if(result != tests[i].expected_result) {
2366 errln("Expected " + tests[i].expected_result
2367 + " got " + result);
2368 return;
2369 }
2370 logln("SUCCESS: Parsed " + tests[i].input
2371 + " got " + result
2372 + " expected " + tests[i].expected_result);
2373 }
2374 }
2375
TestHost(void)2376 void DateFormatTest::TestHost(void)
2377 {
2378 #if U_PLATFORM_USES_ONLY_WIN32_API
2379 Win32DateTimeTest::testLocales(this);
2380 #endif
2381 }
2382
2383 // Relative Date Tests
2384
TestRelative(int daysdelta,const Locale & loc,const char * expectChars)2385 void DateFormatTest::TestRelative(int daysdelta,
2386 const Locale& loc,
2387 const char *expectChars) {
2388 char banner[25];
2389 sprintf(banner, "%d", daysdelta);
2390 UnicodeString bannerStr(banner, "");
2391
2392 UErrorCode status = U_ZERO_ERROR;
2393
2394 FieldPosition pos(FieldPosition::DONT_CARE);
2395 UnicodeString test;
2396 Locale en("en");
2397 DateFormat *fullrelative = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2398
2399 if (fullrelative == NULL) {
2400 dataerrln("DateFormat::createDateInstance(DateFormat::kFullRelative, %s) returned NULL", loc.getName());
2401 return;
2402 }
2403
2404 DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull , loc);
2405
2406 if (full == NULL) {
2407 errln("DateFormat::createDateInstance(DateFormat::kFull, %s) returned NULL", loc.getName());
2408 return;
2409 }
2410
2411 DateFormat *en_full = DateFormat::createDateInstance(DateFormat::kFull, en);
2412
2413 if (en_full == NULL) {
2414 errln("DateFormat::createDateInstance(DateFormat::kFull, en) returned NULL");
2415 return;
2416 }
2417
2418 DateFormat *en_fulltime = DateFormat::createDateTimeInstance(DateFormat::kFull,DateFormat::kFull,en);
2419
2420 if (en_fulltime == NULL) {
2421 errln("DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, en) returned NULL");
2422 return;
2423 }
2424
2425 UnicodeString result;
2426 UnicodeString normalResult;
2427 UnicodeString expect;
2428 UnicodeString parseResult;
2429
2430 Calendar *c = Calendar::createInstance(status);
2431
2432 // Today = Today
2433 c->setTime(Calendar::getNow(), status);
2434 if(daysdelta != 0) {
2435 c->add(Calendar::DATE,daysdelta,status);
2436 }
2437 ASSERT_OK(status);
2438
2439 // calculate the expected string
2440 if(expectChars != NULL) {
2441 expect = expectChars;
2442 } else {
2443 full->format(*c, expect, pos); // expected = normal full
2444 }
2445
2446 fullrelative ->format(*c, result, pos);
2447 en_full ->format(*c, normalResult, pos);
2448
2449 if(result != expect) {
2450 errln("FAIL: Relative Format ["+bannerStr+"] of "+normalResult+" failed, expected "+expect+" but got " + result);
2451 } else {
2452 logln("PASS: Relative Format ["+bannerStr+"] of "+normalResult+" got " + result);
2453 }
2454
2455
2456 //verify
2457 UDate d = fullrelative->parse(result, status);
2458 ASSERT_OK(status);
2459
2460 UnicodeString parseFormat; // parse rel->format full
2461 en_full->format(d, parseFormat, status);
2462
2463 UnicodeString origFormat;
2464 en_full->format(*c, origFormat, pos);
2465
2466 if(parseFormat!=origFormat) {
2467 errln("FAIL: Relative Parse ["+bannerStr+"] of "+result+" failed, expected "+parseFormat+" but got "+origFormat);
2468 } else {
2469 logln("PASS: Relative Parse ["+bannerStr+"] of "+result+" passed, got "+parseFormat);
2470 }
2471
2472 delete full;
2473 delete fullrelative;
2474 delete en_fulltime;
2475 delete en_full;
2476 delete c;
2477 }
2478
2479
TestRelative(void)2480 void DateFormatTest::TestRelative(void)
2481 {
2482 Locale en("en");
2483 TestRelative( 0, en, "today");
2484 TestRelative(-1, en, "yesterday");
2485 TestRelative( 1, en, "tomorrow");
2486 TestRelative( 2, en, NULL);
2487 TestRelative( -2, en, NULL);
2488 TestRelative( 3, en, NULL);
2489 TestRelative( -3, en, NULL);
2490 TestRelative( 300, en, NULL);
2491 TestRelative( -300, en, NULL);
2492 }
2493
TestRelativeClone(void)2494 void DateFormatTest::TestRelativeClone(void)
2495 {
2496 /*
2497 Verify that a cloned formatter gives the same results
2498 and is useable after the original has been deleted.
2499 */
2500 UErrorCode status = U_ZERO_ERROR;
2501 Locale loc("en");
2502 UDate now = Calendar::getNow();
2503 DateFormat *full = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2504 if (full == NULL) {
2505 dataerrln("FAIL: Can't create Relative date instance");
2506 return;
2507 }
2508 UnicodeString result1;
2509 full->format(now, result1, status);
2510 Format *fullClone = full->clone();
2511 delete full;
2512 full = NULL;
2513
2514 UnicodeString result2;
2515 fullClone->format(now, result2, status);
2516 ASSERT_OK(status);
2517 if (result1 != result2) {
2518 errln("FAIL: Clone returned different result from non-clone.");
2519 }
2520 delete fullClone;
2521 }
2522
TestHostClone(void)2523 void DateFormatTest::TestHostClone(void)
2524 {
2525 /*
2526 Verify that a cloned formatter gives the same results
2527 and is useable after the original has been deleted.
2528 */
2529 // This is mainly important on Windows.
2530 UErrorCode status = U_ZERO_ERROR;
2531 Locale loc("en_US@compat=host");
2532 UDate now = Calendar::getNow();
2533 DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull, loc);
2534 if (full == NULL) {
2535 dataerrln("FAIL: Can't create host date instance");
2536 return;
2537 }
2538 UnicodeString result1;
2539 full->format(now, result1, status);
2540 Format *fullClone = full->clone();
2541 delete full;
2542 full = NULL;
2543
2544 UnicodeString result2;
2545 fullClone->format(now, result2, status);
2546 ASSERT_OK(status);
2547 if (result1 != result2) {
2548 errln("FAIL: Clone returned different result from non-clone.");
2549 }
2550 delete fullClone;
2551 }
2552
TestHebrewClone(void)2553 void DateFormatTest::TestHebrewClone(void)
2554 {
2555 /*
2556 Verify that a cloned formatter gives the same results
2557 and is useable after the original has been deleted.
2558 */
2559 UErrorCode status = U_ZERO_ERROR;
2560 Locale loc("he@calendar=hebrew");
2561 UDate now = Calendar::getNow();
2562 LocalPointer<DateFormat> fmt(
2563 DateFormat::createDateInstance(DateFormat::kLong, loc));
2564 if (fmt.isNull()) {
2565 dataerrln("FAIL: Can't create Hebrew date instance");
2566 return;
2567 }
2568 UnicodeString result1;
2569 fmt->format(now, result1, status);
2570 LocalPointer<Format> fmtClone(fmt->clone());
2571
2572 // free fmt to be sure that fmtClone is independent of fmt.
2573 fmt.adoptInstead(NULL);
2574
2575 UnicodeString result2;
2576 fmtClone->format(now, result2, status);
2577 ASSERT_OK(status);
2578 if (result1 != result2) {
2579 errln("FAIL: Clone returned different result from non-clone.");
2580 }
2581 }
2582
getActualAndValidLocales(const Format & fmt,Locale & valid,Locale & actual)2583 static UBool getActualAndValidLocales(
2584 const Format &fmt, Locale &valid, Locale &actual) {
2585 const SimpleDateFormat* dat = dynamic_cast<const SimpleDateFormat*>(&fmt);
2586 if (dat == NULL) {
2587 return FALSE;
2588 }
2589 const DateFormatSymbols *sym = dat->getDateFormatSymbols();
2590 if (sym == NULL) {
2591 return FALSE;
2592 }
2593 UErrorCode status = U_ZERO_ERROR;
2594 valid = sym->getLocale(ULOC_VALID_LOCALE, status);
2595 actual = sym->getLocale(ULOC_ACTUAL_LOCALE, status);
2596 return U_SUCCESS(status);
2597 }
2598
TestDateFormatSymbolsClone(void)2599 void DateFormatTest::TestDateFormatSymbolsClone(void)
2600 {
2601 /*
2602 Verify that a cloned formatter gives the same results
2603 and is useable after the original has been deleted.
2604 */
2605 Locale loc("de_CH_LUCERNE");
2606 LocalPointer<DateFormat> fmt(
2607 DateFormat::createDateInstance(DateFormat::kDefault, loc));
2608 if (fmt.isNull()) {
2609 dataerrln("FAIL: DateFormat::createDateInstance failed for %s", loc.getName());
2610 return;
2611 }
2612 Locale valid1;
2613 Locale actual1;
2614 if (!getActualAndValidLocales(*fmt, valid1, actual1)) {
2615 dataerrln("FAIL: Could not fetch valid + actual locales");
2616 return;
2617 }
2618 LocalPointer<Format> fmtClone(fmt->clone());
2619
2620 // Free fmt to be sure that fmtClone is really independent of fmt.
2621 fmt.adoptInstead(NULL);
2622 Locale valid2;
2623 Locale actual2;
2624 if (!getActualAndValidLocales(*fmtClone, valid2, actual2)) {
2625 errln("FAIL: Could not fetch valid + actual locales");
2626 return;
2627 }
2628 if (valid1 != valid2 || actual1 != actual2) {
2629 errln("Date format symbol locales of clone don't match original");
2630 }
2631 }
2632
TestTimeZoneDisplayName()2633 void DateFormatTest::TestTimeZoneDisplayName()
2634 {
2635 // This test data was ported from ICU4J. Don't know why the 6th column in there because it's not being
2636 // used currently.
2637 const char *fallbackTests[][6] = {
2638 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2639 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2640 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZZ", "-08:00", "-8:00" },
2641 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "PST", "America/Los_Angeles" },
2642 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Pacific Standard Time", "America/Los_Angeles" },
2643 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2644 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2645 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "PDT", "America/Los_Angeles" },
2646 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Pacific Daylight Time", "America/Los_Angeles" },
2647 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "PT", "America/Los_Angeles" },
2648 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Pacific Time", "America/Los_Angeles" },
2649 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "Los Angeles Time", "America/Los_Angeles" },
2650 { "en_GB", "America/Los_Angeles", "2004-01-15T12:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2651 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "Z", "-0700", "-7:00" },
2652 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2653 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2654 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2655 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2656 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2657 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2658 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2659 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "v", "MST", "America/Phoenix" },
2660 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "vvvv", "Mountain Standard Time", "America/Phoenix" },
2661 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "VVVV", "Phoenix Time", "America/Phoenix" },
2662
2663 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2664 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2665 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2666 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2667 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2668 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2669 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2670 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2671 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2672 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2673 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2674
2675 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2676 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2677 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2678 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2679 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2680 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2681 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2682 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2683 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2684 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2685 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2686
2687 { "en", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2688 { "en", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2689 { "en", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2690 { "en", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Cuba Standard Time", "-5:00" },
2691 { "en", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2692 { "en", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2693 { "en", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2694 { "en", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Cuba Daylight Time", "-4:00" },
2695 { "en", "America/Havana", "2004-07-15T00:00:00Z", "v", "Cuba Time", "America/Havana" },
2696 { "en", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Cuba Time", "America/Havana" },
2697 { "en", "America/Havana", "2004-07-15T00:00:00Z", "VVVV", "Cuba Time", "America/Havana" },
2698
2699 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2700 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2701 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2702 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2703 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2704 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2705 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2706 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2707 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2708 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2709 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2710
2711 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2712 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2713 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2714 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2715 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2716 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2717 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2718 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2719 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2720 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2721 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2722
2723 { "en", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2724 { "en", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2725 { "en", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2726 { "en", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Greenwich Mean Time", "+0:00" },
2727 { "en", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2728 { "en", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2729 { "en", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "Europe/London" },
2730 { "en", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "British Summer Time", "Europe/London" },
2731 // icu en.txt has exemplar city for this time zone
2732 { "en", "Europe/London", "2004-07-15T00:00:00Z", "v", "United Kingdom Time", "Europe/London" },
2733 { "en", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "United Kingdom Time", "Europe/London" },
2734 { "en", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "United Kingdom Time", "Europe/London" },
2735
2736 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2737 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2738 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2739 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2740 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2741 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2742 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2743 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2744 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2745 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2746
2747 // JB#5150
2748 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2749 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2750 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2751 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2752 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2753 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2754 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2755 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2756 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "India Time", "Asia/Calcutta" },
2757 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "India Standard Time", "Asia/Calcutta" },
2758
2759 // Proper CLDR primary zone support #9733
2760 { "en", "America/Santiago", "2013-01-01T00:00:00Z", "VVVV", "Chile Time", "America/Santiago" },
2761 { "en", "Pacific/Easter", "2013-01-01T00:00:00Z", "VVVV", "Easter Time", "Pacific/Easter" },
2762
2763 // ==========
2764
2765 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2766 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2767 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2768 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Normalzeit", "-8:00" },
2769 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2770 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2771 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2772 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Sommerzeit", "-7:00" },
2773 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles Zeit", "America/Los_Angeles" },
2774 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Nordamerikanische Westk\\u00fcstenzeit", "America/Los_Angeles" },
2775
2776 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2777 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2778 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2779 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2780 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2781 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2782 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2783 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2784 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2785 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2786
2787 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2788 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2789 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2790 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2791 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2792 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2793 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2794 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2795 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2796 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2797
2798 { "de", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2799 { "de", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2800 { "de", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2801 { "de", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Kubanische Normalzeit", "-5:00" },
2802 { "de", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2803 { "de", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2804 { "de", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2805 { "de", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Kubanische Sommerzeit", "-4:00" },
2806 { "de", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2807 { "de", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2808 // added to test proper fallback of country name
2809 { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2810 { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2811
2812 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2813 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2814 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2815 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2816 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2817 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2818 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2819 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2820 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2821 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2822
2823 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2824 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2825 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2826 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2827 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2828 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2829 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2830 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2831 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2832 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2833
2834 { "de", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2835 { "de", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2836 { "de", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2837 { "de", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Mittlere Greenwich-Zeit", "+0:00" },
2838 { "de", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2839 { "de", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2840 { "de", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2841 { "de", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "Britische Sommerzeit", "+1:00" },
2842 { "de", "Europe/London", "2004-07-15T00:00:00Z", "v", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2843 { "de", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2844
2845 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2846 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2847 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2848 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2849 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2850 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2851 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2852 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2853 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2854 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2855
2856 // JB#5150
2857 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2858 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2859 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2860 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2861 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2862 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2863 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2864 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2865 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "Indien Zeit", "Asia/Calcutta" },
2866 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "Indische Zeit", "Asia/Calcutta" },
2867
2868 // ==========
2869
2870 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2871 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2872 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2873 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u6807\\u51c6\\u65f6\\u95f4", "America/Los_Angeles" },
2874 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2875 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2876 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
2877 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u590f\\u4ee4\\u65f6\\u95f4", "America/Los_Angeles" },
2878 // icu zh.txt has exemplar city for this time zone
2879 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4", "America/Los_Angeles" },
2880 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u65f6\\u95f4", "America/Los_Angeles" },
2881
2882 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2883 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2884 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2885 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2886 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2887 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2888 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2889 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2890 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2891 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2892
2893 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2894 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2895 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2896 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2897 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2898 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2899 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2900 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2901 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2902 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2903
2904 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2905 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2906 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2907 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u6807\\u51c6\\u65f6\\u95f4", "-5:00" },
2908 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2909 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2910 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2911 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u590f\\u4ee4\\u65f6\\u95f4", "-4:00" },
2912 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2913 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2914
2915 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2916 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2917 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2918 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2919 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2920 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2921 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2922 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2923 // icu zh.txt does not have info for this time zone
2924 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2925 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2926
2927 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2928 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2929 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2930 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2931 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2932 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2933 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2934 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2935 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2936 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2937
2938 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2939 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2940 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2941 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2942 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2943 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u683C\\u6797\\u5C3C\\u6CBB\\u6807\\u51C6\\u65F6\\u95F4", "+0:00" },
2944 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2945 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2946 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2947 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u4ee4\\u65f6\\u95f4", "+1:00" },
2948 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2949 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2950 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2951
2952 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2953 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2954 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2955 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2956 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2957 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2958 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2959 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2960 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2961 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2962
2963 // JB#5150
2964 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2965 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2966 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2967 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2968 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2969 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2970 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2971 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2972 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2973 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2974
2975 // ==========
2976
2977 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2978 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2979 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2980 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-8:00" },
2981 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2982 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2983 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2984 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "-7:00" },
2985 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u0932\\u0949\\u0938 \\u090f\\u0902\\u091c\\u093f\\u0932\\u094d\\u0938 \\u0938\\u092e\\u092f", "America/Los_Angeles" },
2986 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u0938\\u092e\\u092f", "America/Los_Angeles" },
2987
2988 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2989 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2990 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2991 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2992 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2993 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2994 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2995 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2996 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u092C\\u094D\\u092F\\u0942\\u0928\\u0938 \\u0906\\u092F\\u0930\\u0938 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2997 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2998
2999 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3000 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3001 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3002 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
3003 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3004 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3005 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3006 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
3007 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u092C\\u094D\\u092F\\u0942\\u0928\\u0938 \\u0906\\u092F\\u0930\\u0938 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
3008 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
3009
3010 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3011 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3012 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3013 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-5:00" },
3014 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3015 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3016 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3017 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "-4:00" },
3018 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092E\\u092F", "America/Havana" },
3019 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092e\\u092f", "America/Havana" },
3020
3021 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3022 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3023 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3024 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "+11:00" },
3025 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3026 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3027 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3028 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "+10:00" },
3029 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3030 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0911\\u0938\\u094d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e \\u0938\\u092e\\u092f", "Australia/Sydney" },
3031
3032 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3033 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3034 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3035 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "+11:00" },
3036 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3037 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3038 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3039 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "+10:00" },
3040 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3041 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0911\\u0938\\u094d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e \\u0938\\u092e\\u092f", "Australia/Sydney" },
3042
3043 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3044 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3045 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3046 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u0917\\u094d\\u0930\\u0940\\u0928\\u0935\\u093f\\u091a \\u092e\\u0940\\u0928 \\u091f\\u093e\\u0907\\u092e", "+0:00" },
3047 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3048 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3049 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3050 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u092c\\u094d\\u0930\\u093f\\u091f\\u093f\\u0936 \\u0917\\u094d\\u0930\\u0940\\u0937\\u094d\\u092e\\u0915\\u093e\\u0932\\u0940\\u0928 \\u0938\\u092e\\u092f", "+1:00" },
3051 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u092f\\u0942\\u0928\\u093e\\u0907\\u091f\\u0947\\u0921 \\u0915\\u093f\\u0902\\u0917\\u0921\\u092e \\u0938\\u092e\\u092f", "Europe/London" },
3052 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u092f\\u0942\\u0928\\u093e\\u0907\\u091f\\u0947\\u0921 \\u0915\\u093f\\u0902\\u0917\\u0921\\u092e \\u0938\\u092e\\u092f", "Europe/London" },
3053
3054 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3055 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3056 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3057 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3058 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3059 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3060 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3061 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3062 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3063 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3064
3065 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3066 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3067 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "IST", "+5:30" },
3068 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3069 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3070 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3071 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "IST", "+05:30" },
3072 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3073 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IST", "Asia/Calcutta" },
3074 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "Asia/Calcutta" },
3075
3076 // ==========
3077
3078 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3079 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-08:00", "-8:00" },
3080 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-8", "America/Los_Angeles" },
3081 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3082 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3083 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-07:00", "-7:00" },
3084 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-7", "America/Los_Angeles" },
3085 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3086 // icu bg.txt has exemplar city for this time zone
3087 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3088 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3089 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3090
3091 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3092 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3093 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3094 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3095 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3096 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3097 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3098 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3099 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
3100 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Buenos_Aires" },
3101
3102 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3103 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3104 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3105 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3106 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3107 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3108 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3109 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3110 // icu bg.txt does not have info for this time zone
3111 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
3112 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Buenos_Aires" },
3113
3114 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3115 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-05:00", "-5:00" },
3116 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-5", "-5:00" },
3117 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-5:00" },
3118 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3119 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-04:00", "-4:00" },
3120 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-4", "-4:00" },
3121 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-4:00" },
3122 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u041a\\u0443\\u0431\\u0430", "America/Havana" },
3123 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043C\\u0435", "America/Havana" },
3124
3125 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3126 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3127 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3128 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u043B\\u044F\\u0442\\u043D\\u043E \\u0447\\u0430\\u0441\\u043E\\u0432\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+11:00" },
3129 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3130 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3131 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3132 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+10:00" },
3133 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3134 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "Australia/Sydney" },
3135
3136 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3137 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3138 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3139 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u043B\\u044F\\u0442\\u043D\\u043E \\u0447\\u0430\\u0441\\u043E\\u0432\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+11:00" },
3140 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3141 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3142 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3143 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+10:00" },
3144 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3145 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "Australia/Sydney" },
3146
3147 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3148 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3149 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3150 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u0421\\u0440\\u0435\\u0434\\u043d\\u043e \\u0433\\u0440\\u0438\\u043d\\u0443\\u0438\\u0447\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+0:00" },
3151 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3152 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+01:00", "+1:00" },
3153 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+1", "+1:00" },
3154 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u0411\\u0440\\u0438\\u0442\\u0430\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+1:00" },
3155 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u041E\\u0431\\u0435\\u0434\\u0438\\u043D\\u0435\\u043D\\u043E\\u0442\\u043E \\u043A\\u0440\\u0430\\u043B\\u0441\\u0442\\u0432\\u043E", "Europe/London" },
3156 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u041E\\u0431\\u0435\\u0434\\u0438\\u043D\\u0435\\u043D\\u043E\\u0442\\u043E \\u043A\\u0440\\u0430\\u043B\\u0441\\u0442\\u0432\\u043E", "Europe/London" },
3157
3158 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3159 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3160 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3161 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3162 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3163 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3164 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3165 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3166 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3167 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3168
3169 // JB#5150
3170 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3171 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3172 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+5:30" },
3173 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u043D\\u0434\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
3174 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3175 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3176 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+05:30" },
3177 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u043D\\u0434\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
3178 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u0418\\u043D\\u0434\\u0438\\u044F", "Asia/Calcutta" },
3179 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u043D\\u0434\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "Asia/Calcutta" },
3180 // ==========
3181
3182 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3183 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3184 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
3185 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u6a19\\u6e96\\u6642", "America/Los_Angeles" },
3186 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-700" },
3187 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3188 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
3189 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u590f\\u6642\\u9593", "America/Los_Angeles" },
3190 // icu ja.txt has exemplar city for this time zone
3191 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3192 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30E1\\u30EA\\u30AB\\u592A\\u5e73\\u6D0B\\u6642\\u9593", "America/Los_Angeles" },
3193 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3194
3195 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3196 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3197 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3198 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3199 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3200 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3201 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3202 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3203 // icu ja.txt does not have info for this time zone
3204 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3205 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3206
3207 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3208 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3209 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3210 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3211 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3212 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3213 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3214 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3215 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3216 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3217
3218 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3219 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3220 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3221 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u6A19\\u6E96\\u6642", "-5:00" },
3222 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3223 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3224 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3225 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u590F\\u6642\\u9593", "-4:00" },
3226 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3227 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3228
3229 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3230 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3231 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3232 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3233 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3234 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3235 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3236 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3237 // icu ja.txt does not have info for this time zone
3238 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3239 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3240
3241 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3242 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3243 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3244 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3245 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3246 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3247 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3248 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3249 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3250 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3251
3252 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3253 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3254 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3255 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u30B0\\u30EA\\u30CB\\u30C3\\u30B8\\u6A19\\u6E96\\u6642", "+0:00" },
3256 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3257 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3258 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3259 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u6642\\u9593", "+1:00" },
3260 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3261 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3262 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3263
3264 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3265 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3266 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3267 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3268 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3269 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3270 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3271 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3272 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3273 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3274
3275 // JB#5150
3276 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3277 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3278 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3279 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3280 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3281 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3282 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3283 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3284 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u30A4\\u30F3\\u30C9\\u6642\\u9593", "Asia/Calcutta" },
3285 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "Asia/Calcutta" },
3286
3287 // ==========
3288
3289 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3290 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3291 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
3292 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "GMT-08:00", "-8:00" },
3293 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3294 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3295 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
3296 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "GMT-07:00", "-7:00" },
3297 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles", "America/Los_Angeles" },
3298 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Los Angeles", "America/Los_Angeles" },
3299
3300 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3301 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3302 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3303 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3304 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3305 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3306 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3307 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3308 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3309 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3310
3311 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3312 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3313 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3314 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3315 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3316 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3317 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3318 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3319 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3320 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3321
3322 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3323 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3324 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3325 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "GMT-05:00", "-5:00" },
3326 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3327 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3328 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3329 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "GMT-04:00", "-4:00" },
3330 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u12A9\\u1263", "America/Havana" },
3331 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u12A9\\u1263", "America/Havana" },
3332
3333 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3334 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3335 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3336 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3337 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3338 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3339 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3340 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3341 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3342 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3343
3344 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3345 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3346 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3347 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3348 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3349 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3350 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3351 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3352 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3353 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3354
3355 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3356 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3357 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3358 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "GMT", "+0:00" },
3359 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3360 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3361 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3362 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "GMT+01:00", "+1:00" },
3363 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u12A5\\u1295\\u130D\\u120A\\u12DD", "Europe/London" },
3364 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u12A5\\u1295\\u130D\\u120A\\u12DD", "Europe/London" },
3365
3366 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3367 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3368 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3369 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3370 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3371 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3372 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3373 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3374 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3375 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3376
3377 // JB#5150
3378 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3379 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3380 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3381 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3382 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3383 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3384 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3385 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3386 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u1205\\u1295\\u12F2", "Alna/Calcutta" },
3387 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u1205\\u1295\\u12F2", "Asia/Calcutta" },
3388
3389 // Ticket#8589 Partial location name to use country name if the zone is the golden
3390 // zone for the time zone's country.
3391 { "en_MX", "America/Chicago", "1995-07-15T00:00:00Z", "vvvv", "Central Time (United States)", "America/Chicago"},
3392
3393 // Tests proper handling of time zones that should have empty sets when inherited from the parent.
3394 // For example, en_GB understands CET as Central European Time, but en_HK, which inherits from en_GB
3395 // does not
3396 { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3397 { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3398 { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "CET", "+1:00"},
3399 { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "CEST", "+2:00"},
3400 { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3401 { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3402 { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "GMT+1", "+1:00"},
3403 { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "GMT+2", "+2:00"},
3404
3405 { NULL, NULL, NULL, NULL, NULL, NULL },
3406 };
3407
3408 UErrorCode status = U_ZERO_ERROR;
3409 LocalPointer<Calendar> cal(GregorianCalendar::createInstance(status));
3410 if (failure(status, "GregorianCalendar::createInstance", TRUE)) return;
3411 SimpleDateFormat testfmt(UnicodeString("yyyy-MM-dd'T'HH:mm:ss'Z'"), status);
3412 if (failure(status, "SimpleDateFormat constructor", TRUE)) return;
3413 testfmt.setTimeZone(*TimeZone::getGMT());
3414
3415 for (int i = 0; fallbackTests[i][0]; i++) {
3416 const char **testLine = fallbackTests[i];
3417 UnicodeString info[5];
3418 for ( int j = 0 ; j < 5 ; j++ ) {
3419 info[j] = UnicodeString(testLine[j], -1, US_INV);
3420 }
3421 info[4] = info[4].unescape();
3422 logln("%s;%s;%s;%s", testLine[0], testLine[1], testLine[2], testLine[3]);
3423
3424 TimeZone *tz = TimeZone::createTimeZone(info[1]);
3425
3426 UDate d = testfmt.parse(testLine[2], status);
3427 cal->setTime(d, status);
3428 if (U_FAILURE(status)) {
3429 errln(UnicodeString("Failed to set date: ") + testLine[2]);
3430 }
3431
3432 SimpleDateFormat fmt(info[3], Locale(testLine[0]),status);
3433 ASSERT_OK(status);
3434 cal->adoptTimeZone(tz);
3435 UnicodeString result;
3436 FieldPosition pos(FieldPosition::DONT_CARE);
3437 fmt.format(*cal.getAlias(), result,pos);
3438 if (result != info[4]) {
3439 errln(info[0] + ";" + info[1] + ";" + info[2] + ";" + info[3] + " expected: '" +
3440 info[4] + "' but got: '" + result + "'");
3441 }
3442 }
3443 }
3444
TestRoundtripWithCalendar(void)3445 void DateFormatTest::TestRoundtripWithCalendar(void) {
3446 UErrorCode status = U_ZERO_ERROR;
3447
3448 TimeZone *tz = TimeZone::createTimeZone("Europe/Paris");
3449 TimeZone *gmt = TimeZone::createTimeZone("Etc/GMT");
3450
3451 Calendar *calendars[] = {
3452 Calendar::createInstance(*tz, Locale("und@calendar=gregorian"), status),
3453 Calendar::createInstance(*tz, Locale("und@calendar=buddhist"), status),
3454 // Calendar::createInstance(*tz, Locale("und@calendar=hebrew"), status),
3455 Calendar::createInstance(*tz, Locale("und@calendar=islamic"), status),
3456 Calendar::createInstance(*tz, Locale("und@calendar=japanese"), status),
3457 NULL
3458 };
3459 if (U_FAILURE(status)) {
3460 dataerrln("Failed to initialize calendars: %s", u_errorName(status));
3461 for (int i = 0; calendars[i] != NULL; i++) {
3462 delete calendars[i];
3463 }
3464 return;
3465 }
3466
3467 //FIXME The formatters commented out below are currently failing because of
3468 // the calendar calculation problem reported by #6691
3469
3470 // The order of test formatters must match the order of calendars above.
3471 DateFormat *formatters[] = {
3472 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("en_US")), //calendar=gregorian
3473 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("th_TH")), //calendar=buddhist
3474 // DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("he_IL@calendar=hebrew")),
3475 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ar_EG@calendar=islamic")),
3476 // DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ja_JP@calendar=japanese")),
3477 NULL
3478 };
3479
3480 UDate d = Calendar::getNow();
3481 UnicodeString buf;
3482 FieldPosition fpos;
3483 ParsePosition ppos;
3484
3485 for (int i = 0; formatters[i] != NULL; i++) {
3486 buf.remove();
3487 fpos.setBeginIndex(0);
3488 fpos.setEndIndex(0);
3489 calendars[i]->setTime(d, status);
3490
3491 // Normal case output - the given calendar matches the calendar
3492 // used by the formatter
3493 formatters[i]->format(*calendars[i], buf, fpos);
3494 UnicodeString refStr(buf);
3495
3496 for (int j = 0; calendars[j] != NULL; j++) {
3497 if (j == i) {
3498 continue;
3499 }
3500 buf.remove();
3501 fpos.setBeginIndex(0);
3502 fpos.setEndIndex(0);
3503 calendars[j]->setTime(d, status);
3504
3505 // Even the different calendar type is specified,
3506 // we should get the same result.
3507 formatters[i]->format(*calendars[j], buf, fpos);
3508 if (refStr != buf) {
3509 errln((UnicodeString)"FAIL: Different format result with a different calendar for the same time -"
3510 + "\n Reference calendar type=" + calendars[i]->getType()
3511 + "\n Another calendar type=" + calendars[j]->getType()
3512 + "\n Expected result=" + refStr
3513 + "\n Actual result=" + buf);
3514 }
3515 }
3516
3517 calendars[i]->setTimeZone(*gmt);
3518 calendars[i]->clear();
3519 ppos.setErrorIndex(-1);
3520 ppos.setIndex(0);
3521
3522 // Normal case parse result - the given calendar matches the calendar
3523 // used by the formatter
3524 formatters[i]->parse(refStr, *calendars[i], ppos);
3525
3526 for (int j = 0; calendars[j] != NULL; j++) {
3527 if (j == i) {
3528 continue;
3529 }
3530 calendars[j]->setTimeZone(*gmt);
3531 calendars[j]->clear();
3532 ppos.setErrorIndex(-1);
3533 ppos.setIndex(0);
3534
3535 // Even the different calendar type is specified,
3536 // we should get the same time and time zone.
3537 formatters[i]->parse(refStr, *calendars[j], ppos);
3538 if (calendars[i]->getTime(status) != calendars[j]->getTime(status)
3539 || calendars[i]->getTimeZone() != calendars[j]->getTimeZone()) {
3540 UnicodeString tzid;
3541 errln((UnicodeString)"FAIL: Different parse result with a different calendar for the same string -"
3542 + "\n Reference calendar type=" + calendars[i]->getType()
3543 + "\n Another calendar type=" + calendars[j]->getType()
3544 + "\n Date string=" + refStr
3545 + "\n Expected time=" + calendars[i]->getTime(status)
3546 + "\n Expected time zone=" + calendars[i]->getTimeZone().getID(tzid)
3547 + "\n Actual time=" + calendars[j]->getTime(status)
3548 + "\n Actual time zone=" + calendars[j]->getTimeZone().getID(tzid));
3549 }
3550 }
3551 if (U_FAILURE(status)) {
3552 errln((UnicodeString)"FAIL: " + u_errorName(status));
3553 break;
3554 }
3555 }
3556
3557 delete tz;
3558 delete gmt;
3559 for (int i = 0; calendars[i] != NULL; i++) {
3560 delete calendars[i];
3561 }
3562 for (int i = 0; formatters[i] != NULL; i++) {
3563 delete formatters[i];
3564 }
3565 }
3566
3567 /*
3568 void DateFormatTest::TestRelativeError(void)
3569 {
3570 UErrorCode status;
3571 Locale en("en");
3572
3573 DateFormat *en_reltime_reldate = DateFormat::createDateTimeInstance(DateFormat::kFullRelative,DateFormat::kFullRelative,en);
3574 if(en_reltime_reldate == NULL) {
3575 logln("PASS: rel date/rel time failed");
3576 } else {
3577 errln("FAIL: rel date/rel time created, should have failed.");
3578 delete en_reltime_reldate;
3579 }
3580 }
3581
3582 void DateFormatTest::TestRelativeOther(void)
3583 {
3584 logln("Nothing in this test. When we get more data from CLDR, put in some tests of -2, +2, etc. ");
3585 }
3586 */
3587
Test6338(void)3588 void DateFormatTest::Test6338(void)
3589 {
3590 UErrorCode status = U_ZERO_ERROR;
3591
3592 SimpleDateFormat fmt1(UnicodeString(u"y-M-d"), Locale("ar"), status);
3593 if (failure(status, "new SimpleDateFormat", TRUE)) return;
3594
3595 UDate dt1 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3596 UnicodeString str1;
3597 str1 = fmt1.format(dt1, str1);
3598 logln(str1);
3599
3600 UDate dt11 = fmt1.parse(str1, status);
3601 failure(status, "fmt->parse");
3602
3603 UnicodeString str11;
3604 str11 = fmt1.format(dt11, str11);
3605 logln(str11);
3606
3607 if (str1 != str11) {
3608 errln((UnicodeString)"FAIL: Different dates str1:" + str1
3609 + " str2:" + str11);
3610 }
3611
3612 /////////////////
3613
3614 status = U_ZERO_ERROR;
3615 SimpleDateFormat fmt2(UnicodeString(u"y M d"), Locale("ar"), status);
3616 failure(status, "new SimpleDateFormat");
3617
3618 UDate dt2 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3619 UnicodeString str2;
3620 str2 = fmt2.format(dt2, str2);
3621 logln(str2);
3622
3623 UDate dt22 = fmt2.parse(str2, status);
3624 failure(status, "fmt->parse");
3625
3626 UnicodeString str22;
3627 str22 = fmt2.format(dt22, str22);
3628 logln(str22);
3629
3630 if (str2 != str22) {
3631 errln((UnicodeString)"FAIL: Different dates str1:" + str2
3632 + " str2:" + str22);
3633 }
3634
3635 /////////////////
3636
3637 status = U_ZERO_ERROR;
3638 SimpleDateFormat fmt3(UnicodeString("y-M-d"), Locale("en-us"), status);
3639 failure(status, "new SimpleDateFormat");
3640
3641 UDate dt3 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3642 UnicodeString str3;
3643 str3 = fmt3.format(dt3, str3);
3644 logln(str3);
3645
3646 UDate dt33 = fmt3.parse(str3, status);
3647 failure(status, "fmt->parse");
3648
3649 UnicodeString str33;
3650 str33 = fmt3.format(dt33, str33);
3651 logln(str33);
3652
3653 if (str3 != str33) {
3654 errln((UnicodeString)"FAIL: Different dates str1:" + str3
3655 + " str2:" + str33);
3656 }
3657
3658 /////////////////
3659
3660 status = U_ZERO_ERROR;
3661 SimpleDateFormat fmt4(UnicodeString("y M d"), Locale("en-us"), status);
3662 failure(status, "new SimpleDateFormat");
3663
3664 UDate dt4 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3665 UnicodeString str4;
3666 str4 = fmt4.format(dt4, str4);
3667 logln(str4);
3668
3669 UDate dt44 = fmt4.parse(str4, status);
3670 failure(status, "fmt->parse");
3671
3672 UnicodeString str44;
3673 str44 = fmt4.format(dt44, str44);
3674 logln(str44);
3675
3676 if (str4 != str44) {
3677 errln((UnicodeString)"FAIL: Different dates str1:" + str4
3678 + " str2:" + str44);
3679 }
3680
3681 }
3682
Test6726(void)3683 void DateFormatTest::Test6726(void)
3684 {
3685 // status
3686 // UErrorCode status = U_ZERO_ERROR;
3687
3688 // fmtf, fmtl, fmtm, fmts;
3689 UnicodeString strf, strl, strm, strs;
3690 UDate dt = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3691
3692 Locale loc("ja");
3693 DateFormat* fmtf = DateFormat::createDateTimeInstance(DateFormat::FULL, DateFormat::FULL, loc);
3694 DateFormat* fmtl = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::FULL, loc);
3695 DateFormat* fmtm = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, loc);
3696 DateFormat* fmts = DateFormat::createDateTimeInstance(DateFormat::SHORT, DateFormat::FULL, loc);
3697 if (fmtf == NULL || fmtl == NULL || fmtm == NULL || fmts == NULL) {
3698 dataerrln("Unable to create DateFormat. got NULL.");
3699 /* It may not be true that if one is NULL all is NULL. Just to be safe. */
3700 delete fmtf;
3701 delete fmtl;
3702 delete fmtm;
3703 delete fmts;
3704
3705 return;
3706 }
3707 strf = fmtf->format(dt, strf);
3708 strl = fmtl->format(dt, strl);
3709 strm = fmtm->format(dt, strm);
3710 strs = fmts->format(dt, strs);
3711
3712
3713 logln("strm.charAt(10)=%04X wanted 0x20\n", strm.charAt(10));
3714 if (strm.charAt(10) != UChar(0x0020)) {
3715 errln((UnicodeString)"FAIL: Improper formatted date: " + strm );
3716 }
3717 logln("strs.charAt(10)=%04X wanted 0x20\n", strs.charAt(8));
3718 if (strs.charAt(10) != UChar(0x0020)) {
3719 errln((UnicodeString)"FAIL: Improper formatted date: " + strs);
3720 }
3721
3722 delete fmtf;
3723 delete fmtl;
3724 delete fmtm;
3725 delete fmts;
3726
3727 return;
3728 }
3729
3730 /**
3731 * Test DateFormat's parsing of default GMT variants. See ticket#6135
3732 */
TestGMTParsing()3733 void DateFormatTest::TestGMTParsing() {
3734 const char* DATA[] = {
3735 "HH:mm:ss Z",
3736
3737 // pattern, input, expected output (in quotes)
3738 "HH:mm:ss Z", "10:20:30 GMT+03:00", "10:20:30 +0300",
3739 "HH:mm:ss Z", "10:20:30 UT-02:00", "10:20:30 -0200",
3740 "HH:mm:ss Z", "10:20:30 GMT", "10:20:30 +0000",
3741 "HH:mm:ss vvvv", "10:20:30 UT+10:00", "10:20:30 +1000",
3742 "HH:mm:ss zzzz", "10:20:30 UTC", "10:20:30 +0000", // standalone "UTC"
3743 "ZZZZ HH:mm:ss", "UT 10:20:30", "10:20:30 +0000",
3744 "z HH:mm:ss", "UT+0130 10:20:30", "10:20:30 +0130",
3745 "z HH:mm:ss", "UTC+0130 10:20:30", "10:20:30 +0130",
3746 // Note: GMT-1100 no longer works because of the introduction of the short
3747 // localized GMT support. Previous implementation support this level of
3748 // leniency (no separator char in localized GMT format), but the new
3749 // implementation handles GMT-11 as the legitimate short localized GMT format
3750 // and stop at there. Otherwise, roundtrip would be broken.
3751 //"HH mm Z ss", "10 20 GMT-1100 30", "10:20:30 -1100",
3752 "HH mm Z ss", "10 20 GMT-11 30", "10:20:30 -1100",
3753 "HH:mm:ssZZZZZ", "14:25:45Z", "14:25:45 +0000",
3754 "HH:mm:ssZZZZZ", "15:00:00-08:00", "15:00:00 -0800",
3755 };
3756 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
3757 expectParse(DATA, DATA_len, Locale("en"));
3758 }
3759
3760 // Test case for localized GMT format parsing
3761 // with no delimitters in offset format (Chinese locale)
Test6880()3762 void DateFormatTest::Test6880() {
3763 UErrorCode status = U_ZERO_ERROR;
3764 UDate d1, d2, dp1, dp2, dexp1, dexp2;
3765 UnicodeString s1, s2;
3766
3767 TimeZone *tz = TimeZone::createTimeZone("Asia/Shanghai");
3768 GregorianCalendar gcal(*tz, status);
3769 if (failure(status, "construct GregorianCalendar", TRUE)) return;
3770
3771 gcal.clear();
3772 gcal.set(1900, UCAL_JULY, 1, 12, 00); // offset 8:05:43
3773 d1 = gcal.getTime(status);
3774
3775 gcal.clear();
3776 gcal.set(1950, UCAL_JULY, 1, 12, 00); // offset 8:00
3777 d2 = gcal.getTime(status);
3778
3779 gcal.clear();
3780 gcal.set(1970, UCAL_JANUARY, 1, 12, 00);
3781 dexp2 = gcal.getTime(status);
3782 dexp1 = dexp2 - (5*60 + 43)*1000; // subtract 5m43s
3783
3784 if (U_FAILURE(status)) {
3785 errln("FAIL: Gregorian calendar error");
3786 }
3787
3788 DateFormat *fmt = DateFormat::createTimeInstance(DateFormat::kFull, Locale("zh"));
3789 if (fmt == NULL) {
3790 dataerrln("Unable to create DateFormat. Got NULL.");
3791 return;
3792 }
3793 fmt->adoptTimeZone(tz);
3794
3795 fmt->format(d1, s1);
3796 fmt->format(d2, s2);
3797
3798 dp1 = fmt->parse(s1, status);
3799 dp2 = fmt->parse(s2, status);
3800
3801 if (U_FAILURE(status)) {
3802 errln("FAIL: Parse failure");
3803 }
3804
3805 if (dp1 != dexp1) {
3806 errln("FAIL: Failed to parse " + s1 + " parsed: " + dp1 + " expected: " + dexp1);
3807 }
3808 if (dp2 != dexp2) {
3809 errln("FAIL: Failed to parse " + s2 + " parsed: " + dp2 + " expected: " + dexp2);
3810 }
3811
3812 delete fmt;
3813 }
3814
3815 typedef struct {
3816 const char * localeStr;
3817 UBool lenient;
3818 UBool expectFail;
3819 UnicodeString datePattern;
3820 UnicodeString dateString;
3821 } NumAsStringItem;
3822
TestNumberAsStringParsing()3823 void DateFormatTest::TestNumberAsStringParsing()
3824 {
3825 const NumAsStringItem items[] = {
3826 // loc lenient fail? datePattern dateString
3827 { "", FALSE, TRUE, UnicodeString("y MMMM d HH:mm:ss"), UnicodeString("2009 7 14 08:43:57") },
3828 { "", TRUE, FALSE, UnicodeString("y MMMM d HH:mm:ss"), UnicodeString("2009 7 14 08:43:57") },
3829 { "en", FALSE, FALSE, UnicodeString("MMM d, y"), UnicodeString("Jul 14, 2009") },
3830 { "en", TRUE, FALSE, UnicodeString("MMM d, y"), UnicodeString("Jul 14, 2009") },
3831 { "en", FALSE, TRUE, UnicodeString("MMM d, y"), UnicodeString("7 14, 2009") },
3832 { "en", TRUE, FALSE, UnicodeString("MMM d, y"), UnicodeString("7 14, 2009") },
3833 { "ja", FALSE, FALSE, UnicodeString("yyyy/MM/dd"), UnicodeString("2009/07/14") },
3834 { "ja", TRUE, FALSE, UnicodeString("yyyy/MM/dd"), UnicodeString("2009/07/14") },
3835 //{ "ja", FALSE, FALSE, UnicodeString("yyyy/MMMMM/d"), UnicodeString("2009/7/14") }, // #8860 covers test failure
3836 { "ja", TRUE, FALSE, UnicodeString("yyyy/MMMMM/d"), UnicodeString("2009/7/14") },
3837 { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3838 { "ja", TRUE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3839 { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3840 { "ja", TRUE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") }, // #8820 fixes test failure
3841 { "ko", FALSE, FALSE, UnicodeString("yyyy. M. d."), UnicodeString("2009. 7. 14.") },
3842 { "ko", TRUE, FALSE, UnicodeString("yyyy. M. d."), UnicodeString("2009. 7. 14.") },
3843 { "ko", FALSE, FALSE, UnicodeString("yyyy. MMMMM d."), CharsToUnicodeString("2009. 7\\uC6D4 14.") },
3844 { "ko", TRUE, FALSE, UnicodeString("yyyy. MMMMM d."), CharsToUnicodeString("2009. 7\\uC6D4 14.") }, // #8820 fixes test failure
3845 { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3846 { "ko", TRUE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3847 { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3848 { "ko", TRUE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") }, // #8820 fixes test failure
3849 { NULL, FALSE, FALSE, UnicodeString(""), UnicodeString("") }
3850 };
3851 const NumAsStringItem * itemPtr;
3852 for (itemPtr = items; itemPtr->localeStr != NULL; itemPtr++ ) {
3853 Locale locale = Locale::createFromName(itemPtr->localeStr);
3854 UErrorCode status = U_ZERO_ERROR;
3855 SimpleDateFormat formatter(itemPtr->datePattern, locale, status);
3856 if (U_FAILURE(status)) {
3857 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3858 return;
3859 }
3860
3861 formatter.setLenient(itemPtr->lenient);
3862 formatter.setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->lenient, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->lenient, status);
3863 UDate date1 = formatter.parse(itemPtr->dateString, status);
3864 if (U_FAILURE(status)) {
3865 if (!itemPtr->expectFail) {
3866 errln("FAIL, err when expected success: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3867 ": using pattern \"" + itemPtr->datePattern + "\", could not parse \"" + itemPtr->dateString + "\"; err: " + u_errorName(status) );
3868 }
3869 } else if (itemPtr->expectFail) {
3870 errln("FAIL, expected err but got none: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3871 ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\"." );
3872 } else if (!itemPtr->lenient) {
3873 UnicodeString formatted;
3874 formatter.format(date1, formatted);
3875 if (formatted != itemPtr->dateString) {
3876 errln("FAIL, mismatch formatting parsed date: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3877 ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\", formatted result \"" + formatted + "\".");
3878 }
3879 }
3880 }
3881 }
3882
TestISOEra()3883 void DateFormatTest::TestISOEra() {
3884
3885 const char* data[] = {
3886 // input, output
3887 "BC 4004-10-23T07:00:00Z", "BC 4004-10-23T07:00:00Z",
3888 "AD 4004-10-23T07:00:00Z", "AD 4004-10-23T07:00:00Z",
3889 "-4004-10-23T07:00:00Z" , "BC 4005-10-23T07:00:00Z",
3890 "4004-10-23T07:00:00Z" , "AD 4004-10-23T07:00:00Z",
3891 };
3892
3893 int32_t numData = 8;
3894
3895 UErrorCode status = U_ZERO_ERROR;
3896
3897 // create formatter
3898 SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("GGG yyyy-MM-dd'T'HH:mm:ss'Z"), status);
3899 failure(status, "new SimpleDateFormat", TRUE);
3900 if (status == U_MISSING_RESOURCE_ERROR) {
3901 if (fmt1 != NULL) {
3902 delete fmt1;
3903 }
3904 return;
3905 }
3906 for(int i=0; i < numData; i+=2) {
3907 // create input string
3908 UnicodeString in = data[i];
3909
3910 // parse string to date
3911 UDate dt1 = fmt1->parse(in, status);
3912 failure(status, "fmt->parse", TRUE);
3913
3914 // format date back to string
3915 UnicodeString out;
3916 out = fmt1->format(dt1, out);
3917 logln(out);
3918
3919 // check that roundtrip worked as expected
3920 UnicodeString expected = data[i+1];
3921 if (out != expected) {
3922 dataerrln((UnicodeString)"FAIL: " + in + " -> " + out + " expected -> " + expected);
3923 }
3924 }
3925
3926 delete fmt1;
3927 }
TestFormalChineseDate()3928 void DateFormatTest::TestFormalChineseDate() {
3929
3930 UErrorCode status = U_ZERO_ERROR;
3931 UnicodeString pattern(u"y\u5e74M\u6708d\u65e5");
3932 UnicodeString numsys_override(u"y=hanidec;M=hans;d=hans");
3933
3934 // create formatter
3935 SimpleDateFormat sdf(pattern, numsys_override, Locale::getChina(),status);
3936 if (failure(status, "new SimpleDateFormat with override", true)) {
3937 return;
3938 }
3939
3940 UDate thedate = date(2009-1900, UCAL_JULY, 28);
3941 FieldPosition pos(FieldPosition::DONT_CARE);
3942 UnicodeString result;
3943 sdf.format(thedate,result,pos);
3944
3945 UnicodeString expected = "\\u4e8c\\u3007\\u3007\\u4e5d\\u5e74\\u4e03\\u6708\\u4e8c\\u5341\\u516b\\u65e5";
3946 expected = expected.unescape();
3947 if (result != expected) {
3948 dataerrln((UnicodeString)"FAIL: -> " + result + " expected -> " + expected);
3949 }
3950
3951 UDate parsedate = sdf.parse(expected,status);
3952 if ( parsedate != thedate ) {
3953 UnicodeString pat1 ("yyyy-MM-dd'T'HH:mm:ss'Z'", -1, US_INV );
3954 SimpleDateFormat usf(pat1, Locale::getEnglish(), status);
3955 UnicodeString parsedres,expres;
3956 usf.format(parsedate,parsedres,pos);
3957 usf.format(thedate,expres,pos);
3958 dataerrln((UnicodeString)"FAIL: parsed -> " + parsedres + " expected -> " + expres);
3959 }
3960 }
3961
3962 // Test case for #8675
3963 // Incorrect parse offset with stand alone GMT string on 2nd or later iteration.
TestStandAloneGMTParse()3964 void DateFormatTest::TestStandAloneGMTParse() {
3965 UErrorCode status = U_ZERO_ERROR;
3966 SimpleDateFormat sdf("ZZZZ", Locale(""), status);
3967
3968 if (U_SUCCESS(status)) {
3969
3970 UnicodeString inText(u"GMT$$$");
3971 for (int32_t i = 0; i < 10; i++) {
3972 ParsePosition pos(0);
3973 sdf.parse(inText, pos);
3974 if (pos.getIndex() != 3) {
3975 errln((UnicodeString)"FAIL: Incorrect output parse position: actual=" + pos.getIndex() + " expected=3");
3976 }
3977 }
3978
3979 } else {
3980 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3981 }
3982 }
3983
TestParsePosition()3984 void DateFormatTest::TestParsePosition() {
3985 const char* TestData[][4] = {
3986 // {<pattern>, <lead>, <date string>, <trail>}
3987 {"yyyy-MM-dd HH:mm:ssZ", "", "2010-01-10 12:30:00+0500", ""},
3988 {"yyyy-MM-dd HH:mm:ss ZZZZ", "", "2010-01-10 12:30:00 GMT+05:00", ""},
3989 {"Z HH:mm:ss", "", "-0100 13:20:30", ""},
3990 {"y-M-d Z", "", "2011-8-25 -0400", " Foo"},
3991 {"y/M/d H:mm:ss z", "", "2011/7/1 12:34:00 PDT", ""},
3992 {"y/M/d H:mm:ss z", "+123", "2011/7/1 12:34:00 PDT", " PST"},
3993 {"vvvv a h:mm:ss", "", "Pacific Time AM 10:21:45", ""},
3994 {"HH:mm v M/d", "111", "14:15 PT 8/10", " 12345"},
3995 {"'time zone:' VVVV 'date:' yyyy-MM-dd", "xxxx", "time zone: Los Angeles Time date: 2010-02-25", "xxxx"},
3996 {"yG", "", "2012AD", ""},
3997 {"yG", "", "2012", "x"},
3998 {0, 0, 0, 0},
3999 };
4000
4001 for (int32_t i = 0; TestData[i][0]; i++) {
4002 UErrorCode status = U_ZERO_ERROR;
4003 SimpleDateFormat sdf(UnicodeString(TestData[i][0]), status);
4004 if (failure(status, "new SimpleDateFormat", TRUE)) return;
4005
4006 int32_t startPos, resPos;
4007
4008 // lead text
4009 UnicodeString input(TestData[i][1]);
4010 startPos = input.length();
4011
4012 // date string
4013 input += TestData[i][2];
4014 resPos = input.length();
4015
4016 // trail text
4017 input += TestData[i][3];
4018
4019 ParsePosition pos(startPos);
4020 //UDate d = sdf->parse(input, pos);
4021 (void)sdf.parse(input, pos);
4022
4023 if (pos.getIndex() != resPos) {
4024 errln(UnicodeString("FAIL: Parsing [") + input + "] with pattern [" + TestData[i][0] + "] returns position - "
4025 + pos.getIndex() + ", expected - " + resPos);
4026 }
4027 }
4028 }
4029
4030
4031 typedef struct {
4032 int32_t era;
4033 int32_t year;
4034 int32_t month; // 1-based
4035 int32_t isLeapMonth;
4036 int32_t day;
4037 } ChineseCalTestDate;
4038
4039 #define NUM_TEST_DATES 3
4040
4041 typedef struct {
4042 const char * locale;
4043 int32_t style; // <0 => custom
4044 UnicodeString dateString[NUM_TEST_DATES];
4045 } MonthPatternItem;
4046
TestMonthPatterns()4047 void DateFormatTest::TestMonthPatterns()
4048 {
4049 const ChineseCalTestDate dates[NUM_TEST_DATES] = {
4050 // era yr mo lp da
4051 { 78, 29, 4, 0, 2 }, // (in chinese era 78) gregorian 2012-4-22
4052 { 78, 29, 4, 1, 2 }, // (in chinese era 78) gregorian 2012-5-22
4053 { 78, 29, 5, 0, 2 }, // (in chinese era 78) gregorian 2012-6-20
4054 };
4055
4056 const MonthPatternItem items[] = {
4057 // locale date style; expected formats for the 3 dates above
4058 { "root@calendar=chinese", DateFormat::kLong, { UnicodeString("2012(ren-chen) M04 2"), UnicodeString("2012(ren-chen) M04bis 2"), UnicodeString("2012(ren-chen) M05 2") } },
4059 { "root@calendar=chinese", DateFormat::kShort, { UnicodeString("2012-04-02"), UnicodeString("2012-04bis-02"), UnicodeString("2012-05-02") } },
4060 { "root@calendar=chinese", -1, { UnicodeString("29-4-2"), UnicodeString("29-4bis-2"), UnicodeString("29-5-2") } },
4061 { "root@calendar=chinese", -2, { UnicodeString("78x29-4-2"), UnicodeString("78x29-4bis-2"), UnicodeString("78x29-5-2") } },
4062 { "root@calendar=chinese", -3, { UnicodeString("ren-chen-4-2"), UnicodeString("ren-chen-4bis-2"), UnicodeString("ren-chen-5-2") } },
4063 { "root@calendar=chinese", -4, { UnicodeString("ren-chen M04 2"), UnicodeString("ren-chen M04bis 2"), UnicodeString("ren-chen M05 2") } },
4064 { "en@calendar=gregorian", -3, { UnicodeString("2012-4-22"), UnicodeString("2012-5-22"), UnicodeString("2012-6-20") } },
4065 { "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)") } },
4066 { "en@calendar=chinese", DateFormat::kShort, { UnicodeString("4/2/2012"), UnicodeString("4bis/2/2012"), UnicodeString("5/2/2012") } },
4067 { "zh@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4068 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u95F0\\u56DB\\u6708\\u521D\\u4E8C"),
4069 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4070 { "zh@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("2012/4/2"),
4071 CharsToUnicodeString("2012/\\u95F04/2"),
4072 CharsToUnicodeString("2012/5/2") } },
4073 { "zh@calendar=chinese", -3, { CharsToUnicodeString("\\u58EC\\u8FB0-4-2"),
4074 CharsToUnicodeString("\\u58EC\\u8FB0-\\u95F04-2"),
4075 CharsToUnicodeString("\\u58EC\\u8FB0-5-2") } },
4076 { "zh@calendar=chinese", -4, { CharsToUnicodeString("\\u58EC\\u8FB0 \\u56DB\\u6708 2"),
4077 CharsToUnicodeString("\\u58EC\\u8FB0 \\u95F0\\u56DB\\u6708 2"),
4078 CharsToUnicodeString("\\u58EC\\u8FB0 \\u4E94\\u6708 2") } },
4079 { "zh_Hant@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4080 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u958F\\u56DB\\u6708\\u521D\\u4E8C"),
4081 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4082 { "zh_Hant@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("2012/4/2"),
4083 CharsToUnicodeString("2012/\\u958F4/2"),
4084 CharsToUnicodeString("2012/5/2") } },
4085 { "fr@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2 s\\u00ECyu\\u00E8 ren-chen"),
4086 CharsToUnicodeString("2 s\\u00ECyu\\u00E8bis ren-chen"),
4087 CharsToUnicodeString("2 w\\u01D4yu\\u00E8 ren-chen") } },
4088 { "fr@calendar=chinese", DateFormat::kShort, { UnicodeString("2/4/29"), UnicodeString("2/4bis/29"), UnicodeString("2/5/29") } },
4089 { "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)") } },
4090 { "en@calendar=dangi", DateFormat::kShort, { UnicodeString("3bis/2/2012"), UnicodeString("4/2/2012"), UnicodeString("5/1/2012") } },
4091 { "en@calendar=dangi", -2, { UnicodeString("78x29-3bis-2"), UnicodeString("78x29-4-2"), UnicodeString("78x29-5-1") } },
4092 { "ko@calendar=dangi", DateFormat::kLong, { CharsToUnicodeString("\\uC784\\uC9C4\\uB144 \\uC7243\\uC6D4 2\\uC77C"),
4093 CharsToUnicodeString("\\uC784\\uC9C4\\uB144 4\\uC6D4 2\\uC77C"),
4094 CharsToUnicodeString("\\uC784\\uC9C4\\uB144 5\\uC6D4 1\\uC77C") } },
4095 { "ko@calendar=dangi", DateFormat::kShort, { CharsToUnicodeString("29. \\uC7243. 2."),
4096 CharsToUnicodeString("29. 4. 2."),
4097 CharsToUnicodeString("29. 5. 1.") } },
4098 // terminator
4099 { NULL, 0, { UnicodeString(""), UnicodeString(""), UnicodeString("") } }
4100 };
4101
4102 //. style: -1 -2 -3 -4
4103 const UnicodeString customPatterns[] = { "y-Ml-d", "G'x'y-Ml-d", "U-M-d", "U MMM d" }; // like old root pattern, using 'l'
4104
4105 UErrorCode status = U_ZERO_ERROR;
4106 Locale rootChineseCalLocale = Locale::createFromName("root@calendar=chinese");
4107 Calendar * rootChineseCalendar = Calendar::createInstance(rootChineseCalLocale, status);
4108 if (U_SUCCESS(status)) {
4109 const MonthPatternItem * itemPtr;
4110 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4111 Locale locale = Locale::createFromName(itemPtr->locale);
4112 DateFormat * dmft = (itemPtr->style >= 0)?
4113 DateFormat::createDateInstance((DateFormat::EStyle)itemPtr->style, locale):
4114 new SimpleDateFormat(customPatterns[-itemPtr->style - 1], locale, status);
4115 if ( dmft != NULL ) {
4116 if (U_SUCCESS(status)) {
4117 const ChineseCalTestDate * datePtr = dates;
4118 int32_t idate;
4119 for (idate = 0; idate < NUM_TEST_DATES; idate++, datePtr++) {
4120 rootChineseCalendar->clear();
4121 rootChineseCalendar->set(UCAL_ERA, datePtr->era);
4122 rootChineseCalendar->set(datePtr->year, datePtr->month-1, datePtr->day);
4123 rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, datePtr->isLeapMonth);
4124 UnicodeString result;
4125 FieldPosition fpos(FieldPosition::DONT_CARE);
4126 dmft->format(*rootChineseCalendar, result, fpos);
4127 if ( result.compare(itemPtr->dateString[idate]) != 0 ) {
4128 errln( UnicodeString("FAIL: Chinese calendar format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4129 ", expected \"" + itemPtr->dateString[idate] + "\", got \"" + result + "\"");
4130 } else {
4131 // formatted OK, try parse
4132 ParsePosition ppos(0);
4133 // ensure we are really parsing the fields we should be
4134 rootChineseCalendar->set(UCAL_YEAR, 1);
4135 rootChineseCalendar->set(UCAL_MONTH, 0);
4136 rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, 0);
4137 rootChineseCalendar->set(UCAL_DATE, 1);
4138 //
4139 dmft->parse(result, *rootChineseCalendar, ppos);
4140 int32_t year = rootChineseCalendar->get(UCAL_YEAR, status);
4141 int32_t month = rootChineseCalendar->get(UCAL_MONTH, status) + 1;
4142 int32_t isLeapMonth = rootChineseCalendar->get(UCAL_IS_LEAP_MONTH, status);
4143 int32_t day = rootChineseCalendar->get(UCAL_DATE, status);
4144 if ( ppos.getIndex() < result.length() || year != datePtr->year || month != datePtr->month || isLeapMonth != datePtr->isLeapMonth || day != datePtr->day ) {
4145 errln( UnicodeString("FAIL: Chinese calendar parse for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4146 ", string \"" + result + "\", expected " + datePtr->year +"-"+datePtr->month+"("+datePtr->isLeapMonth+")-"+datePtr->day + ", got pos " +
4147 ppos.getIndex() + " " + year +"-"+month+"("+isLeapMonth+")-"+day);
4148 }
4149 }
4150 }
4151 } else {
4152 dataerrln("Error creating SimpleDateFormat for Chinese calendar- %s", u_errorName(status));
4153 }
4154 delete dmft;
4155 } else {
4156 dataerrln("FAIL: Unable to create DateFormat for Chinese calendar- %s", u_errorName(status));
4157 }
4158 }
4159 delete rootChineseCalendar;
4160 } else {
4161 errln(UnicodeString("FAIL: Unable to create Calendar for root@calendar=chinese"));
4162 }
4163 }
4164
4165 typedef struct {
4166 const char * locale;
4167 UnicodeString pattern;
4168 UDisplayContext capitalizationContext;
4169 UnicodeString expectedFormat;
4170 } TestContextItem;
4171
TestContext()4172 void DateFormatTest::TestContext()
4173 {
4174 const UDate july022008 = 1215000001979.0;
4175 const TestContextItem items[] = {
4176 //locale pattern capitalizationContext expected formatted date
4177 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_NONE, UnicodeString("juillet 2008") },
4178 #if !UCONFIG_NO_BREAK_ITERATION
4179 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UnicodeString("juillet 2008") },
4180 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, UnicodeString("Juillet 2008") },
4181 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, UnicodeString("juillet 2008") },
4182 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE, UnicodeString("Juillet 2008") },
4183 #endif
4184 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_NONE, CharsToUnicodeString("\\u010Dervenec 2008") },
4185 #if !UCONFIG_NO_BREAK_ITERATION
4186 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, CharsToUnicodeString("\\u010Dervenec 2008") },
4187 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, CharsToUnicodeString("\\u010Cervenec 2008") },
4188 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, CharsToUnicodeString("\\u010Cervenec 2008") },
4189 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE, CharsToUnicodeString("\\u010Dervenec 2008") },
4190 #endif
4191 // terminator
4192 { NULL, UnicodeString(""), (UDisplayContext)0, UnicodeString("") }
4193 };
4194 UErrorCode status = U_ZERO_ERROR;
4195 Calendar* cal = Calendar::createInstance(status);
4196 if (U_FAILURE(status)) {
4197 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4198 } else {
4199 cal->setTime(july022008, status);
4200 const TestContextItem * itemPtr;
4201 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4202 Locale locale = Locale::createFromName(itemPtr->locale);
4203 status = U_ZERO_ERROR;
4204 SimpleDateFormat * sdmft = new SimpleDateFormat(itemPtr->pattern, locale, status);
4205 if (U_FAILURE(status)) {
4206 dataerrln(UnicodeString("FAIL: Unable to create SimpleDateFormat for specified pattern with locale ") + UnicodeString(itemPtr->locale));
4207 } else {
4208 sdmft->setContext(itemPtr->capitalizationContext, status);
4209 UnicodeString result;
4210 FieldPosition pos(FieldPosition::DONT_CARE);
4211 sdmft->format(*cal, result, pos);
4212 if (result.compare(itemPtr->expectedFormat) != 0) {
4213 errln(UnicodeString("FAIL: format for locale ") + UnicodeString(itemPtr->locale) +
4214 ", status " + (int)status +
4215 ", capitalizationContext " + (int)itemPtr->capitalizationContext +
4216 ", expected " + itemPtr->expectedFormat + ", got " + result);
4217 }
4218 }
4219 if (sdmft) {
4220 delete sdmft;
4221 }
4222 }
4223 }
4224 if (cal) {
4225 delete cal;
4226 }
4227 }
4228
4229 // test item for a particular locale + calendar and date format
4230 typedef struct {
4231 int32_t era;
4232 int32_t year;
4233 int32_t month;
4234 int32_t day;
4235 int32_t hour;
4236 int32_t minute;
4237 UnicodeString formattedDate;
4238 } CalAndFmtTestItem;
4239
4240 // test item giving locale + calendar, date format, and CalAndFmtTestItems
4241 typedef struct {
4242 const char * locale; // with calendar
4243 DateFormat::EStyle style;
4244 UnicodeString pattern; // ignored unless style == DateFormat::kNone
4245 const CalAndFmtTestItem *caftItems;
4246 } TestNonGregoItem;
4247
TestNonGregoFmtParse()4248 void DateFormatTest::TestNonGregoFmtParse()
4249 {
4250 // test items for he@calendar=hebrew, long date format
4251 const CalAndFmtTestItem cafti_he_hebrew_long[] = {
4252 { 0, 4999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05D3\\u05F3\\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4253 { 0, 5100, 0, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05E7\\u05F3") },
4254 { 0, 5774, 5, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05D0\\u05D3\\u05E8 \\u05D0\\u05F3 \\u05EA\\u05E9\\u05E2\\u05F4\\u05D3") },
4255 { 0, 5999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4256 { 0, 6100, 0, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05D5\\u05F3\\u05E7\\u05F3") },
4257 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4258 };
4259 const CalAndFmtTestItem cafti_zh_chinese_custU[] = {
4260 { 78, 31, 0, 1, 12, 0, CharsToUnicodeString("2014\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4261 { 77, 31, 0, 1, 12, 0, CharsToUnicodeString("1954\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4262 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4263 };
4264 const CalAndFmtTestItem cafti_zh_chinese_custNoU[] = {
4265 { 78, 31, 0, 1, 12, 0, CharsToUnicodeString("2014\\u5E74\\u6B63\\u67081") },
4266 { 77, 31, 0, 1, 12, 0, CharsToUnicodeString("1954\\u5E74\\u6B63\\u67081") },
4267 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4268 };
4269 const CalAndFmtTestItem cafti_ja_japanese_custGy[] = {
4270 {235, 26, 2, 5, 12, 0, CharsToUnicodeString("2014(\\u5E73\\u621026)\\u5E743\\u67085\\u65E5") },
4271 {234, 60, 2, 5, 12, 0, CharsToUnicodeString("1985(\\u662D\\u548C60)\\u5E743\\u67085\\u65E5") },
4272 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4273 };
4274 const CalAndFmtTestItem cafti_ja_japanese_custNoGy[] = {
4275 {235, 26, 2, 5, 12, 0, CharsToUnicodeString("2014\\u5E743\\u67085\\u65E5") },
4276 {234, 60, 2, 5, 12, 0, CharsToUnicodeString("1985\\u5E743\\u67085\\u65E5") },
4277 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4278 };
4279 const CalAndFmtTestItem cafti_en_islamic_cust[] = {
4280 { 0, 1384, 0, 1, 12, 0, UnicodeString("1 Muh. 1384 AH, 1964") },
4281 { 0, 1436, 0, 1, 12, 0, UnicodeString("1 Muh. 1436 AH, 2014") },
4282 { 0, 1487, 0, 1, 12, 0, UnicodeString("1 Muh. 1487 AH, 2064") },
4283 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4284 };
4285 // overal test items
4286 const TestNonGregoItem items[] = {
4287 { "he@calendar=hebrew", DateFormat::kLong, UnicodeString(""), cafti_he_hebrew_long },
4288 { "zh@calendar=chinese", DateFormat::kNone, CharsToUnicodeString("rU\\u5E74MMMd"), cafti_zh_chinese_custU },
4289 { "zh@calendar=chinese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74MMMd"), cafti_zh_chinese_custNoU },
4290 { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r(Gy)\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custGy },
4291 { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custNoGy },
4292 { "en@calendar=islamic", DateFormat::kNone, UnicodeString("d MMM y G, r"), cafti_en_islamic_cust },
4293 { NULL, DateFormat::kNone, UnicodeString(""), NULL } // terminator
4294 };
4295 const TestNonGregoItem * itemPtr;
4296 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++) {
4297 Locale locale = Locale::createFromName(itemPtr->locale);
4298 LocalPointer<DateFormat> dfmt;
4299 UErrorCode status = U_ZERO_ERROR;
4300 if (itemPtr->style != DateFormat::kNone) {
4301 dfmt.adoptInstead(DateFormat::createDateInstance(itemPtr->style, locale));
4302 } else {
4303 dfmt.adoptInstead(new SimpleDateFormat(itemPtr->pattern, locale, status));
4304 }
4305 if (U_FAILURE(status)) {
4306 dataerrln("new SimpleDateFormat fails for locale %s", itemPtr->locale);
4307 } else if (!dfmt.isValid()) {
4308 dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->locale);
4309 } else {
4310 LocalPointer<Calendar>cal((dfmt->getCalendar())->clone());
4311 if (!cal.isValid()) {
4312 dataerrln("(DateFormat::getCalendar)->clone() fails for locale %s", itemPtr->locale);
4313 } else {
4314 const CalAndFmtTestItem * caftItemPtr;
4315 for (caftItemPtr = itemPtr->caftItems; caftItemPtr->year != 0; caftItemPtr++) {
4316 cal->clear();
4317 cal->set(UCAL_ERA, caftItemPtr->era);
4318 cal->set(UCAL_YEAR, caftItemPtr->year);
4319 cal->set(UCAL_MONTH, caftItemPtr->month);
4320 cal->set(UCAL_DATE, caftItemPtr->day);
4321 cal->set(UCAL_HOUR_OF_DAY, caftItemPtr->hour);
4322 cal->set(UCAL_MINUTE, caftItemPtr->minute);
4323 UnicodeString result;
4324 FieldPosition fpos(FieldPosition::DONT_CARE);
4325 dfmt->format(*cal, result, fpos);
4326 if ( result.compare(caftItemPtr->formattedDate) != 0 ) {
4327 errln( UnicodeString("FAIL: date format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4328 ", expected \"" + caftItemPtr->formattedDate + "\", got \"" + result + "\"");
4329 } else {
4330 // formatted OK, try parse
4331 ParsePosition ppos(0);
4332 dfmt->parse(result, *cal, ppos);
4333 status = U_ZERO_ERROR;
4334 int32_t era = cal->get(UCAL_ERA, status);
4335 int32_t year = cal->get(UCAL_YEAR, status);
4336 int32_t month = cal->get(UCAL_MONTH, status);
4337 int32_t day = cal->get(UCAL_DATE, status);
4338 if ( U_FAILURE(status) || ppos.getIndex() < result.length() || era != caftItemPtr->era ||
4339 year != caftItemPtr->year || month != caftItemPtr->month || day != caftItemPtr->day ) {
4340 errln( UnicodeString("FAIL: date parse for locale ") + UnicodeString(itemPtr->locale) +
4341 ", style " + itemPtr->style + ", string \"" + result + "\", expected " +
4342 caftItemPtr->era +":"+caftItemPtr->year +"-"+caftItemPtr->month+"-"+caftItemPtr->day + ", got pos " +
4343 ppos.getIndex() + " " + year +"-"+month+"-"+day + " status " + UnicodeString(u_errorName(status)) );
4344 }
4345 }
4346 }
4347 }
4348 }
4349 }
4350 }
4351
4352 typedef struct {
4353 const char* localeID;
4354 DateFormat::EStyle style;
4355 UnicodeString expectPattern;
4356 UnicodeString expectFormat;
4357 } TestFmtWithNumSysItem;
4358 enum { kBBufMax = 128 };
TestFormatsWithNumberSystems()4359 void DateFormatTest::TestFormatsWithNumberSystems()
4360 {
4361 LocalPointer<TimeZone> zone(TimeZone::createTimeZone(UnicodeString("UTC")));
4362 const UDate date = 1451556000000.0; // for UTC: grego 31-Dec-2015 10 AM, hebrew 19 tevet 5776, chinese yi-wei 11mo 21day
4363 const TestFmtWithNumSysItem items[] = {
4364 { "haw@calendar=gregorian", DateFormat::kShort, UnicodeString("d/M/yy"), UnicodeString("31/xii/15") },
4365 { "he@calendar=hebrew", DateFormat::kLong, CharsToUnicodeString("d \\u05D1MMMM y"), CharsToUnicodeString("\\u05D9\\u05F4\\u05D8 \\u05D1\\u05D8\\u05D1\\u05EA \\u05EA\\u05E9\\u05E2\\u05F4\\u05D5") },
4366 { "zh@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u5341\\u4E00\\u6708\\u5EFF\\u4E00") },
4367 { "zh_Hant@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u51AC\\u6708\\u5EFF\\u4E00") },
4368 { "ja@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("U\\u5E74MMMd\\u65E5"), CharsToUnicodeString("\\u4E59\\u672A\\u5E74\\u5341\\u4E00\\u6708\\u4E8C\\u4E00\\u65E5") },
4369 { NULL, DateFormat::kNone, UnicodeString(""), UnicodeString("") },
4370 };
4371 const TestFmtWithNumSysItem * itemPtr;
4372 for (itemPtr = items; itemPtr->localeID != NULL; itemPtr++) {
4373 char bExpected[kBBufMax];
4374 char bResult[kBBufMax];
4375 UErrorCode status = U_ZERO_ERROR;
4376 Locale locale = Locale::createFromName(itemPtr->localeID);
4377 LocalPointer<Calendar> cal(Calendar::createInstance(zone.orphan(), locale, status));
4378 if (U_FAILURE(status)) {
4379 dataerrln("Calendar::createInstance fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4380 continue;
4381 }
4382 cal->setTime(date, status);
4383 if (U_FAILURE(status)) {
4384 dataerrln("Calendar::setTime fails for locale %s, date %.1f, status %s", itemPtr->localeID, date, u_errorName(status));
4385 continue;
4386 }
4387 LocalPointer<SimpleDateFormat> sdfmt(static_cast<SimpleDateFormat *>(DateFormat::createDateInstance(itemPtr->style, locale)));
4388 if (sdfmt.isNull()) {
4389 dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->localeID);
4390 continue;
4391 }
4392 UnicodeString getFormat;
4393 sdfmt->format(*(cal.getAlias()), getFormat, NULL, status);
4394 if (U_FAILURE(status)) {
4395 errln("DateFormat::format fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4396 continue;
4397 }
4398 if (getFormat.compare(itemPtr->expectFormat) != 0) {
4399 itemPtr->expectFormat.extract(0, itemPtr->expectFormat.length(), bExpected, kBBufMax);
4400 getFormat.extract(0, getFormat.length(), bResult, kBBufMax);
4401 errln("DateFormat::format for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4402 }
4403 UnicodeString getPattern;
4404 sdfmt->toPattern(getPattern);
4405 if (getPattern.compare(itemPtr->expectPattern) != 0) {
4406 itemPtr->expectPattern.extract(0, itemPtr->expectPattern.length(), bExpected, kBBufMax);
4407 getPattern.extract(0, getPattern.length(), bResult, kBBufMax);
4408 errln("DateFormat::toPattern() for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4409 }
4410 }
4411 }
4412
4413 static const UDate TEST_DATE = 1326585600000.; // 2012-jan-15
4414
TestDotAndAtLeniency()4415 void DateFormatTest::TestDotAndAtLeniency() {
4416 // Test for date/time parsing regression with CLDR 22.1/ICU 50 pattern strings.
4417 // For details see http://bugs.icu-project.org/trac/ticket/9789
4418 static const char *locales[] = { "en", "fr" };
4419 for (int32_t i = 0; i < UPRV_LENGTHOF(locales); ++i) {
4420 Locale locale(locales[i]);
4421
4422 for (DateFormat::EStyle dateStyle = DateFormat::FULL; dateStyle <= DateFormat::SHORT;
4423 dateStyle = static_cast<DateFormat::EStyle>(dateStyle + 1)) {
4424 LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance(dateStyle, locale));
4425
4426 for (DateFormat::EStyle timeStyle = DateFormat::FULL; timeStyle <= DateFormat::SHORT;
4427 timeStyle = static_cast<DateFormat::EStyle>(timeStyle + 1)) {
4428 LocalPointer<DateFormat> format(DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale));
4429 LocalPointer<DateFormat> timeFormat(DateFormat::createTimeInstance(timeStyle, locale));
4430 UnicodeString formattedString;
4431 if (format.isNull()) {
4432 dataerrln("Unable to create DateFormat");
4433 continue;
4434 }
4435 format->format(TEST_DATE, formattedString);
4436
4437 if (!showParse(*format, formattedString)) {
4438 errln(UnicodeString(" with date-time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4439 }
4440
4441 UnicodeString ds, ts;
4442 formattedString = dateFormat->format(TEST_DATE, ds) + " " + timeFormat->format(TEST_DATE, ts);
4443 if (!showParse(*format, formattedString)) {
4444 errln(UnicodeString(" with date sp sp time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4445 }
4446 if (formattedString.indexOf("n ") >= 0) { // will add "." after the end of text ending in 'n', like Jan.
4447 UnicodeString plusDot(formattedString);
4448 plusDot.findAndReplace("n ", "n. ").append(".");
4449 if (!showParse(*format, plusDot)) {
4450 errln(UnicodeString(" with date plus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4451 }
4452 }
4453 if (formattedString.indexOf(". ") >= 0) { // will subtract "." at the end of strings.
4454 UnicodeString minusDot(formattedString);
4455 minusDot.findAndReplace(". ", " ");
4456 if (!showParse(*format, minusDot)) {
4457 errln(UnicodeString(" with date minus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4458 }
4459 }
4460 }
4461 }
4462 }
4463 }
4464
showParse(DateFormat & format,const UnicodeString & formattedString)4465 UBool DateFormatTest::showParse(DateFormat &format, const UnicodeString &formattedString) {
4466 ParsePosition parsePosition;
4467 UDate parsed = format.parse(formattedString, parsePosition);
4468 UBool ok = TEST_DATE == parsed && parsePosition.getIndex() == formattedString.length();
4469 UnicodeString pattern;
4470 static_cast<SimpleDateFormat &>(format).toPattern(pattern);
4471 if (ok) {
4472 logln(pattern + " parsed: " + formattedString);
4473 } else {
4474 errln(pattern + " fails to parse: " + formattedString);
4475 }
4476 return ok;
4477 }
4478
4479
4480 typedef struct {
4481 const char * locale;
4482 UBool leniency;
4483 UnicodeString parseString;
4484 UnicodeString pattern;
4485 UnicodeString expectedResult; // empty string indicates expected error
4486 } TestDateFormatLeniencyItem;
4487
TestDateFormatLeniency()4488 void DateFormatTest::TestDateFormatLeniency() {
4489 // For details see http://bugs.icu-project.org/trac/ticket/10261
4490
4491 const UDate july022008 = 1215000001979.0;
4492 const TestDateFormatLeniencyItem items[] = {
4493 //locale leniency parse String pattern expected result
4494 { "en", true, UnicodeString("2008-07 02"), UnicodeString("yyyy-LLLL dd"), UnicodeString("2008-July 02") },
4495 { "en", false, UnicodeString("2008-07 02"), UnicodeString("yyyy-LLLL dd"), UnicodeString("") },
4496 { "en", true, UnicodeString("2008-Jan 02"), UnicodeString("yyyy-LLL. dd"), UnicodeString("2008-Jan. 02") },
4497 { "en", false, UnicodeString("2008-Jan 02"), UnicodeString("yyyy-LLL. dd"), UnicodeString("") },
4498 { "en", true, UnicodeString("2008-Jan--02"), UnicodeString("yyyy-MMM' -- 'dd"), UnicodeString("2008-Jan -- 02") },
4499 { "en", false, UnicodeString("2008-Jan--02"), UnicodeString("yyyy-MMM' -- 'dd"), UnicodeString("") },
4500 // terminator
4501 { NULL, true, UnicodeString(""), UnicodeString(""), UnicodeString("") }
4502 };
4503 UErrorCode status = U_ZERO_ERROR;
4504 LocalPointer<Calendar> cal(Calendar::createInstance(status));
4505 if (U_FAILURE(status)) {
4506 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4507 return;
4508 }
4509 cal->setTime(july022008, status);
4510 const TestDateFormatLeniencyItem * itemPtr;
4511 LocalPointer<SimpleDateFormat> sdmft;
4512 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4513
4514 Locale locale = Locale::createFromName(itemPtr->locale);
4515 status = U_ZERO_ERROR;
4516 ParsePosition pos(0);
4517 sdmft.adoptInsteadAndCheckErrorCode(new SimpleDateFormat(itemPtr->pattern, locale, status), status);
4518 if (U_FAILURE(status)) {
4519 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4520 continue;
4521 }
4522 sdmft->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->leniency, status).
4523 setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->leniency, status).
4524 setBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, itemPtr->leniency, status);
4525 UDate d = sdmft->parse(itemPtr->parseString, pos);
4526
4527 if(itemPtr->expectedResult.length() == 0) {
4528 if(pos.getErrorIndex() != -1) {
4529 continue;
4530 } else {
4531 errln("error: unexpected parse success - " + itemPtr->parseString +
4532 " - pattern " + itemPtr->pattern +
4533 " - error index " + pos.getErrorIndex() +
4534 " - leniency " + itemPtr->leniency);
4535 continue;
4536 }
4537 }
4538 if(pos.getErrorIndex() != -1) {
4539 errln("error: parse error for string - " + itemPtr->parseString +
4540 " - pattern " + itemPtr->pattern +
4541 " - idx " + pos.getIndex() +
4542 " - error index "+pos.getErrorIndex() +
4543 " - leniency " + itemPtr->leniency);
4544 continue;
4545 }
4546
4547 UnicodeString formatResult("");
4548 sdmft->format(d, formatResult);
4549 if(formatResult.compare(itemPtr->expectedResult) != 0) {
4550 errln("error: unexpected format result. pattern["+itemPtr->pattern+"] expected[" + itemPtr->expectedResult + "] but result was[" + formatResult + "]");
4551 continue;
4552 } else {
4553 logln("formatted results match! - " + formatResult);
4554 }
4555
4556 }
4557 }
4558
4559
4560 typedef struct {
4561 UBool leniency;
4562 UnicodeString parseString;
4563 UnicodeString pattern;
4564 UnicodeString expectedResult; // empty string indicates expected error
4565 } TestMultiPatternMatchItem;
4566
TestParseMultiPatternMatch()4567 void DateFormatTest::TestParseMultiPatternMatch() {
4568 // For details see http://bugs.icu-project.org/trac/ticket/10336
4569 const TestMultiPatternMatchItem items[] = {
4570 // leniency parse String pattern expected result
4571 {true, UnicodeString("2013-Sep 13"), UnicodeString("yyyy-MMM dd"), UnicodeString("2013-Sep 13")},
4572 {true, UnicodeString("2013-September 14"), UnicodeString("yyyy-MMM dd"), UnicodeString("2013-Sep 14")},
4573 {false, UnicodeString("2013-September 15"), UnicodeString("yyyy-MMM dd"), UnicodeString("")},
4574 {false, UnicodeString("2013-September 16"), UnicodeString("yyyy-MMMM dd"), UnicodeString("2013-September 16")},
4575 {true, UnicodeString("2013-Sep 17"), UnicodeString("yyyy-LLL dd"), UnicodeString("2013-Sep 17")},
4576 {true, UnicodeString("2013-September 18"), UnicodeString("yyyy-LLL dd"), UnicodeString("2013-Sep 18")},
4577 {false, UnicodeString("2013-September 19"), UnicodeString("yyyy-LLL dd"), UnicodeString("")},
4578 {false, UnicodeString("2013-September 20"), UnicodeString("yyyy-LLLL dd"), UnicodeString("2013-September 20")},
4579 {true, UnicodeString("2013 Sat Sep 21"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("2013 Sat Sep 21")},
4580 {true, UnicodeString("2013 Sunday Sep 22"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("2013 Sun Sep 22")},
4581 {false, UnicodeString("2013 Monday Sep 23"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("")},
4582 {false, UnicodeString("2013 Tuesday Sep 24"), UnicodeString("yyyy EEEE MMM dd"), UnicodeString("2013 Tuesday Sep 24")},
4583 {true, UnicodeString("2013 Wed Sep 25"), UnicodeString("yyyy eee MMM dd"), UnicodeString("2013 Wed Sep 25")},
4584 {true, UnicodeString("2013 Thu Sep 26"), UnicodeString("yyyy eee MMM dd"), UnicodeString("2013 Thu Sep 26")},
4585 {false, UnicodeString("2013 Friday Sep 27"), UnicodeString("yyyy eee MMM dd"), UnicodeString("")},
4586 {false, UnicodeString("2013 Saturday Sep 28"), UnicodeString("yyyy eeee MMM dd"), UnicodeString("2013 Saturday Sep 28")},
4587 {true, UnicodeString("2013 Sun Sep 29"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("2013 Sun Sep 29")},
4588 {true, UnicodeString("2013 Monday Sep 30"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("2013 Mon Sep 30")},
4589 {false, UnicodeString("2013 Sunday Oct 13"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("")},
4590 {false, UnicodeString("2013 Monday Oct 14"), UnicodeString("yyyy cccc MMM dd"), UnicodeString("2013 Monday Oct 14")},
4591 {true, UnicodeString("2013 Oct 15 Q4"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 15 Q4")},
4592 {true, UnicodeString("2013 Oct 16 4th quarter"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 16 Q4")},
4593 {false, UnicodeString("2013 Oct 17 4th quarter"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("")},
4594 {false, UnicodeString("2013 Oct 18 Q4"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 18 Q4")},
4595 {true, UnicodeString("2013 Oct 19 Q4"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 19 4th quarter")},
4596 {true, UnicodeString("2013 Oct 20 4th quarter"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 20 4th quarter")},
4597 {false, UnicodeString("2013 Oct 21 Q4"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("")},
4598 {false, UnicodeString("2013 Oct 22 4th quarter"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 22 4th quarter")},
4599 {false, UnicodeString("--end--"), UnicodeString(""), UnicodeString("")},
4600 };
4601
4602 UErrorCode status = U_ZERO_ERROR;
4603 LocalPointer<Calendar> cal(Calendar::createInstance(status));
4604 if (U_FAILURE(status)) {
4605 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4606 return;
4607 }
4608 const TestMultiPatternMatchItem * itemPtr;
4609 DateFormat* sdmft = DateFormat::createDateInstance();
4610 if (sdmft == NULL) {
4611 dataerrln(UnicodeString("FAIL: Unable to create DateFormat"));
4612 return;
4613 }
4614 for (itemPtr = items; itemPtr->parseString != "--end--"; itemPtr++ ) {
4615 status = U_ZERO_ERROR;
4616 ParsePosition pos(0);
4617 ((SimpleDateFormat*) sdmft)->applyPattern(itemPtr->pattern);
4618 if (U_FAILURE(status)) {
4619 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4620 continue;
4621 }
4622 sdmft->setBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, itemPtr->leniency, status);
4623 UDate d = sdmft->parse(itemPtr->parseString, pos);
4624
4625 if(itemPtr->expectedResult.length() == 0) {
4626 if(pos.getErrorIndex() != -1) {
4627 continue;
4628 } else {
4629 errln("error: unexpected parse success - " + itemPtr->parseString +
4630 " - error index " + pos.getErrorIndex() +
4631 " - leniency " + itemPtr->leniency);
4632 continue;
4633 }
4634 }
4635 if(pos.getErrorIndex() != -1) {
4636 errln("error: parse error for string - " +itemPtr->parseString + " -- idx["+pos.getIndex()+"] errIdx["+pos.getErrorIndex()+"]");
4637 continue;
4638 }
4639
4640 UnicodeString formatResult("");
4641 sdmft->format(d, formatResult);
4642 if(formatResult.compare(itemPtr->expectedResult) != 0) {
4643 errln("error: unexpected format result. expected[" + itemPtr->expectedResult + "] but result was[" + formatResult + "]");
4644 } else {
4645 logln("formatted results match! - " + formatResult);
4646 }
4647 }
4648 delete sdmft;
4649 }
4650
TestParseLeniencyAPIs()4651 void DateFormatTest::TestParseLeniencyAPIs() {
4652 UErrorCode status = U_ZERO_ERROR;
4653 LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance());
4654 DateFormat *fmt = dateFormat.getAlias();
4655 if (fmt == NULL) {
4656 dataerrln("Failed calling dateFormat.getAlias()");
4657 return;
4658 }
4659
4660 assertTrue("isLenient default", fmt->isLenient());
4661 assertTrue("isCalendarLenient default", fmt->isCalendarLenient());
4662 assertTrue("ALLOW_WHITESPACE default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4663 assertTrue("ALLOW_NUMERIC default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4664 assertTrue("PARTIAL_MATCH default", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4665 assertTrue("MULTIPLE_PATTERNS default", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4666
4667 // Set calendar to strict
4668 fmt->setCalendarLenient(FALSE);
4669
4670 assertFalse("isLeninent after setCalendarLenient(FALSE)", fmt->isLenient());
4671 assertFalse("isCalendarLenient after setCalendarLenient(FALSE)", fmt->isCalendarLenient());
4672 assertTrue("ALLOW_WHITESPACE after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4673 assertTrue("ALLOW_NUMERIC after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4674
4675 // Set to strict
4676 fmt->setLenient(FALSE);
4677
4678 assertFalse("isLeninent after setLenient(FALSE)", fmt->isLenient());
4679 assertFalse("isCalendarLenient after setLenient(FALSE)", fmt->isCalendarLenient());
4680 assertFalse("ALLOW_WHITESPACE after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4681 assertFalse("ALLOW_NUMERIC after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4682 // These two boolean attributes are NOT affected according to the API specification
4683 assertTrue("PARTIAL_MATCH after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4684 assertTrue("MULTIPLE_PATTERNS after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4685
4686 // Allow white space leniency
4687 fmt->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, TRUE, status);
4688
4689 assertFalse("isLeninent after ALLOW_WHITESPACE/TRUE", fmt->isLenient());
4690 assertFalse("isCalendarLenient after ALLOW_WHITESPACE/TRUE", fmt->isCalendarLenient());
4691 assertTrue("ALLOW_WHITESPACE after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4692 assertFalse("ALLOW_NUMERIC after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4693
4694 // Set to lenient
4695 fmt->setLenient(TRUE);
4696
4697 assertTrue("isLenient after setLenient(TRUE)", fmt->isLenient());
4698 assertTrue("isCalendarLenient after setLenient(TRUE)", fmt->isCalendarLenient());
4699 assertTrue("ALLOW_WHITESPACE after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4700 assertTrue("ALLOW_NUMERIC after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4701 }
4702
TestNumberFormatOverride()4703 void DateFormatTest::TestNumberFormatOverride() {
4704 UErrorCode status = U_ZERO_ERROR;
4705 UnicodeString fields = (UnicodeString) "M";
4706
4707 LocalPointer<SimpleDateFormat> fmt;
4708 fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4709 if (!assertSuccess("SimpleDateFormat with pattern MM d", status)) {
4710 return;
4711 }
4712
4713
4714 for(int i=0; i<3; i++){
4715 NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4716 assertSuccess("NumberFormat en_US", status);
4717 fmt->adoptNumberFormat(fields, check_nf, status);
4718 assertSuccess("adoptNumberFormat check_nf", status);
4719
4720 const NumberFormat* get_nf = fmt->getNumberFormatForField((UChar)0x004D /*'M'*/);
4721 if (get_nf != check_nf) errln("FAIL: getter and setter do not work");
4722 }
4723 NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4724 assertSuccess("NumberFormat en_US", status);
4725 fmt->adoptNumberFormat(check_nf); // make sure using the same NF will not crash
4726
4727 const char * DATA [][2] = {
4728 { "", "\\u521D\\u516D \\u5341\\u4E94"},
4729 { "M", "\\u521D\\u516D 15"},
4730 { "Mo", "\\u521D\\u516D 15"},
4731 { "Md", "\\u521D\\u516D \\u5341\\u4E94"},
4732 { "MdMMd", "\\u521D\\u516D \\u5341\\u4E94"},
4733 { "mixed", "\\u521D\\u516D \\u5341\\u4E94"}
4734 };
4735
4736 UDate test_date = date(97, 6 - 1, 15);
4737
4738 for(int i=0; i < UPRV_LENGTHOF(DATA); i++){
4739 fields = DATA[i][0];
4740
4741 LocalPointer<SimpleDateFormat> fmt;
4742 fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4743 assertSuccess("SimpleDateFormat with pattern MM d", status);
4744 NumberFormat* overrideNF = NumberFormat::createInstance(Locale::createFromName("zh@numbers=hanidays"),status);
4745 assertSuccess("NumberFormat zh@numbers=hanidays", status);
4746 if (U_FAILURE(status)) {
4747 status = U_ZERO_ERROR;
4748 continue;
4749 }
4750
4751 if (fields == (UnicodeString) "") { // use the one w/o fields
4752 fmt->adoptNumberFormat(overrideNF);
4753 } else if (fields == (UnicodeString) "mixed") { // set 1 field at first but then full override, both(M & d) should be override
4754 NumberFormat* singleOverrideNF = NumberFormat::createInstance(Locale::createFromName("en@numbers=hebr"),status);
4755 assertSuccess("NumberFormat en@numbers=hebr", status);
4756
4757 fields = (UnicodeString) "M";
4758 fmt->adoptNumberFormat(fields, singleOverrideNF, status);
4759 assertSuccess("adoptNumberFormat singleOverrideNF", status);
4760
4761 fmt->adoptNumberFormat(overrideNF);
4762 } else if (fields == (UnicodeString) "Mo"){ // o is invlid field
4763 fmt->adoptNumberFormat(fields, overrideNF, status);
4764 if(status == U_INVALID_FORMAT_ERROR) {
4765 status = U_ZERO_ERROR;
4766 continue;
4767 }
4768 } else {
4769 fmt->adoptNumberFormat(fields, overrideNF, status);
4770 assertSuccess("adoptNumberFormat overrideNF", status);
4771 }
4772
4773 UnicodeString result;
4774 FieldPosition pos(FieldPosition::DONT_CARE);
4775 fmt->format(test_date,result, pos);
4776
4777 UnicodeString expected = ((UnicodeString)DATA[i][1]).unescape();
4778
4779 if (result != expected)
4780 errln("FAIL: Expected " + expected + " get: " + result);
4781 }
4782 }
4783
TestCreateInstanceForSkeleton()4784 void DateFormatTest::TestCreateInstanceForSkeleton() {
4785 UErrorCode status = U_ZERO_ERROR;
4786 LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4787 "yMMMMd", "en", status));
4788 if (!assertSuccess("Create with pattern yMMMMd", status)) {
4789 return;
4790 }
4791 UnicodeString result;
4792 FieldPosition pos(FieldPosition::DONT_CARE);
4793 fmt->format(date(98, 5-1, 25), result, pos);
4794 assertEquals("format yMMMMd", "May 25, 1998", result);
4795 fmt.adoptInstead(DateFormat::createInstanceForSkeleton(
4796 "yMd", "en", status));
4797 if (!assertSuccess("Create with pattern yMd", status)) {
4798 return;
4799 }
4800 result.remove();
4801 fmt->format(date(98, 5-1, 25), result, pos);
4802 assertEquals("format yMd", "5/25/1998", result);
4803 }
4804
TestCreateInstanceForSkeletonDefault()4805 void DateFormatTest::TestCreateInstanceForSkeletonDefault() {
4806 UErrorCode status = U_ZERO_ERROR;
4807 Locale savedLocale;
4808 Locale::setDefault(Locale::getUS(), status);
4809 LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4810 "yMMMd", status));
4811 Locale::setDefault(savedLocale, status);
4812 if (!assertSuccess("Create with pattern yMMMd", status)) {
4813 return;
4814 }
4815 UnicodeString result;
4816 FieldPosition pos(FieldPosition::DONT_CARE);
4817 fmt->format(date(98, 5-1, 25), result, pos);
4818 assertEquals("format yMMMd", "May 25, 1998", result);
4819 }
4820
TestCreateInstanceForSkeletonWithCalendar()4821 void DateFormatTest::TestCreateInstanceForSkeletonWithCalendar() {
4822 UErrorCode status = U_ZERO_ERROR;
4823 LocalPointer<DateFormat> fmt(
4824 DateFormat::createInstanceForSkeleton(
4825 Calendar::createInstance(
4826 TimeZone::createTimeZone("GMT-3:00"),
4827 status),
4828 "yMdHm", "en", status));
4829 if (!assertSuccess("Create with pattern yMMMMd", status)) {
4830 return;
4831 }
4832 UnicodeString result;
4833 FieldPosition pos(FieldPosition::DONT_CARE);
4834
4835 LocalPointer<Calendar> cal(Calendar::createInstance(
4836 TimeZone::createTimeZone("GMT-7:00"),
4837 status));
4838 if (!assertSuccess("Creating GMT-7 time zone failed", status)) {
4839 return;
4840 }
4841 cal->clear();
4842 cal->set(1998, 5-1, 25, 0, 0, 0);
4843
4844 // date format time zone should be 4 hours ahead.
4845 fmt->format(cal->getTime(status), result, pos);
4846 assertEquals("format yMdHm", "5/25/1998, 04:00", result);
4847 assertSuccess("", status);
4848 }
4849
TestDFSCreateForLocaleNonGregorianLocale()4850 void DateFormatTest::TestDFSCreateForLocaleNonGregorianLocale() {
4851 UErrorCode status = U_ZERO_ERROR;
4852 Locale fa("fa");
4853 LocalPointer<DateFormatSymbols> sym(
4854 DateFormatSymbols::createForLocale(fa, status));
4855 if (!assertSuccess("", status)) {
4856 return;
4857 }
4858
4859 // Farsi should default to the persian calendar, not gregorian
4860 int32_t count;
4861 const UnicodeString *months = sym->getShortMonths(count);
4862
4863 // First persian month.
4864 UnicodeString expected("\\u0641\\u0631\\u0648\\u0631\\u062f\\u06cc\\u0646");
4865 assertEquals("", expected.unescape(), months[0]);
4866 }
4867
TestDFSCreateForLocaleWithCalendarInLocale()4868 void DateFormatTest::TestDFSCreateForLocaleWithCalendarInLocale() {
4869 UErrorCode status = U_ZERO_ERROR;
4870 Locale en_heb("en@calendar=hebrew");
4871 LocalPointer<DateFormatSymbols> sym(
4872 DateFormatSymbols::createForLocale(en_heb, status));
4873 if (!assertSuccess("", status)) {
4874 return;
4875 }
4876
4877 // We should get the months of the hebrew calendar, not the gregorian
4878 // calendar.
4879 int32_t count;
4880 const UnicodeString *months = sym->getShortMonths(count);
4881
4882 // First hebrew month.
4883 UnicodeString expected("Tishri");
4884 assertEquals("", expected, months[0]);
4885 }
4886
TestChangeCalendar()4887 void DateFormatTest::TestChangeCalendar() {
4888 UErrorCode status = U_ZERO_ERROR;
4889 Locale en("en");
4890 Locale en_heb("en@calendar=hebrew");
4891 LocalPointer<DateFormat> fmt(
4892 DateFormat::createInstanceForSkeleton("yMMMd", en, status));
4893 if (!assertSuccess("", status)) {
4894 return;
4895 }
4896 fmt->adoptCalendar(Calendar::createInstance(en_heb, status));
4897 if (!assertSuccess("", status)) {
4898 return;
4899 }
4900 UnicodeString result;
4901 FieldPosition pos(FieldPosition::DONT_CARE);
4902 fmt->format(date(98, 5-1, 25), result, pos);
4903 assertEquals("format yMMMd", "Iyar 29, 5758", result);
4904 }
4905
TestPatternFromSkeleton()4906 void DateFormatTest::TestPatternFromSkeleton() {
4907 static const struct {
4908 const Locale& locale;
4909 const char* const skeleton;
4910 const char* const pattern;
4911 } TESTDATA[] = {
4912 // Ticket #11985
4913 {Locale::getEnglish(), "jjmm", "h:mm a"},
4914 {Locale::getEnglish(), "JJmm", "hh:mm"},
4915 {Locale::getGerman(), "jjmm", "HH:mm"},
4916 {Locale::getGerman(), "JJmm", "HH:mm"},
4917 // Ticket #20739
4918 // minutes+milliseconds, seconds missing, should be repaired
4919 {Locale::getEnglish(), "SSSSm", "mm:ss.SSSS"},
4920 {Locale::getEnglish(), "mSSSS", "mm:ss.SSSS"},
4921 {Locale::getEnglish(), "SSSm", "mm:ss.SSS"},
4922 {Locale::getEnglish(), "mSSS", "mm:ss.SSS"},
4923 {Locale::getEnglish(), "SSm", "mm:ss.SS"},
4924 {Locale::getEnglish(), "mSS", "mm:ss.SS"},
4925 {Locale::getEnglish(), "Sm", "mm:ss.S"},
4926 {Locale::getEnglish(), "mS", "mm:ss.S"},
4927 // only milliseconds, untouched, no repairs
4928 {Locale::getEnglish(), "S", "S"},
4929 {Locale::getEnglish(), "SS", "SS"},
4930 {Locale::getEnglish(), "SSS", "SSS"},
4931 {Locale::getEnglish(), "SSSS", "SSSS"},
4932 // hour:minute+seconds+milliseconds, correct, no repairs, proper pattern
4933 {Locale::getEnglish(), "jmsSSS", "h:mm:ss.SSS a"},
4934 {Locale::getEnglish(), "jmSSS", "h:mm:ss.SSS a"},
4935 // Ticket #20738
4936 // seconds+milliseconds, correct, no repairs, proper pattern
4937 {Locale::getEnglish(), "sS", "s.S"},
4938 {Locale::getEnglish(), "sSS", "s.SS"},
4939 {Locale::getEnglish(), "sSSS", "s.SSS"},
4940 {Locale::getEnglish(), "sSSSS", "s.SSSS"},
4941 {Locale::getEnglish(), "sS", "s.S"},
4942 // minutes+seconds+milliseconds, correct, no repairs, proper pattern
4943 {Locale::getEnglish(), "msS", "mm:ss.S"},
4944 {Locale::getEnglish(), "msSS", "mm:ss.SS"},
4945 {Locale::getEnglish(), "msSSS", "mm:ss.SSS"},
4946 {Locale::getEnglish(), "msSSSS", "mm:ss.SSSS"}
4947 };
4948
4949 for (size_t i = 0; i < UPRV_LENGTHOF(TESTDATA); i++) {
4950 UErrorCode status = U_ZERO_ERROR;
4951 LocalPointer<DateFormat> fmt(
4952 DateFormat::createInstanceForSkeleton(
4953 TESTDATA[i].skeleton, TESTDATA[i].locale, status));
4954 if (!assertSuccess("createInstanceForSkeleton", status)) {
4955 return;
4956 }
4957 UnicodeString pattern;
4958 static_cast<const SimpleDateFormat*>(fmt.getAlias())->toPattern(pattern);
4959 assertEquals("Format pattern", TESTDATA[i].pattern, pattern);
4960 }
4961 }
4962
TestAmPmMidnightNoon()4963 void DateFormatTest::TestAmPmMidnightNoon() {
4964 // Some times on 2015-11-13 (UTC+0).
4965 UDate k000000 = 1447372800000.0;
4966 UDate k000030 = 1447372830000.0;
4967 UDate k003000 = 1447374600000.0;
4968 UDate k060000 = 1447394400000.0;
4969 UDate k120000 = 1447416000000.0;
4970 UDate k180000 = 1447437600000.0;
4971
4972 UErrorCode errorCode = U_ZERO_ERROR;
4973 SimpleDateFormat sdf(UnicodeString(), errorCode);
4974 if (U_FAILURE(errorCode)) {
4975 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
4976 return;
4977 }
4978 const TimeZone *tz = TimeZone::getGMT();
4979 sdf.setTimeZone(*tz);
4980 UnicodeString out;
4981
4982 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
4983 // For ICU 57 output of "midnight" is temporarily suppressed.
4984
4985 // Short.
4986 sdf.applyPattern(UnicodeString("hh:mm:ss bbb"));
4987
4988 // assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4989 assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4990 assertEquals("hh:mm:ss bbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
4991 assertEquals("hh:mm:ss bbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
4992 assertEquals("hh:mm:ss bbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
4993 assertEquals("hh:mm:ss bbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
4994 assertEquals("hh:mm:ss bbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
4995
4996 sdf.applyPattern(UnicodeString("hh:mm bbb"));
4997
4998 // assertEquals("hh:mm bbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
4999 assertEquals("hh:mm bbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
5000 // assertEquals("hh:mm bbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5001 assertEquals("hh:mm bbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
5002 assertEquals("hh:mm bbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
5003
5004 sdf.applyPattern(UnicodeString("hh bbb"));
5005
5006 // assertEquals("hh bbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5007 assertEquals("hh bbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
5008 // assertEquals("hh bbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5009 assertEquals("hh bbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
5010 // assertEquals("hh bbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5011 assertEquals("hh bbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
5012
5013 // Wide.
5014 sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
5015
5016 // assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5017 assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
5018 assertEquals("hh:mm:ss bbbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
5019 assertEquals("hh:mm:ss bbbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
5020 assertEquals("hh:mm:ss bbbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
5021 assertEquals("hh:mm:ss bbbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5022 assertEquals("hh:mm:ss bbbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
5023
5024 sdf.applyPattern(UnicodeString("hh:mm bbbb"));
5025
5026 // assertEquals("hh:mm bbbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5027 assertEquals("hh:mm bbbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
5028 // assertEquals("hh:mm bbbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5029 assertEquals("hh:mm bbbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
5030 assertEquals("hh:mm bbbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
5031
5032 sdf.applyPattern(UnicodeString("hh bbbb"));
5033
5034 // assertEquals("hh bbbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5035 assertEquals("hh bbbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
5036 // assertEquals("hh bbbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5037 assertEquals("hh bbbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
5038 // assertEquals("hh bbbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5039 assertEquals("hh bbbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
5040
5041 // Narrow.
5042 sdf.applyPattern(UnicodeString("hh:mm:ss bbbbb"));
5043
5044 // assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5045 assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 a", sdf.format(k000000, out.remove()));
5046 assertEquals("hh:mm:ss bbbbb | 00:00:30", "12:00:30 a", sdf.format(k000030, out.remove()));
5047 assertEquals("hh:mm:ss bbbbb | 00:30:00", "12:30:00 a", sdf.format(k003000, out.remove()));
5048 assertEquals("hh:mm:ss bbbbb | 06:00:00", "06:00:00 a", sdf.format(k060000, out.remove()));
5049 assertEquals("hh:mm:ss bbbbb | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5050 assertEquals("hh:mm:ss bbbbb | 18:00:00", "06:00:00 p", sdf.format(k180000, out.remove()));
5051
5052 sdf.applyPattern(UnicodeString("hh:mm bbbbb"));
5053
5054 // assertEquals("hh:mm bbbbb | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5055 assertEquals("hh:mm bbbbb | 00:00:00", "12:00 a", sdf.format(k000000, out.remove()));
5056 // assertEquals("hh:mm bbbbb | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5057 assertEquals("hh:mm bbbbb | 00:00:30", "12:00 a", sdf.format(k000030, out.remove()));
5058 assertEquals("hh:mm bbbbb | 00:30:00", "12:30 a", sdf.format(k003000, out.remove()));
5059
5060 sdf.applyPattern(UnicodeString("hh bbbbb"));
5061
5062 // assertEquals("hh bbbbb | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5063 assertEquals("hh bbbbb | 00:00:00", "12 a", sdf.format(k000000, out.remove()));
5064 // assertEquals("hh bbbbb | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5065 assertEquals("hh bbbbb | 00:00:30", "12 a", sdf.format(k000030, out.remove()));
5066 // assertEquals("hh bbbbb | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5067 assertEquals("hh bbbbb | 00:30:00", "12 a", sdf.format(k003000, out.remove()));
5068 }
5069
TestFlexibleDayPeriod()5070 void DateFormatTest::TestFlexibleDayPeriod() {
5071 // Some times on 2015-11-13 (UTC+0).
5072 UDate k000000 = 1447372800000.0;
5073 UDate k000030 = 1447372830000.0;
5074 UDate k003000 = 1447374600000.0;
5075 UDate k060000 = 1447394400000.0;
5076 UDate k120000 = 1447416000000.0;
5077 UDate k180000 = 1447437600000.0;
5078
5079 UErrorCode errorCode = U_ZERO_ERROR;
5080 SimpleDateFormat sdf(UnicodeString(), errorCode);
5081 if (U_FAILURE(errorCode)) {
5082 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5083 return;
5084 }
5085 const TimeZone *tz = TimeZone::getGMT();
5086 sdf.setTimeZone(*tz);
5087 UnicodeString out;
5088
5089 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5090 // For ICU 57 output of "midnight" is temporarily suppressed.
5091
5092 // Short.
5093 sdf.applyPattern(UnicodeString("hh:mm:ss BBB"));
5094
5095 // assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5096 assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5097 assertEquals("hh:mm:ss BBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5098 assertEquals("hh:mm:ss BBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5099 assertEquals("hh:mm:ss BBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5100 assertEquals("hh:mm:ss BBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5101 assertEquals("hh:mm:ss BBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5102
5103 sdf.applyPattern(UnicodeString("hh:mm BBB"));
5104
5105 // assertEquals("hh:mm BBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5106 assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5107 // assertEquals("hh:mm BBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5108 assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5109 assertEquals("hh:mm BBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5110
5111 sdf.applyPattern(UnicodeString("hh BBB"));
5112
5113 // assertEquals("hh BBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5114 assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5115 // assertEquals("hh BBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5116 assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5117 // assertEquals("hh BBB | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5118 assertEquals("hh BBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5119
5120 // Wide.
5121 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5122
5123 // assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5124 assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5125 assertEquals("hh:mm:ss BBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5126 assertEquals("hh:mm:ss BBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5127 assertEquals("hh:mm:ss BBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5128 assertEquals("hh:mm:ss BBBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5129 assertEquals("hh:mm:ss BBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5130
5131 sdf.applyPattern(UnicodeString("hh:mm BBBB"));
5132
5133 // assertEquals("hh:mm BBBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5134 assertEquals("hh:mm BBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5135 // assertEquals("hh:mm BBBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5136 assertEquals("hh:mm BBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5137 assertEquals("hh:mm BBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5138
5139 sdf.applyPattern(UnicodeString("hh BBBB"));
5140
5141 // assertEquals("hh BBBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5142 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5143 // assertEquals("hh BBBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5144 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5145 // assertEquals("hh BBBB | 00:80:00", "12 midnight", sdf.format(k003000, out.remove()));
5146 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5147
5148 // Narrow.
5149 sdf.applyPattern(UnicodeString("hh:mm:ss BBBBB"));
5150
5151 // assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5152 assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5153 assertEquals("hh:mm:ss BBBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5154 assertEquals("hh:mm:ss BBBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5155 assertEquals("hh:mm:ss BBBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5156 assertEquals("hh:mm:ss BBBBB | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5157 assertEquals("hh:mm:ss BBBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5158
5159 sdf.applyPattern(UnicodeString("hh:mm BBBBB"));
5160
5161 // assertEquals("hh:mm BBBBB | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5162 assertEquals("hh:mm BBBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5163 // assertEquals("hh:mm BBBBB | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5164 assertEquals("hh:mm BBBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5165 assertEquals("hh:mm BBBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5166
5167 sdf.applyPattern(UnicodeString("hh BBBBB"));
5168
5169 // assertEquals("hh BBBBB | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5170 assertEquals("hh BBBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5171 // assertEquals("hh BBBBB | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5172 assertEquals("hh BBBBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5173 // assertEquals("hh BBBBB | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5174 assertEquals("hh BBBBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5175 }
5176
TestDayPeriodWithLocales()5177 void DateFormatTest::TestDayPeriodWithLocales() {
5178 // Some times on 2015-11-13 (UTC+0).
5179 UDate k000000 = 1447372800000.0;
5180 UDate k010000 = 1447376400000.0;
5181 UDate k120000 = 1447416000000.0;
5182 UDate k220000 = 1447452000000.0;
5183
5184 UErrorCode errorCode = U_ZERO_ERROR;
5185 const TimeZone *tz = TimeZone::getGMT();
5186 UnicodeString out;
5187
5188 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5189 // For ICU 57 output of "midnight" and its localized equivalentns is temporarily suppressed.
5190
5191 // Locale de has a word for midnight, but not noon.
5192 SimpleDateFormat sdf(UnicodeString(), Locale::getGermany(), errorCode);
5193 if (U_FAILURE(errorCode)) {
5194 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5195 return;
5196 }
5197 sdf.setTimeZone(*tz);
5198
5199 sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
5200
5201 // assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 Mitternacht",
5202 // sdf.format(k000000, out.remove()));
5203 assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 AM",
5204 sdf.format(k000000, out.remove()));
5205 assertEquals("hh:mm:ss bbbb | 12:00:00 | de", "12:00:00 PM",
5206 sdf.format(k120000, out.remove()));
5207
5208 // Locale ee has a rule that wraps around midnight (21h - 4h).
5209 sdf = SimpleDateFormat(UnicodeString(), Locale("ee"), errorCode);
5210 sdf.setTimeZone(*tz);
5211
5212 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5213
5214 assertEquals("hh:mm:ss BBBB | 22:00:00 | ee", UnicodeString("10:00:00 z\\u00E3").unescape(),
5215 sdf.format(k220000, out.remove()));
5216 assertEquals("hh:mm:ss BBBB | 00:00:00 | ee", UnicodeString("12:00:00 z\\u00E3").unescape(),
5217 sdf.format(k000000, out.remove()));
5218 assertEquals("hh:mm:ss BBBB | 01:00:00 | ee", UnicodeString("01:00:00 z\\u00E3").unescape(),
5219 sdf.format(k010000, out.remove()));
5220
5221 // Locale root has rules for AM/PM only.
5222 sdf = SimpleDateFormat(UnicodeString(), Locale("root"), errorCode);
5223 sdf.setTimeZone(*tz);
5224
5225 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5226
5227 assertEquals("hh:mm:ss BBBB | 00:00:00 | root", "12:00:00 AM",
5228 sdf.format(k000000, out.remove()));
5229 assertEquals("hh:mm:ss BBBB | 12:00:00 | root", "12:00:00 PM",
5230 sdf.format(k120000, out.remove()));
5231
5232 // Empty string should behave exactly as root.
5233 sdf = SimpleDateFormat(UnicodeString(), Locale(""), errorCode);
5234 sdf.setTimeZone(*tz);
5235
5236 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5237
5238 assertEquals("hh:mm:ss BBBB | 00:00:00 | \"\" (root)", "12:00:00 AM",
5239 sdf.format(k000000, out.remove()));
5240 assertEquals("hh:mm:ss BBBB | 12:00:00 | \"\" (root)", "12:00:00 PM",
5241 sdf.format(k120000, out.remove()));
5242
5243 // Locale en_US should fall back to en.
5244 sdf = SimpleDateFormat(UnicodeString(), Locale("en_US"), errorCode);
5245 sdf.setTimeZone(*tz);
5246
5247 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5248
5249 // assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 midnight",
5250 // sdf.format(k000000, out.remove()));
5251 assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 at night",
5252 sdf.format(k000000, out.remove()));
5253 assertEquals("hh:mm:ss BBBB | 01:00:00 | en_US", "01:00:00 at night",
5254 sdf.format(k010000, out.remove()));
5255 assertEquals("hh:mm:ss BBBB | 12:00:00 | en_US", "12:00:00 noon",
5256 sdf.format(k120000, out.remove()));
5257
5258 // Locale es_CO should not fall back to es and should have a
5259 // different string for 1 in the morning.
5260 // (es_CO: "de la manana" (first n has a tilde) vs. es: "de la madrugada")
5261 sdf = SimpleDateFormat(UnicodeString(), Locale("es_CO"), errorCode);
5262 sdf.setTimeZone(*tz);
5263
5264 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5265 assertEquals("hh:mm:ss BBBB | 01:00:00 | es_CO", u"01:00:00 de la mañana",
5266 sdf.format(k010000, out.remove()));
5267
5268 sdf = SimpleDateFormat(UnicodeString(), Locale("es"), errorCode);
5269 sdf.setTimeZone(*tz);
5270
5271 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5272 assertEquals("hh:mm:ss BBBB | 01:00:00 | es", "01:00:00 de la madrugada",
5273 sdf.format(k010000, out.remove()));
5274
5275 // #13215: for locales with keywords, check hang in DayPeriodRules""getInstance(const Locale, ...),
5276 // which is called in SimpleDateFormat::format for patterns that include 'B'.
5277 sdf = SimpleDateFormat(UnicodeString(), Locale("en@calendar=buddhist"), errorCode);
5278 sdf.setTimeZone(*tz);
5279
5280 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5281 assertEquals("hh:mm:ss BBBB | 01:00:00 | en@calendar=buddhist", "01:00:00 at night",
5282 sdf.format(k010000, out.remove()));
5283 }
5284
TestMinuteSecondFieldsInOddPlaces()5285 void DateFormatTest::TestMinuteSecondFieldsInOddPlaces() {
5286 // Some times on 2015-11-13 (UTC+0).
5287 UDate k000000 = 1447372800000.0;
5288 UDate k000030 = 1447372830000.0;
5289 UDate k003000 = 1447374600000.0;
5290 UDate k060030 = 1447394430000.0;
5291 UDate k063000 = 1447396200000.0;
5292
5293 UErrorCode errorCode = U_ZERO_ERROR;
5294 const TimeZone *tz = TimeZone::getGMT();
5295 UnicodeString out;
5296
5297 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5298 // For ICU 57 output of "midnight" is temporarily suppressed.
5299
5300 // Seconds field is not present.
5301
5302 // Apply pattern through constructor to make sure parsePattern() is called during initialization.
5303 SimpleDateFormat sdf(UnicodeString("hh:mm 'ss' bbbb"), errorCode);
5304 if (U_FAILURE(errorCode)) {
5305 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5306 return;
5307 }
5308 sdf.setTimeZone(*tz);
5309
5310 // assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss midnight",
5311 // sdf.format(k000030, out.remove()));
5312 assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss AM",
5313 sdf.format(k000030, out.remove()));
5314 assertEquals("hh:mm 'ss' bbbb | 06:00:30", "06:00 ss AM",
5315 sdf.format(k060030, out.remove()));
5316
5317 sdf.applyPattern(UnicodeString("hh:mm 'ss' BBBB"));
5318
5319 // assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss midnight",
5320 // sdf.format(k000030, out.remove()));
5321 assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss at night",
5322 sdf.format(k000030, out.remove()));
5323 assertEquals("hh:mm 'ss' BBBB | 06:00:30", "06:00 ss in the morning",
5324 sdf.format(k060030, out.remove()));
5325
5326 // Minutes field is not present.
5327 sdf.applyPattern(UnicodeString("hh 'mm ss' bbbb"));
5328
5329 // assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss midnight",
5330 // sdf.format(k003000, out.remove()));
5331 assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss AM",
5332 sdf.format(k003000, out.remove()));
5333 assertEquals("hh 'mm ss' bbbb | 06:30:00", "06 mm ss AM",
5334 sdf.format(k063000, out.remove()));
5335
5336 sdf.applyPattern(UnicodeString("hh 'mm ss' BBBB"));
5337
5338 // assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss midnight",
5339 // sdf.format(k003000, out.remove()));
5340 assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss at night",
5341 sdf.format(k003000, out.remove()));
5342 assertEquals("hh 'mm ss' BBBB | 06:30:00", "06 mm ss in the morning",
5343 sdf.format(k063000, out.remove()));
5344
5345 // Minutes and seconds fields appear after day periods.
5346 sdf.applyPattern(UnicodeString("bbbb hh:mm:ss"));
5347
5348 // assertEquals("bbbb hh:mm:ss | 00:00:00", "midnight 12:00:00",
5349 // sdf.format(k000000, out.remove()));
5350 assertEquals("bbbb hh:mm:ss | 00:00:00", "AM 12:00:00",
5351 sdf.format(k000000, out.remove()));
5352 assertEquals("bbbb hh:mm:ss | 00:00:30", "AM 12:00:30",
5353 sdf.format(k000030, out.remove()));
5354 assertEquals("bbbb hh:mm:ss | 00:30:00", "AM 12:30:00",
5355 sdf.format(k003000, out.remove()));
5356
5357 sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5358
5359 // assertEquals("BBBB hh:mm:ss | 00:00:00", "midnight 12:00:00",
5360 // sdf.format(k000000, out.remove()));
5361 assertEquals("BBBB hh:mm:ss | 00:00:00", "at night 12:00:00",
5362 sdf.format(k000000, out.remove()));
5363 assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5364 sdf.format(k000030, out.remove()));
5365 assertEquals("BBBB hh:mm:ss | 00:30:00", "at night 12:30:00",
5366 sdf.format(k003000, out.remove()));
5367
5368 // Confirm applyPattern() reparses the pattern string.
5369 sdf.applyPattern(UnicodeString("BBBB hh"));
5370 // assertEquals("BBBB hh | 00:00:30", "midnight 12",
5371 // sdf.format(k000030, out.remove()));
5372 assertEquals("BBBB hh | 00:00:30", "at night 12",
5373 sdf.format(k000030, out.remove()));
5374
5375 sdf.applyPattern(UnicodeString("BBBB hh:mm:'ss'"));
5376 // assertEquals("BBBB hh:mm:'ss' | 00:00:30", "midnight 12:00:ss",
5377 // sdf.format(k000030, out.remove()));
5378 assertEquals("BBBB hh | 00:00:30", "at night 12:00:ss",
5379 sdf.format(k000030, out.remove()));
5380
5381 sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5382 assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5383 sdf.format(k000030, out.remove()));
5384 }
5385
TestDayPeriodParsing()5386 void DateFormatTest::TestDayPeriodParsing() {
5387 // Some times on 2015-11-13 (UTC+0).
5388 UDate k000000 = 1447372800000.0;
5389 UDate k003700 = 1447375020000.0;
5390 UDate k010000 = 1447376400000.0;
5391 UDate k013000 = 1447378200000.0;
5392 UDate k030000 = 1447383600000.0;
5393 UDate k090000 = 1447405200000.0;
5394 UDate k120000 = 1447416000000.0;
5395 UDate k130000 = 1447419600000.0;
5396 UDate k133700 = 1447421820000.0;
5397 UDate k150000 = 1447426800000.0;
5398 UDate k190000 = 1447441200000.0;
5399 UDate k193000 = 1447443000000.0;
5400 UDate k200000 = 1447444800000.0;
5401 UDate k210000 = 1447448400000.0;
5402
5403 UErrorCode errorCode = U_ZERO_ERROR;
5404 SimpleDateFormat sdf(UnicodeString(), errorCode);
5405 if (U_FAILURE(errorCode)) {
5406 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5407 return;
5408 }
5409 const TimeZone *tz = TimeZone::getGMT();
5410 sdf.setTimeZone(*tz);
5411 UnicodeString out;
5412
5413 // 'B' -- flexible day periods
5414 // A day period on its own parses to the center of that period.
5415 sdf.applyPattern(UnicodeString("yyyy-MM-dd B"));
5416 assertEquals("yyyy-MM-dd B | 2015-11-13 midnight",
5417 k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5418 assertEquals("yyyy-MM-dd B | 2015-11-13 noon",
5419 k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5420 assertEquals("yyyy-MM-dd B | 2015-11-13 in the afternoon",
5421 k150000, sdf.parse(UnicodeString("2015-11-13 in the afternoon"), errorCode));
5422 assertEquals("yyyy-MM-dd B | 2015-11-13 in the evening",
5423 k193000, sdf.parse(UnicodeString("2015-11-13 in the evening"), errorCode));
5424 assertEquals("yyyy-MM-dd B | 2015-11-13 at night",
5425 k013000, sdf.parse(UnicodeString("2015-11-13 at night"), errorCode));
5426
5427 // If time and day period are consistent with each other then time is parsed accordingly.
5428 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5429 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 midnight",
5430 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5431 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 noon",
5432 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5433 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 at night",
5434 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5435 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 in the afternoon",
5436 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5437 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 in the morning",
5438 k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5439 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 at night",
5440 k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5441
5442 // If the hour is 13 thru 23 then day period has no effect on time (since time is assumed
5443 // to be in 24-hour format).
5444 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5445 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 midnight",
5446 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5447 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 noon",
5448 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5449 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5450 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5451 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the afternoon",
5452 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the afternoon"), errorCode));
5453 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the morning",
5454 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the morning"), errorCode));
5455 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5456 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5457
5458 // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5459 // This unfortunately means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5460 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5461 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 midnight",
5462 k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5463 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 noon",
5464 k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5465
5466 // But when parsed with 'H', 0 indicates a 24-hour time, therefore we disregard the day period.
5467 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5468 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 midnight",
5469 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5470 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 noon",
5471 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5472 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5473 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5474 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the afternoon",
5475 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the afternoon"), errorCode));
5476 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the morning",
5477 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the morning"), errorCode));
5478 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5479 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5480
5481 // Even when parsed with 'H', hours 1 thru 12 are considered 12-hour time and takes
5482 // day period into account in parsing.
5483 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5484 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 midnight",
5485 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5486 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 noon",
5487 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5488 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 at night",
5489 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5490 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 in the afternoon",
5491 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5492 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 in the morning",
5493 k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5494 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 at night",
5495 k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5496
5497 // If a 12-hour time and the day period don't agree with each other, time is parsed as close
5498 // to the given day period as possible.
5499 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5500
5501 // AFTERNOON1 is [12, 18), but "7 in the afternoon" parses to 19:00.
5502 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 07:00 in the afternoon",
5503 k190000, sdf.parse(UnicodeString("2015-11-13 07:00 in the afternoon"), errorCode));
5504 // NIGHT1 is [21, 6), but "8 at night" parses to 20:00.
5505 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 08:00 at night",
5506 k200000, sdf.parse(UnicodeString("2015-11-13 08:00 at night"), errorCode));
5507
5508 // 'b' -- fixed day periods (AM, PM, midnight, noon)
5509 // On their own, "midnight" parses to 00:00 and "noon" parses to 12:00.
5510 // AM and PM are handled by the 'a' parser (which doesn't handle this case well).
5511 sdf.applyPattern(UnicodeString("yyyy-MM-dd b"));
5512 assertEquals("yyyy-MM-dd b | 2015-11-13 midnight",
5513 k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5514 assertEquals("yyyy-MM-dd b | 2015-11-13 noon",
5515 k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5516
5517 // For 12-hour times, AM and PM should be parsed as if with pattern character 'a'.
5518 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5519 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 AM",
5520 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 AM"), errorCode));
5521 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 PM",
5522 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 PM"), errorCode));
5523
5524 // 12 midnight parses to 00:00, and 12 noon parses to 12:00.
5525 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 midnight",
5526 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5527 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 noon",
5528 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5529
5530 // Hours 13-23 indicate 24-hour time so we disregard "midnight" or "noon".
5531 // Again, AM and PM are handled by the 'a' parser which doesn't handle this case well.
5532 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5533 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 midnight",
5534 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5535 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 noon",
5536 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5537
5538 // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5539 // Again, this means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5540 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5541 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 midnight",
5542 k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5543 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 noon",
5544 k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5545
5546 // With 'H' though 0 indicates a 24-hour time, therefore we disregard the day period.
5547 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5548 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 midnight",
5549 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5550 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 noon",
5551 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5552
5553 // If "midnight" or "noon" is parsed with a 12-hour time other than 12:00, choose
5554 // the version that's closer to the period given.
5555 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5556 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 midnight",
5557 k030000, sdf.parse(UnicodeString("2015-11-13 03:00 midnight"), errorCode));
5558 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 noon",
5559 k150000, sdf.parse(UnicodeString("2015-11-13 03:00 noon"), errorCode));
5560 }
5561
TestParseRegression13744()5562 void DateFormatTest::TestParseRegression13744() {
5563 LocalPointer<DateFormat> dfmt(DateFormat::createDateTimeInstance(
5564 DateFormat::SHORT, DateFormat::SHORT, Locale("en", "US")));
5565 if (dfmt.isNull()) {
5566 dataerrln("DateFormat::createDateTimeInstance() failed");
5567 return;
5568 }
5569 ParsePosition pos(0);
5570 UnicodeString inDate("4/27/18");
5571 dfmt->parse(inDate, pos);
5572 assertEquals("Error index", inDate.length(), pos.getErrorIndex());
5573 }
5574
TestAdoptCalendarLeak()5575 void DateFormatTest::TestAdoptCalendarLeak() {
5576 UErrorCode status = U_ZERO_ERROR;
5577 // This test relies on the locale fullName exceeding ULOC_FULLNAME_CAPACITY
5578 // in order for setKeywordValue to fail.
5579 SimpleDateFormat sdf(
5580 "d.M.y",
5581 Locale("de__POSIX@colstrength=primary;currency=eur;em=default;"
5582 "hours=h23;lb=strict;lw=normal;measure=metric;numbers=latn;"
5583 "rg=atzzzz;sd=atat1;ss=none;timezone=Europe/Vienna"),
5584 status);
5585 ASSERT_OK(status);
5586 sdf.adoptCalendar(Calendar::createInstance(status));
5587 }
5588
5589 /**
5590 * Test that 'a' and 'B' fields are not duplicated in the field position iterator.
5591 */
Test20741_ABFields()5592 void DateFormatTest::Test20741_ABFields() {
5593 IcuTestErrorCode status(*this, "Test20741_ABFields");
5594
5595 const char16_t timeZone[] = u"PST8PDT";
5596
5597 UnicodeString skeletons[] = {u"EEEEEBBBBB", u"EEEEEbbbbb"};
5598
5599 for (int32_t j = 0; j < 2; j++) {
5600 UnicodeString skeleton = skeletons[j];
5601
5602 int32_t count = 0;
5603 const Locale* locales = Locale::getAvailableLocales(count);
5604 for (int32_t i = 0; i < count; i++) {
5605 if (quick && (i % 17) != 0) { continue; }
5606
5607 const Locale locale = locales[i];
5608 LocalPointer<DateTimePatternGenerator> gen(DateTimePatternGenerator::createInstance(locale, status));
5609 UnicodeString pattern = gen->getBestPattern(skeleton, status);
5610
5611 SimpleDateFormat dateFormat(pattern, locale, status);
5612 FieldPositionIterator fpositer;
5613 UnicodeString result;
5614 LocalPointer<Calendar> calendar(Calendar::createInstance(TimeZone::createTimeZone(timeZone), status));
5615 calendar->setTime(UDate(0), status);
5616 dateFormat.format(*calendar, result, &fpositer, status);
5617
5618 FieldPosition curFieldPosition;
5619 FieldPosition lastFieldPosition;
5620 lastFieldPosition.setBeginIndex(-1);
5621 lastFieldPosition.setEndIndex(-1);
5622 while(fpositer.next(curFieldPosition)) {
5623 assertFalse("Field missing on pattern", pattern.indexOf(PATTERN_CHARS[curFieldPosition.getField()]) == -1);
5624 if (curFieldPosition.getBeginIndex() == lastFieldPosition.getBeginIndex() && curFieldPosition.getEndIndex() == lastFieldPosition.getEndIndex()) {
5625 assertEquals("Different fields at same position", PATTERN_CHARS[curFieldPosition.getField()], PATTERN_CHARS[lastFieldPosition.getField()]);
5626 }
5627
5628 lastFieldPosition = curFieldPosition;
5629 }
5630 }
5631 }
5632 }
5633
5634 #endif /* #if !UCONFIG_NO_FORMATTING */
5635
5636 //eof
5637