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