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