]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/intltest/dtfmttst.cpp
ICU-59152.0.1.tar.gz
[apple/icu.git] / icuSources / test / intltest / dtfmttst.cpp
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 ********************************************************************/
8
9 #include "unicode/utypes.h"
10
11 #if !UCONFIG_NO_FORMATTING
12
13 #include "dtfmttst.h"
14 #include "unicode/localpointer.h"
15 #include "unicode/timezone.h"
16 #include "unicode/gregocal.h"
17 #include "unicode/smpdtfmt.h"
18 #include "unicode/datefmt.h"
19 #include "unicode/dtptngen.h"
20 #include "unicode/simpletz.h"
21 #include "unicode/strenum.h"
22 #include "unicode/dtfmtsym.h"
23 #include "cmemory.h"
24 #include "cstring.h"
25 #include "caltest.h" // for fieldName
26 #include <stdio.h> // for sprintf
27
28 #if U_PLATFORM_USES_ONLY_WIN32_API
29 #include "windttst.h"
30 #endif
31
32 #define ASSERT_OK(status) if(U_FAILURE(status)) {errcheckln(status, #status " = %s @ %s:%d", u_errorName(status), __FILE__, __LINE__); return; }
33
34 // *****************************************************************************
35 // class DateFormatTest
36 // *****************************************************************************
37
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
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.
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
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
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
419 UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
420
421 UnicodeString&
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 */
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 */
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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\\u00A0\\u0645", -1, US_INV).unescape();
1381
1382 const UnicodeString expectedLatn = UnicodeString(
1383 "9:52\\u00A0\\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 */
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 */
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 */
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 */
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
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
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
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
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
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
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
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
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 */
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 */
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 */
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
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
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
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
2375 void DateFormatTest::TestHost(void)
2376 {
2377 #if U_PLATFORM_USES_ONLY_WIN32_API
2378 Win32DateTimeTest::testLocales(this);
2379 #endif
2380 }
2381
2382 // Relative Date Tests
2383
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
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
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
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
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
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
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 if (fmt.isNull()) {
2608 dataerrln("FAIL: DateFormat::createDateInstance failed for %s", loc.getName());
2609 return;
2610 }
2611 Locale valid1;
2612 Locale actual1;
2613 if (!getActualAndValidLocales(*fmt, valid1, actual1)) {
2614 dataerrln("FAIL: Could not fetch valid + actual locales");
2615 return;
2616 }
2617 LocalPointer<Format> fmtClone(fmt->clone());
2618
2619 // Free fmt to be sure that fmtClone is really independent of fmt.
2620 fmt.adoptInstead(NULL);
2621 Locale valid2;
2622 Locale actual2;
2623 if (!getActualAndValidLocales(*fmtClone, valid2, actual2)) {
2624 errln("FAIL: Could not fetch valid + actual locales");
2625 return;
2626 }
2627 if (valid1 != valid2 || actual1 != actual2) {
2628 errln("Date format symbol locales of clone don't match original");
2629 }
2630 }
2631
2632 void DateFormatTest::TestTimeZoneDisplayName()
2633 {
2634 // This test data was ported from ICU4J. Don't know why the 6th column in there because it's not being
2635 // used currently.
2636 const char *fallbackTests[][6] = {
2637 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2638 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2639 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZZ", "-08:00", "-8:00" },
2640 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "PST", "America/Los_Angeles" },
2641 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Pacific Standard Time", "America/Los_Angeles" },
2642 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2643 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2644 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "PDT", "America/Los_Angeles" },
2645 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Pacific Daylight Time", "America/Los_Angeles" },
2646 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "PT", "America/Los_Angeles" },
2647 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Pacific Time", "America/Los_Angeles" },
2648 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "Los Angeles Time", "America/Los_Angeles" },
2649 { "en_GB", "America/Los_Angeles", "2004-01-15T12:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2650 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "Z", "-0700", "-7:00" },
2651 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2652 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2653 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2654 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2655 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2656 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2657 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2658 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "v", "MST", "America/Phoenix" },
2659 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "vvvv", "Mountain Standard Time", "America/Phoenix" },
2660 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "VVVV", "Phoenix Time", "America/Phoenix" },
2661
2662 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2663 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2664 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2665 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2666 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2667 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2668 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2669 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2670 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2671 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2672 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2673
2674 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2675 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2676 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2677 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2678 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2679 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2680 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2681 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2682 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2683 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2684 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2685
2686 { "en", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2687 { "en", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2688 { "en", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2689 { "en", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Cuba Standard Time", "-5:00" },
2690 { "en", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2691 { "en", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2692 { "en", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2693 { "en", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Cuba Daylight Time", "-4:00" },
2694 { "en", "America/Havana", "2004-07-15T00:00:00Z", "v", "Cuba Time", "America/Havana" },
2695 { "en", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Cuba Time", "America/Havana" },
2696 { "en", "America/Havana", "2004-07-15T00:00:00Z", "VVVV", "Cuba Time", "America/Havana" },
2697
2698 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2699 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2700 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2701 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2702 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2703 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2704 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2705 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2706 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2707 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2708 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2709
2710 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2711 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2712 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2713 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2714 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2715 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2716 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2717 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2718 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2719 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2720 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2721
2722 { "en", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2723 { "en", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2724 { "en", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2725 { "en", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Greenwich Mean Time", "+0:00" },
2726 { "en", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2727 { "en", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2728 { "en", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "Europe/London" },
2729 { "en", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "British Summer Time", "Europe/London" },
2730 // icu en.txt has exemplar city for this time zone
2731 { "en", "Europe/London", "2004-07-15T00:00:00Z", "v", "United Kingdom Time", "Europe/London" },
2732 { "en", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "United Kingdom Time", "Europe/London" },
2733 { "en", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "United Kingdom Time", "Europe/London" },
2734
2735 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2736 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2737 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2738 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2739 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2740 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2741 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2742 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2743 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2744 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2745
2746 // JB#5150
2747 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2748 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2749 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2750 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2751 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2752 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2753 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2754 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2755 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "India Time", "Asia/Calcutta" },
2756 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "India Standard Time", "Asia/Calcutta" },
2757
2758 // Proper CLDR primary zone support #9733
2759 { "en", "America/Santiago", "2013-01-01T00:00:00Z", "VVVV", "Chile Time", "America/Santiago" },
2760 { "en", "Pacific/Easter", "2013-01-01T00:00:00Z", "VVVV", "Easter Time", "Pacific/Easter" },
2761
2762 // ==========
2763
2764 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2765 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2766 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2767 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Normalzeit", "-8:00" },
2768 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2769 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2770 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2771 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Sommerzeit", "-7:00" },
2772 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles Zeit", "America/Los_Angeles" },
2773 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Nordamerikanische Westk\\u00fcstenzeit", "America/Los_Angeles" },
2774
2775 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2776 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2777 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2778 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2779 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2780 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2781 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2782 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2783 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2784 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2785
2786 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2787 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2788 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2789 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2790 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2791 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2792 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2793 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2794 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2795 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2796
2797 { "de", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2798 { "de", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2799 { "de", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2800 { "de", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Kubanische Normalzeit", "-5:00" },
2801 { "de", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2802 { "de", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2803 { "de", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2804 { "de", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Kubanische Sommerzeit", "-4:00" },
2805 { "de", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2806 { "de", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2807 // added to test proper fallback of country name
2808 { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2809 { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2810
2811 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2812 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2813 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2814 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2815 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2816 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2817 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2818 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2819 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2820 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2821
2822 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2823 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2824 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2825 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2826 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2827 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2828 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2829 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2830 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2831 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2832
2833 { "de", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2834 { "de", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2835 { "de", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2836 { "de", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Mittlere Greenwich-Zeit", "+0:00" },
2837 { "de", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2838 { "de", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2839 { "de", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2840 { "de", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "Britische Sommerzeit", "+1:00" },
2841 { "de", "Europe/London", "2004-07-15T00:00:00Z", "v", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2842 { "de", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2843
2844 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2845 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2846 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2847 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2848 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2849 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2850 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2851 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2852 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2853 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2854
2855 // JB#5150
2856 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2857 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2858 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2859 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2860 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2861 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2862 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2863 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2864 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "Indien Zeit", "Asia/Calcutta" },
2865 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "Indische Zeit", "Asia/Calcutta" },
2866
2867 // ==========
2868
2869 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2870 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2871 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2872 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u6807\\u51c6\\u65f6\\u95f4", "America/Los_Angeles" },
2873 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2874 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2875 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
2876 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u590f\\u4ee4\\u65f6\\u95f4", "America/Los_Angeles" },
2877 // icu zh.txt has exemplar city for this time zone
2878 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4", "America/Los_Angeles" },
2879 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u65f6\\u95f4", "America/Los_Angeles" },
2880
2881 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2882 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2883 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2884 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2885 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2886 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2887 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2888 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2889 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2890 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2891
2892 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2893 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2894 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2895 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2896 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2897 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2898 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2899 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2900 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2901 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2902
2903 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2904 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2905 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2906 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u6807\\u51c6\\u65f6\\u95f4", "-5:00" },
2907 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2908 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2909 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2910 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u590f\\u4ee4\\u65f6\\u95f4", "-4:00" },
2911 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2912 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2913
2914 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2915 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2916 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2917 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2918 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2919 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2920 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2921 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2922 // icu zh.txt does not have info for this time zone
2923 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2924 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2925
2926 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2927 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2928 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2929 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2930 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2931 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2932 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2933 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2934 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2935 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2936
2937 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2938 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2939 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2940 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2941 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2942 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u683C\\u6797\\u5C3C\\u6CBB\\u6807\\u51C6\\u65F6\\u95F4", "+0:00" },
2943 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2944 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2945 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2946 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u4ee4\\u65f6\\u95f4", "+1:00" },
2947 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2948 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2949 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2950
2951 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2952 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2953 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2954 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2955 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2956 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2957 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2958 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2959 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2960 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2961
2962 // JB#5150
2963 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2964 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2965 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2966 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2967 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2968 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2969 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2970 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2971 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2972 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2973
2974 // ==========
2975
2976 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2977 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-\\u0966\\u096E:\\u0966\\u0966", "-8:00" },
2978 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-\\u096E", "-8:00" },
2979 { "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" },
2980 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2981 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-\\u0966\\u096D:\\u0966\\u0966", "-7:00" },
2982 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-\\u096D", "-7:00" },
2983 { "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" },
2984 { "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" },
2985 { "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" },
2986
2987 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2988 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-\\u0966\\u0969:\\u0966\\u0966", "-3:00" },
2989 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-\\u0969", "-3:00" },
2990 { "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" },
2991 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2992 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-\\u0966\\u0969:\\u0966\\u0966", "-3:00" },
2993 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-\\u0969", "-3:00" },
2994 { "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" },
2995 { "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" },
2996 { "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" },
2997
2998 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2999 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-\\u0966\\u0969:\\u0966\\u0966", "-3:00" },
3000 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-\\u0969", "-3:00" },
3001 { "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" },
3002 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3003 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-\\u0966\\u0969:\\u0966\\u0966", "-3:00" },
3004 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-\\u0969", "-3:00" },
3005 { "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" },
3006 { "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" },
3007 { "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" },
3008
3009 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3010 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-\\u0966\\u096B:\\u0966\\u0966", "-5:00" },
3011 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-\\u096B", "-5:00" },
3012 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-5:00" },
3013 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3014 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-\\u0966\\u096A:\\u0966\\u0966", "-4:00" },
3015 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-\\u096A", "-4:00" },
3016 { "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" },
3017 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092E\\u092F", "America/Havana" },
3018 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092e\\u092f", "America/Havana" },
3019
3020 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3021 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+\\u0967\\u0967:\\u0966\\u0966", "+11:00" },
3022 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+\\u0967\\u0967", "+11:00" },
3023 { "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" },
3024 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3025 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+\\u0967\\u0966:\\u0966\\u0966", "+10:00" },
3026 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+\\u0967\\u0966", "+10:00" },
3027 { "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" },
3028 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3029 { "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" },
3030
3031 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3032 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+\\u0967\\u0967:\\u0966\\u0966", "+11:00" },
3033 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+\\u0967\\u0967", "+11:00" },
3034 { "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" },
3035 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3036 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+\\u0967\\u0966:\\u0966\\u0966", "+10:00" },
3037 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+\\u0967\\u0966", "+10:00" },
3038 { "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" },
3039 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3040 { "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" },
3041
3042 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3043 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3044 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3045 { "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" },
3046 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3047 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+\\u0966\\u0967:\\u0966\\u0966", "+1:00" },
3048 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+\\u0967", "+1:00" },
3049 { "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" },
3050 { "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" },
3051 { "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" },
3052
3053 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3054 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-\\u0966\\u0969:\\u0966\\u0966", "-3:00" },
3055 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-\\u0969", "-3:00" },
3056 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-\\u0966\\u0969:\\u0966\\u0966", "-3:00" },
3057 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3058 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-\\u0966\\u0969:\\u0966\\u0966", "-3:00" },
3059 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-\\u0969", "-3:00" },
3060 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-\\u0966\\u0969:\\u0966\\u0966", "-3:00" },
3061 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-\\u0969", "-3:00" },
3062 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-\\u0966\\u0969:\\u0966\\u0966", "-3:00" },
3063
3064 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3065 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+\\u0966\\u096B:\\u0969\\u0966", "+5:30" },
3066 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "IST", "+5:30" },
3067 { "hi", "Asia/Calcutta", "2004-01-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", "Z", "+0530", "+5:30" },
3069 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+\\u0966\\u096B:\\u0969\\u0966", "+5:30" },
3070 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "IST", "+05:30" },
3071 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3072 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IST", "Asia/Calcutta" },
3073 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "Asia/Calcutta" },
3074
3075 // ==========
3076
3077 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3078 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-08:00", "-8:00" },
3079 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-8", "America/Los_Angeles" },
3080 { "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" },
3081 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3082 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-07:00", "-7:00" },
3083 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-7", "America/Los_Angeles" },
3084 { "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" },
3085 // icu bg.txt has exemplar city for this time zone
3086 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3087 { "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" },
3088 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3089
3090 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3091 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3092 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3093 { "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" },
3094 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3095 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3096 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3097 { "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" },
3098 { "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" },
3099 { "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" },
3100
3101 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3102 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3103 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3104 { "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" },
3105 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3106 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3107 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3108 { "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" },
3109 // icu bg.txt does not have info for this time zone
3110 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
3111 { "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" },
3112
3113 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3114 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-05:00", "-5:00" },
3115 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-5", "-5:00" },
3116 { "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" },
3117 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3118 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-04:00", "-4:00" },
3119 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-4", "-4:00" },
3120 { "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" },
3121 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u041a\\u0443\\u0431\\u0430", "America/Havana" },
3122 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043C\\u0435", "America/Havana" },
3123
3124 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3125 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3126 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3127 { "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" },
3128 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3129 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3130 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3131 { "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" },
3132 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3133 { "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" },
3134
3135 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3136 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3137 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3138 { "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" },
3139 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3140 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3141 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3142 { "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" },
3143 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3144 { "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" },
3145
3146 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3147 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3148 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3149 { "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" },
3150 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3151 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+01:00", "+1:00" },
3152 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+1", "+1:00" },
3153 { "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" },
3154 { "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" },
3155 { "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" },
3156
3157 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3158 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3159 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3160 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3161 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3162 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3163 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3164 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3165 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3166 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3167
3168 // JB#5150
3169 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3170 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3171 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+5:30" },
3172 { "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" },
3173 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3174 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3175 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+05:30" },
3176 { "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" },
3177 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u0418\\u043D\\u0434\\u0438\\u044F", "Asia/Calcutta" },
3178 { "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" },
3179 // ==========
3180
3181 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3182 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3183 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
3184 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u6a19\\u6e96\\u6642", "America/Los_Angeles" },
3185 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-700" },
3186 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3187 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
3188 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u590f\\u6642\\u9593", "America/Los_Angeles" },
3189 // icu ja.txt has exemplar city for this time zone
3190 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3191 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30E1\\u30EA\\u30AB\\u592A\\u5e73\\u6D0B\\u6642\\u9593", "America/Los_Angeles" },
3192 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3193
3194 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3195 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3196 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3197 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3198 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3199 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3200 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3201 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3202 // icu ja.txt does not have info for this time zone
3203 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3204 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3205
3206 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3207 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3208 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3209 { "ja", "America/Buenos_Aires", "2004-01-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", "Z", "-0300", "-3:00" },
3211 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3212 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3213 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3214 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3215 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3216
3217 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3218 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3219 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3220 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u6A19\\u6E96\\u6642", "-5:00" },
3221 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3222 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3223 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3224 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u590F\\u6642\\u9593", "-4:00" },
3225 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3226 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3227
3228 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3229 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3230 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3231 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3232 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3233 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3234 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3235 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3236 // icu ja.txt does not have info for this time zone
3237 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3238 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3239
3240 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3241 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3242 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3243 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3244 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3245 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3246 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3247 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3248 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3249 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3250
3251 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3252 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3253 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3254 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u30B0\\u30EA\\u30CB\\u30C3\\u30B8\\u6A19\\u6E96\\u6642", "+0:00" },
3255 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3256 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3257 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3258 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u6642\\u9593", "+1:00" },
3259 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3260 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3261 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3262
3263 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3264 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3265 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3266 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3267 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3268 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3269 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3270 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3271 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3272 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3273
3274 // JB#5150
3275 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3276 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3277 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3278 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3279 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3280 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3281 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3282 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3283 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u30A4\\u30F3\\u30C9\\u6642\\u9593", "Asia/Calcutta" },
3284 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "Asia/Calcutta" },
3285
3286 // ==========
3287
3288 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3289 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3290 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
3291 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "GMT-08:00", "-8:00" },
3292 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3293 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3294 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
3295 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "GMT-07:00", "-7:00" },
3296 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles", "America/Los_Angeles" },
3297 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Los Angeles", "America/Los_Angeles" },
3298
3299 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3300 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3301 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3302 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3303 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3304 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3305 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3306 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3307 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3308 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3309
3310 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3311 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3312 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3313 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3314 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3315 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3316 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3317 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3318 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3319 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3320
3321 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3322 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3323 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3324 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "GMT-05:00", "-5:00" },
3325 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3326 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3327 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3328 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "GMT-04:00", "-4:00" },
3329 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "v", "CU", "America/Havana" },
3330 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "CU", "America/Havana" },
3331
3332 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3333 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3334 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3335 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3336 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3337 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3338 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3339 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3340 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3341 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3342
3343 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3344 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3345 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3346 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3347 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3348 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3349 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3350 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3351 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3352 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3353
3354 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3355 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3356 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3357 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "GMT", "+0:00" },
3358 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3359 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3360 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3361 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "GMT+01:00", "+1:00" },
3362 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "v", "GB", "Europe/London" },
3363 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "GB", "Europe/London" },
3364
3365 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3366 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3367 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3368 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3369 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3370 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3371 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3372 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3373 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3374 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3375
3376 // JB#5150
3377 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3378 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3379 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3380 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3381 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3382 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3383 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3384 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3385 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IN", "Alna/Calcutta" },
3386 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "IN", "Asia/Calcutta" },
3387
3388 // Ticket#8589 Partial location name to use country name if the zone is the golden
3389 // zone for the time zone's country.
3390 { "en_MX", "America/Chicago", "1995-07-15T00:00:00Z", "vvvv", "Central Time (United States)", "America/Chicago"},
3391
3392 // Tests proper handling of time zones that should have empty sets when inherited from the parent.
3393 // For example, en_GB understands CET as Central European Time, but en_HK, which inherits from en_GB
3394 // does not
3395 { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3396 { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3397 { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "CET", "+1:00"},
3398 { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "CEST", "+2:00"},
3399 { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3400 { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3401 { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "GMT+1", "+1:00"},
3402 { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "GMT+2", "+2:00"},
3403
3404 { NULL, NULL, NULL, NULL, NULL, NULL },
3405 };
3406
3407 UErrorCode status = U_ZERO_ERROR;
3408 Calendar *cal = GregorianCalendar::createInstance(status);
3409 if (failure(status, "GregorianCalendar::createInstance", TRUE)) return;
3410 SimpleDateFormat testfmt(UnicodeString("yyyy-MM-dd'T'HH:mm:ss'Z'"), status);
3411 if (failure(status, "SimpleDateFormat constructor", TRUE)) return;
3412 testfmt.setTimeZone(*TimeZone::getGMT());
3413
3414 for (int i = 0; fallbackTests[i][0]; i++) {
3415 const char **testLine = fallbackTests[i];
3416 UnicodeString info[5];
3417 for ( int j = 0 ; j < 5 ; j++ ) {
3418 info[j] = UnicodeString(testLine[j], -1, US_INV);
3419 }
3420 info[4] = info[4].unescape();
3421 logln("%s;%s;%s;%s", testLine[0], testLine[1], testLine[2], testLine[3]);
3422
3423 TimeZone *tz = TimeZone::createTimeZone(info[1]);
3424
3425 UDate d = testfmt.parse(testLine[2], status);
3426 cal->setTime(d, status);
3427 if (U_FAILURE(status)) {
3428 errln(UnicodeString("Failed to set date: ") + testLine[2]);
3429 }
3430
3431 SimpleDateFormat fmt(info[3], Locale(testLine[0]),status);
3432 ASSERT_OK(status);
3433 cal->adoptTimeZone(tz);
3434 UnicodeString result;
3435 FieldPosition pos(FieldPosition::DONT_CARE);
3436 fmt.format(*cal,result,pos);
3437 if (result != info[4]) {
3438 errln(info[0] + ";" + info[1] + ";" + info[2] + ";" + info[3] + " expected: '" +
3439 info[4] + "' but got: '" + result + "'");
3440 }
3441 }
3442 delete cal;
3443 }
3444
3445 void DateFormatTest::TestRoundtripWithCalendar(void) {
3446 UErrorCode status = U_ZERO_ERROR;
3447
3448 TimeZone *tz = TimeZone::createTimeZone("Europe/Paris");
3449 TimeZone *gmt = TimeZone::createTimeZone("Etc/GMT");
3450
3451 Calendar *calendars[] = {
3452 Calendar::createInstance(*tz, Locale("und@calendar=gregorian"), status),
3453 Calendar::createInstance(*tz, Locale("und@calendar=buddhist"), status),
3454 // Calendar::createInstance(*tz, Locale("und@calendar=hebrew"), status),
3455 Calendar::createInstance(*tz, Locale("und@calendar=islamic"), status),
3456 Calendar::createInstance(*tz, Locale("und@calendar=japanese"), status),
3457 NULL
3458 };
3459 if (U_FAILURE(status)) {
3460 dataerrln("Failed to initialize calendars: %s", u_errorName(status));
3461 for (int i = 0; calendars[i] != NULL; i++) {
3462 delete calendars[i];
3463 }
3464 return;
3465 }
3466
3467 //FIXME The formatters commented out below are currently failing because of
3468 // the calendar calculation problem reported by #6691
3469
3470 // The order of test formatters must match the order of calendars above.
3471 DateFormat *formatters[] = {
3472 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("en_US")), //calendar=gregorian
3473 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("th_TH")), //calendar=buddhist
3474 // DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("he_IL@calendar=hebrew")),
3475 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ar_EG@calendar=islamic")),
3476 // DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ja_JP@calendar=japanese")),
3477 NULL
3478 };
3479
3480 UDate d = Calendar::getNow();
3481 UnicodeString buf;
3482 FieldPosition fpos;
3483 ParsePosition ppos;
3484
3485 for (int i = 0; formatters[i] != NULL; i++) {
3486 buf.remove();
3487 fpos.setBeginIndex(0);
3488 fpos.setEndIndex(0);
3489 calendars[i]->setTime(d, status);
3490
3491 // Normal case output - the given calendar matches the calendar
3492 // used by the formatter
3493 formatters[i]->format(*calendars[i], buf, fpos);
3494 UnicodeString refStr(buf);
3495
3496 for (int j = 0; calendars[j] != NULL; j++) {
3497 if (j == i) {
3498 continue;
3499 }
3500 buf.remove();
3501 fpos.setBeginIndex(0);
3502 fpos.setEndIndex(0);
3503 calendars[j]->setTime(d, status);
3504
3505 // Even the different calendar type is specified,
3506 // we should get the same result.
3507 formatters[i]->format(*calendars[j], buf, fpos);
3508 if (refStr != buf) {
3509 errln((UnicodeString)"FAIL: Different format result with a different calendar for the same time -"
3510 + "\n Reference calendar type=" + calendars[i]->getType()
3511 + "\n Another calendar type=" + calendars[j]->getType()
3512 + "\n Expected result=" + refStr
3513 + "\n Actual result=" + buf);
3514 }
3515 }
3516
3517 calendars[i]->setTimeZone(*gmt);
3518 calendars[i]->clear();
3519 ppos.setErrorIndex(-1);
3520 ppos.setIndex(0);
3521
3522 // Normal case parse result - the given calendar matches the calendar
3523 // used by the formatter
3524 formatters[i]->parse(refStr, *calendars[i], ppos);
3525
3526 for (int j = 0; calendars[j] != NULL; j++) {
3527 if (j == i) {
3528 continue;
3529 }
3530 calendars[j]->setTimeZone(*gmt);
3531 calendars[j]->clear();
3532 ppos.setErrorIndex(-1);
3533 ppos.setIndex(0);
3534
3535 // Even the different calendar type is specified,
3536 // we should get the same time and time zone.
3537 formatters[i]->parse(refStr, *calendars[j], ppos);
3538 if (calendars[i]->getTime(status) != calendars[j]->getTime(status)
3539 || calendars[i]->getTimeZone() != calendars[j]->getTimeZone()) {
3540 UnicodeString tzid;
3541 errln((UnicodeString)"FAIL: Different parse result with a different calendar for the same string -"
3542 + "\n Reference calendar type=" + calendars[i]->getType()
3543 + "\n Another calendar type=" + calendars[j]->getType()
3544 + "\n Date string=" + refStr
3545 + "\n Expected time=" + calendars[i]->getTime(status)
3546 + "\n Expected time zone=" + calendars[i]->getTimeZone().getID(tzid)
3547 + "\n Actual time=" + calendars[j]->getTime(status)
3548 + "\n Actual time zone=" + calendars[j]->getTimeZone().getID(tzid));
3549 }
3550 }
3551 if (U_FAILURE(status)) {
3552 errln((UnicodeString)"FAIL: " + u_errorName(status));
3553 break;
3554 }
3555 }
3556
3557 delete tz;
3558 delete gmt;
3559 for (int i = 0; calendars[i] != NULL; i++) {
3560 delete calendars[i];
3561 }
3562 for (int i = 0; formatters[i] != NULL; i++) {
3563 delete formatters[i];
3564 }
3565 }
3566
3567 /*
3568 void DateFormatTest::TestRelativeError(void)
3569 {
3570 UErrorCode status;
3571 Locale en("en");
3572
3573 DateFormat *en_reltime_reldate = DateFormat::createDateTimeInstance(DateFormat::kFullRelative,DateFormat::kFullRelative,en);
3574 if(en_reltime_reldate == NULL) {
3575 logln("PASS: rel date/rel time failed");
3576 } else {
3577 errln("FAIL: rel date/rel time created, should have failed.");
3578 delete en_reltime_reldate;
3579 }
3580 }
3581
3582 void DateFormatTest::TestRelativeOther(void)
3583 {
3584 logln("Nothing in this test. When we get more data from CLDR, put in some tests of -2, +2, etc. ");
3585 }
3586 */
3587
3588 void DateFormatTest::Test6338(void)
3589 {
3590 UErrorCode status = U_ZERO_ERROR;
3591
3592 SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("ar"), status);
3593 if (failure(status, "new SimpleDateFormat", TRUE)) return;
3594
3595 UDate dt1 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3596 UnicodeString str1;
3597 str1 = fmt1->format(dt1, str1);
3598 logln(str1);
3599
3600 UDate dt11 = fmt1->parse(str1, status);
3601 failure(status, "fmt->parse");
3602
3603 UnicodeString str11;
3604 str11 = fmt1->format(dt11, str11);
3605 logln(str11);
3606
3607 if (str1 != str11) {
3608 errln((UnicodeString)"FAIL: Different dates str1:" + str1
3609 + " str2:" + str11);
3610 }
3611 delete fmt1;
3612
3613 /////////////////
3614
3615 status = U_ZERO_ERROR;
3616 SimpleDateFormat *fmt2 = new SimpleDateFormat(UnicodeString("y M d"), Locale("ar"), status);
3617 failure(status, "new SimpleDateFormat");
3618
3619 UDate dt2 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3620 UnicodeString str2;
3621 str2 = fmt2->format(dt2, str2);
3622 logln(str2);
3623
3624 UDate dt22 = fmt2->parse(str2, status);
3625 failure(status, "fmt->parse");
3626
3627 UnicodeString str22;
3628 str22 = fmt2->format(dt22, str22);
3629 logln(str22);
3630
3631 if (str2 != str22) {
3632 errln((UnicodeString)"FAIL: Different dates str1:" + str2
3633 + " str2:" + str22);
3634 }
3635 delete fmt2;
3636
3637 /////////////////
3638
3639 status = U_ZERO_ERROR;
3640 SimpleDateFormat *fmt3 = new SimpleDateFormat(UnicodeString("y-M-d"), Locale("en-us"), status);
3641 failure(status, "new SimpleDateFormat");
3642
3643 UDate dt3 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3644 UnicodeString str3;
3645 str3 = fmt3->format(dt3, str3);
3646 logln(str3);
3647
3648 UDate dt33 = fmt3->parse(str3, status);
3649 failure(status, "fmt->parse");
3650
3651 UnicodeString str33;
3652 str33 = fmt3->format(dt33, str33);
3653 logln(str33);
3654
3655 if (str3 != str33) {
3656 errln((UnicodeString)"FAIL: Different dates str1:" + str3
3657 + " str2:" + str33);
3658 }
3659 delete fmt3;
3660
3661 /////////////////
3662
3663 status = U_ZERO_ERROR;
3664 SimpleDateFormat *fmt4 = new SimpleDateFormat(UnicodeString("y M d"), Locale("en-us"), status);
3665 failure(status, "new SimpleDateFormat");
3666
3667 UDate dt4 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3668 UnicodeString str4;
3669 str4 = fmt4->format(dt4, str4);
3670 logln(str4);
3671
3672 UDate dt44 = fmt4->parse(str4, status);
3673 failure(status, "fmt->parse");
3674
3675 UnicodeString str44;
3676 str44 = fmt4->format(dt44, str44);
3677 logln(str44);
3678
3679 if (str4 != str44) {
3680 errln((UnicodeString)"FAIL: Different dates str1:" + str4
3681 + " str2:" + str44);
3682 }
3683 delete fmt4;
3684
3685 }
3686
3687 void DateFormatTest::Test6726(void)
3688 {
3689 // status
3690 // UErrorCode status = U_ZERO_ERROR;
3691
3692 // fmtf, fmtl, fmtm, fmts;
3693 UnicodeString strf, strl, strm, strs;
3694 UDate dt = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3695
3696 Locale loc("ja");
3697 DateFormat* fmtf = DateFormat::createDateTimeInstance(DateFormat::FULL, DateFormat::FULL, loc);
3698 DateFormat* fmtl = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::FULL, loc);
3699 DateFormat* fmtm = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, loc);
3700 DateFormat* fmts = DateFormat::createDateTimeInstance(DateFormat::SHORT, DateFormat::FULL, loc);
3701 if (fmtf == NULL || fmtl == NULL || fmtm == NULL || fmts == NULL) {
3702 dataerrln("Unable to create DateFormat. got NULL.");
3703 /* It may not be true that if one is NULL all is NULL. Just to be safe. */
3704 delete fmtf;
3705 delete fmtl;
3706 delete fmtm;
3707 delete fmts;
3708
3709 return;
3710 }
3711 strf = fmtf->format(dt, strf);
3712 strl = fmtl->format(dt, strl);
3713 strm = fmtm->format(dt, strm);
3714 strs = fmts->format(dt, strs);
3715
3716
3717 logln("strm.charAt(10)=%04X wanted 0x20\n", strm.charAt(10));
3718 if (strm.charAt(10) != UChar(0x0020)) {
3719 errln((UnicodeString)"FAIL: Improper formatted date: " + strm );
3720 }
3721 logln("strs.charAt(10)=%04X wanted 0x20\n", strs.charAt(8));
3722 if (strs.charAt(10) != UChar(0x0020)) {
3723 errln((UnicodeString)"FAIL: Improper formatted date: " + strs);
3724 }
3725
3726 delete fmtf;
3727 delete fmtl;
3728 delete fmtm;
3729 delete fmts;
3730
3731 return;
3732 }
3733
3734 /**
3735 * Test DateFormat's parsing of default GMT variants. See ticket#6135
3736 */
3737 void DateFormatTest::TestGMTParsing() {
3738 const char* DATA[] = {
3739 "HH:mm:ss Z",
3740
3741 // pattern, input, expected output (in quotes)
3742 "HH:mm:ss Z", "10:20:30 GMT+03:00", "10:20:30 +0300",
3743 "HH:mm:ss Z", "10:20:30 UT-02:00", "10:20:30 -0200",
3744 "HH:mm:ss Z", "10:20:30 GMT", "10:20:30 +0000",
3745 "HH:mm:ss vvvv", "10:20:30 UT+10:00", "10:20:30 +1000",
3746 "HH:mm:ss zzzz", "10:20:30 UTC", "10:20:30 +0000", // standalone "UTC"
3747 "ZZZZ HH:mm:ss", "UT 10:20:30", "10:20:30 +0000",
3748 "z HH:mm:ss", "UT+0130 10:20:30", "10:20:30 +0130",
3749 "z HH:mm:ss", "UTC+0130 10:20:30", "10:20:30 +0130",
3750 // Note: GMT-1100 no longer works because of the introduction of the short
3751 // localized GMT support. Previous implementation support this level of
3752 // leniency (no separator char in localized GMT format), but the new
3753 // implementation handles GMT-11 as the legitimate short localized GMT format
3754 // and stop at there. Otherwise, roundtrip would be broken.
3755 //"HH mm Z ss", "10 20 GMT-1100 30", "10:20:30 -1100",
3756 "HH mm Z ss", "10 20 GMT-11 30", "10:20:30 -1100",
3757 "HH:mm:ssZZZZZ", "14:25:45Z", "14:25:45 +0000",
3758 "HH:mm:ssZZZZZ", "15:00:00-08:00", "15:00:00 -0800",
3759 };
3760 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
3761 expectParse(DATA, DATA_len, Locale("en"));
3762 }
3763
3764 // Test case for localized GMT format parsing
3765 // with no delimitters in offset format (Chinese locale)
3766 void DateFormatTest::Test6880() {
3767 UErrorCode status = U_ZERO_ERROR;
3768 UDate d1, d2, dp1, dp2, dexp1, dexp2;
3769 UnicodeString s1, s2;
3770
3771 TimeZone *tz = TimeZone::createTimeZone("Asia/Shanghai");
3772 GregorianCalendar gcal(*tz, status);
3773 if (failure(status, "construct GregorianCalendar", TRUE)) return;
3774
3775 gcal.clear();
3776 gcal.set(1900, UCAL_JULY, 1, 12, 00); // offset 8:05:43
3777 d1 = gcal.getTime(status);
3778
3779 gcal.clear();
3780 gcal.set(1950, UCAL_JULY, 1, 12, 00); // offset 8:00
3781 d2 = gcal.getTime(status);
3782
3783 gcal.clear();
3784 gcal.set(1970, UCAL_JANUARY, 1, 12, 00);
3785 dexp2 = gcal.getTime(status);
3786 dexp1 = dexp2 - (5*60 + 43)*1000; // subtract 5m43s
3787
3788 if (U_FAILURE(status)) {
3789 errln("FAIL: Gregorian calendar error");
3790 }
3791
3792 DateFormat *fmt = DateFormat::createTimeInstance(DateFormat::kFull, Locale("zh"));
3793 if (fmt == NULL) {
3794 dataerrln("Unable to create DateFormat. Got NULL.");
3795 return;
3796 }
3797 fmt->adoptTimeZone(tz);
3798
3799 fmt->format(d1, s1);
3800 fmt->format(d2, s2);
3801
3802 dp1 = fmt->parse(s1, status);
3803 dp2 = fmt->parse(s2, status);
3804
3805 if (U_FAILURE(status)) {
3806 errln("FAIL: Parse failure");
3807 }
3808
3809 if (dp1 != dexp1) {
3810 errln("FAIL: Failed to parse " + s1 + " parsed: " + dp1 + " expected: " + dexp1);
3811 }
3812 if (dp2 != dexp2) {
3813 errln("FAIL: Failed to parse " + s2 + " parsed: " + dp2 + " expected: " + dexp2);
3814 }
3815
3816 delete fmt;
3817 }
3818
3819 typedef struct {
3820 const char * localeStr;
3821 UBool lenient;
3822 UBool expectFail;
3823 UnicodeString datePattern;
3824 UnicodeString dateString;
3825 } NumAsStringItem;
3826
3827 void DateFormatTest::TestNumberAsStringParsing()
3828 {
3829 const NumAsStringItem items[] = {
3830 // loc lenient fail? datePattern dateString
3831 { "", FALSE, TRUE, UnicodeString("y MMMM d HH:mm:ss"), UnicodeString("2009 7 14 08:43:57") },
3832 { "", TRUE, FALSE, UnicodeString("y MMMM d HH:mm:ss"), UnicodeString("2009 7 14 08:43:57") },
3833 { "en", FALSE, FALSE, UnicodeString("MMM d, y"), UnicodeString("Jul 14, 2009") },
3834 { "en", TRUE, FALSE, UnicodeString("MMM d, y"), UnicodeString("Jul 14, 2009") },
3835 { "en", FALSE, TRUE, UnicodeString("MMM d, y"), UnicodeString("7 14, 2009") },
3836 { "en", TRUE, FALSE, UnicodeString("MMM d, y"), UnicodeString("7 14, 2009") },
3837 { "ja", FALSE, FALSE, UnicodeString("yyyy/MM/dd"), UnicodeString("2009/07/14") },
3838 { "ja", TRUE, FALSE, UnicodeString("yyyy/MM/dd"), UnicodeString("2009/07/14") },
3839 //{ "ja", FALSE, FALSE, UnicodeString("yyyy/MMMMM/d"), UnicodeString("2009/7/14") }, // #8860 covers test failure
3840 { "ja", TRUE, FALSE, UnicodeString("yyyy/MMMMM/d"), UnicodeString("2009/7/14") },
3841 { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3842 { "ja", TRUE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3843 { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3844 { "ja", TRUE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") }, // #8820 fixes test failure
3845 { "ko", FALSE, FALSE, UnicodeString("yyyy. M. d."), UnicodeString("2009. 7. 14.") },
3846 { "ko", TRUE, FALSE, UnicodeString("yyyy. M. d."), UnicodeString("2009. 7. 14.") },
3847 { "ko", FALSE, FALSE, UnicodeString("yyyy. MMMMM d."), CharsToUnicodeString("2009. 7\\uC6D4 14.") },
3848 { "ko", TRUE, FALSE, UnicodeString("yyyy. MMMMM d."), CharsToUnicodeString("2009. 7\\uC6D4 14.") }, // #8820 fixes test failure
3849 { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3850 { "ko", TRUE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3851 { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3852 { "ko", TRUE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") }, // #8820 fixes test failure
3853 { NULL, FALSE, FALSE, UnicodeString(""), UnicodeString("") }
3854 };
3855 const NumAsStringItem * itemPtr;
3856 for (itemPtr = items; itemPtr->localeStr != NULL; itemPtr++ ) {
3857 Locale locale = Locale::createFromName(itemPtr->localeStr);
3858 UErrorCode status = U_ZERO_ERROR;
3859 SimpleDateFormat *formatter = new SimpleDateFormat(itemPtr->datePattern, locale, status);
3860 if (formatter == NULL || U_FAILURE(status)) {
3861 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3862 return;
3863 }
3864
3865 formatter->setLenient(itemPtr->lenient);
3866 formatter->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->lenient, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->lenient, status);
3867 UDate date1 = formatter->parse(itemPtr->dateString, status);
3868 if (U_FAILURE(status)) {
3869 if (!itemPtr->expectFail) {
3870 errln("FAIL, err when expected success: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3871 ": using pattern \"" + itemPtr->datePattern + "\", could not parse \"" + itemPtr->dateString + "\"; err: " + u_errorName(status) );
3872 }
3873 } else if (itemPtr->expectFail) {
3874 errln("FAIL, expected err but got none: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3875 ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\"." );
3876 } else if (!itemPtr->lenient) {
3877 UnicodeString formatted;
3878 formatter->format(date1, formatted);
3879 if (formatted != itemPtr->dateString) {
3880 errln("FAIL, mismatch formatting parsed date: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3881 ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\", formatted result \"" + formatted + "\".");
3882 }
3883 }
3884
3885 delete formatter;
3886 }
3887 }
3888
3889 void DateFormatTest::TestISOEra() {
3890
3891 const char* data[] = {
3892 // input, output
3893 "BC 4004-10-23T07:00:00Z", "BC 4004-10-23T07:00:00Z",
3894 "AD 4004-10-23T07:00:00Z", "AD 4004-10-23T07:00:00Z",
3895 "-4004-10-23T07:00:00Z" , "BC 4005-10-23T07:00:00Z",
3896 "4004-10-23T07:00:00Z" , "AD 4004-10-23T07:00:00Z",
3897 };
3898
3899 int32_t numData = 8;
3900
3901 UErrorCode status = U_ZERO_ERROR;
3902
3903 // create formatter
3904 SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("GGG yyyy-MM-dd'T'HH:mm:ss'Z"), status);
3905 failure(status, "new SimpleDateFormat", TRUE);
3906 if (status == U_MISSING_RESOURCE_ERROR) {
3907 if (fmt1 != NULL) {
3908 delete fmt1;
3909 }
3910 return;
3911 }
3912 for(int i=0; i < numData; i+=2) {
3913 // create input string
3914 UnicodeString in = data[i];
3915
3916 // parse string to date
3917 UDate dt1 = fmt1->parse(in, status);
3918 failure(status, "fmt->parse", TRUE);
3919
3920 // format date back to string
3921 UnicodeString out;
3922 out = fmt1->format(dt1, out);
3923 logln(out);
3924
3925 // check that roundtrip worked as expected
3926 UnicodeString expected = data[i+1];
3927 if (out != expected) {
3928 dataerrln((UnicodeString)"FAIL: " + in + " -> " + out + " expected -> " + expected);
3929 }
3930 }
3931
3932 delete fmt1;
3933 }
3934 void DateFormatTest::TestFormalChineseDate() {
3935
3936 UErrorCode status = U_ZERO_ERROR;
3937 UnicodeString pattern ("y\\u5e74M\\u6708d\\u65e5", -1, US_INV );
3938 pattern = pattern.unescape();
3939 UnicodeString override ("y=hanidec;M=hans;d=hans", -1, US_INV );
3940
3941 // create formatter
3942 SimpleDateFormat *sdf = new SimpleDateFormat(pattern,override,Locale::getChina(),status);
3943 if (failure(status, "new SimpleDateFormat with override", TRUE)) {
3944 return;
3945 }
3946
3947 UDate thedate = date(2009-1900, UCAL_JULY, 28);
3948 FieldPosition pos(FieldPosition::DONT_CARE);
3949 UnicodeString result;
3950 sdf->format(thedate,result,pos);
3951
3952 UnicodeString expected = "\\u4e8c\\u3007\\u3007\\u4e5d\\u5e74\\u4e03\\u6708\\u4e8c\\u5341\\u516b\\u65e5";
3953 expected = expected.unescape();
3954 if (result != expected) {
3955 dataerrln((UnicodeString)"FAIL: -> " + result + " expected -> " + expected);
3956 }
3957
3958 UDate parsedate = sdf->parse(expected,status);
3959 if ( parsedate != thedate ) {
3960 UnicodeString pat1 ("yyyy-MM-dd'T'HH:mm:ss'Z'", -1, US_INV );
3961 SimpleDateFormat *usf = new SimpleDateFormat(pat1,Locale::getEnglish(),status);
3962 UnicodeString parsedres,expres;
3963 usf->format(parsedate,parsedres,pos);
3964 usf->format(thedate,expres,pos);
3965 dataerrln((UnicodeString)"FAIL: parsed -> " + parsedres + " expected -> " + expres);
3966 delete usf;
3967 }
3968 delete sdf;
3969 }
3970
3971 // Test case for #8675
3972 // Incorrect parse offset with stand alone GMT string on 2nd or later iteration.
3973 void DateFormatTest::TestStandAloneGMTParse() {
3974 UErrorCode status = U_ZERO_ERROR;
3975 SimpleDateFormat *sdf = new SimpleDateFormat("ZZZZ", Locale(""), status);
3976
3977 if (U_SUCCESS(status)) {
3978
3979 UnicodeString inText("GMT$$$");
3980 for (int32_t i = 0; i < 10; i++) {
3981 ParsePosition pos(0);
3982 sdf->parse(inText, pos);
3983 if (pos.getIndex() != 3) {
3984 errln((UnicodeString)"FAIL: Incorrect output parse position: actual=" + pos.getIndex() + " expected=3");
3985 }
3986 }
3987
3988 delete sdf;
3989 } else {
3990 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3991 }
3992 }
3993
3994 void DateFormatTest::TestParsePosition() {
3995 const char* TestData[][4] = {
3996 // {<pattern>, <lead>, <date string>, <trail>}
3997 {"yyyy-MM-dd HH:mm:ssZ", "", "2010-01-10 12:30:00+0500", ""},
3998 {"yyyy-MM-dd HH:mm:ss ZZZZ", "", "2010-01-10 12:30:00 GMT+05:00", ""},
3999 {"Z HH:mm:ss", "", "-0100 13:20:30", ""},
4000 {"y-M-d Z", "", "2011-8-25 -0400", " Foo"},
4001 {"y/M/d H:mm:ss z", "", "2011/7/1 12:34:00 PDT", ""},
4002 {"y/M/d H:mm:ss z", "+123", "2011/7/1 12:34:00 PDT", " PST"},
4003 {"vvvv a h:mm:ss", "", "Pacific Time AM 10:21:45", ""},
4004 {"HH:mm v M/d", "111", "14:15 PT 8/10", " 12345"},
4005 {"'time zone:' VVVV 'date:' yyyy-MM-dd", "xxxx", "time zone: Los Angeles Time date: 2010-02-25", "xxxx"},
4006 {"yG", "", "2012AD", ""},
4007 {"yG", "", "2012", "x"},
4008 {0, 0, 0, 0},
4009 };
4010
4011 for (int32_t i = 0; TestData[i][0]; i++) {
4012 UErrorCode status = U_ZERO_ERROR;
4013 SimpleDateFormat *sdf = new SimpleDateFormat(UnicodeString(TestData[i][0]), status);
4014 if (failure(status, "new SimpleDateFormat", TRUE)) return;
4015
4016 int32_t startPos, resPos;
4017
4018 // lead text
4019 UnicodeString input(TestData[i][1]);
4020 startPos = input.length();
4021
4022 // date string
4023 input += TestData[i][2];
4024 resPos = input.length();
4025
4026 // trail text
4027 input += TestData[i][3];
4028
4029 ParsePosition pos(startPos);
4030 //UDate d = sdf->parse(input, pos);
4031 (void)sdf->parse(input, pos);
4032
4033 if (pos.getIndex() != resPos) {
4034 errln(UnicodeString("FAIL: Parsing [") + input + "] with pattern [" + TestData[i][0] + "] returns position - "
4035 + pos.getIndex() + ", expected - " + resPos);
4036 }
4037
4038 delete sdf;
4039 }
4040 }
4041
4042
4043 typedef struct {
4044 int32_t era;
4045 int32_t year;
4046 int32_t month; // 1-based
4047 int32_t isLeapMonth;
4048 int32_t day;
4049 } ChineseCalTestDate;
4050
4051 #define NUM_TEST_DATES 3
4052
4053 typedef struct {
4054 const char * locale;
4055 int32_t style; // <0 => custom
4056 UnicodeString dateString[NUM_TEST_DATES];
4057 } MonthPatternItem;
4058
4059 void DateFormatTest::TestMonthPatterns()
4060 {
4061 const ChineseCalTestDate dates[NUM_TEST_DATES] = {
4062 // era yr mo lp da
4063 { 78, 29, 4, 0, 2 }, // (in chinese era 78) gregorian 2012-4-22
4064 { 78, 29, 4, 1, 2 }, // (in chinese era 78) gregorian 2012-5-22
4065 { 78, 29, 5, 0, 2 }, // (in chinese era 78) gregorian 2012-6-20
4066 };
4067
4068 const MonthPatternItem items[] = {
4069 // locale date style; expected formats for the 3 dates above
4070 { "root@calendar=chinese", DateFormat::kLong, { UnicodeString("2012(ren-chen) M04 2"), UnicodeString("2012(ren-chen) M04bis 2"), UnicodeString("2012(ren-chen) M05 2") } },
4071 { "root@calendar=chinese", DateFormat::kShort, { UnicodeString("2012-04-02"), UnicodeString("2012-04bis-02"), UnicodeString("2012-05-02") } },
4072 { "root@calendar=chinese", -1, { UnicodeString("29-4-2"), UnicodeString("29-4bis-2"), UnicodeString("29-5-2") } },
4073 { "root@calendar=chinese", -2, { UnicodeString("78x29-4-2"), UnicodeString("78x29-4bis-2"), UnicodeString("78x29-5-2") } },
4074 { "root@calendar=chinese", -3, { UnicodeString("ren-chen-4-2"), UnicodeString("ren-chen-4bis-2"), UnicodeString("ren-chen-5-2") } },
4075 { "root@calendar=chinese", -4, { UnicodeString("ren-chen M04 2"), UnicodeString("ren-chen M04bis 2"), UnicodeString("ren-chen M05 2") } },
4076 { "en@calendar=gregorian", -3, { UnicodeString("2012-4-22"), UnicodeString("2012-5-22"), UnicodeString("2012-6-20") } },
4077 { "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)") } },
4078 { "en@calendar=chinese", DateFormat::kShort, { UnicodeString("4/2/2012"), UnicodeString("4bis/2/2012"), UnicodeString("5/2/2012") } },
4079 { "zh@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4080 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u95F0\\u56DB\\u6708\\u521D\\u4E8C"),
4081 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4082 { "zh@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("2012-4-2"),
4083 CharsToUnicodeString("2012-\\u95F04-2"),
4084 CharsToUnicodeString("2012-5-2") } },
4085 { "zh@calendar=chinese", -3, { CharsToUnicodeString("\\u58EC\\u8FB0-4-2"),
4086 CharsToUnicodeString("\\u58EC\\u8FB0-\\u95F04-2"),
4087 CharsToUnicodeString("\\u58EC\\u8FB0-5-2") } },
4088 { "zh@calendar=chinese", -4, { CharsToUnicodeString("\\u58EC\\u8FB0 \\u56DB\\u6708 2"),
4089 CharsToUnicodeString("\\u58EC\\u8FB0 \\u95F0\\u56DB\\u6708 2"),
4090 CharsToUnicodeString("\\u58EC\\u8FB0 \\u4E94\\u6708 2") } },
4091 { "zh_Hant@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4092 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u958F\\u56DB\\u6708\\u521D\\u4E8C"),
4093 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4094 { "zh_Hant@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("2012/4/2"),
4095 CharsToUnicodeString("2012/\\u958F4/2"),
4096 CharsToUnicodeString("2012/5/2") } },
4097 { "fr@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2 s\\u00ECyu\\u00E8 ren-chen"),
4098 CharsToUnicodeString("2 s\\u00ECyu\\u00E8bis ren-chen"),
4099 CharsToUnicodeString("2 w\\u01D4yu\\u00E8 ren-chen") } },
4100 { "fr@calendar=chinese", DateFormat::kShort, { UnicodeString("2/4/29"), UnicodeString("2/4bis/29"), UnicodeString("2/5/29") } },
4101 { "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)") } },
4102 { "en@calendar=dangi", DateFormat::kShort, { UnicodeString("3bis/2/2012"), UnicodeString("4/2/2012"), UnicodeString("5/1/2012") } },
4103 { "en@calendar=dangi", -2, { UnicodeString("78x29-3bis-2"), UnicodeString("78x29-4-2"), UnicodeString("78x29-5-1") } },
4104 { "ko@calendar=dangi", DateFormat::kLong, { CharsToUnicodeString("\\uC784\\uC9C4\\uB144 \\uC7243\\uC6D4 2\\uC77C"),
4105 CharsToUnicodeString("\\uC784\\uC9C4\\uB144 4\\uC6D4 2\\uC77C"),
4106 CharsToUnicodeString("\\uC784\\uC9C4\\uB144 5\\uC6D4 1\\uC77C") } },
4107 { "ko@calendar=dangi", DateFormat::kShort, { CharsToUnicodeString("29. \\uC7243. 2."),
4108 CharsToUnicodeString("29. 4. 2."),
4109 CharsToUnicodeString("29. 5. 1.") } },
4110 // terminator
4111 { NULL, 0, { UnicodeString(""), UnicodeString(""), UnicodeString("") } }
4112 };
4113
4114 //. style: -1 -2 -3 -4
4115 const UnicodeString customPatterns[] = { "y-Ml-d", "G'x'y-Ml-d", "U-M-d", "U MMM d" }; // like old root pattern, using 'l'
4116
4117 UErrorCode status = U_ZERO_ERROR;
4118 Locale rootChineseCalLocale = Locale::createFromName("root@calendar=chinese");
4119 Calendar * rootChineseCalendar = Calendar::createInstance(rootChineseCalLocale, status);
4120 if (U_SUCCESS(status)) {
4121 const MonthPatternItem * itemPtr;
4122 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4123 Locale locale = Locale::createFromName(itemPtr->locale);
4124 DateFormat * dmft = (itemPtr->style >= 0)?
4125 DateFormat::createDateInstance((DateFormat::EStyle)itemPtr->style, locale):
4126 new SimpleDateFormat(customPatterns[-itemPtr->style - 1], locale, status);
4127 if ( dmft != NULL ) {
4128 if (U_SUCCESS(status)) {
4129 const ChineseCalTestDate * datePtr = dates;
4130 int32_t idate;
4131 for (idate = 0; idate < NUM_TEST_DATES; idate++, datePtr++) {
4132 rootChineseCalendar->clear();
4133 rootChineseCalendar->set(UCAL_ERA, datePtr->era);
4134 rootChineseCalendar->set(datePtr->year, datePtr->month-1, datePtr->day);
4135 rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, datePtr->isLeapMonth);
4136 UnicodeString result;
4137 FieldPosition fpos(FieldPosition::DONT_CARE);
4138 dmft->format(*rootChineseCalendar, result, fpos);
4139 if ( result.compare(itemPtr->dateString[idate]) != 0 ) {
4140 errln( UnicodeString("FAIL: Chinese calendar format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4141 ", expected \"" + itemPtr->dateString[idate] + "\", got \"" + result + "\"");
4142 } else {
4143 // formatted OK, try parse
4144 ParsePosition ppos(0);
4145 // ensure we are really parsing the fields we should be
4146 rootChineseCalendar->set(UCAL_YEAR, 1);
4147 rootChineseCalendar->set(UCAL_MONTH, 0);
4148 rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, 0);
4149 rootChineseCalendar->set(UCAL_DATE, 1);
4150 //
4151 dmft->parse(result, *rootChineseCalendar, ppos);
4152 int32_t year = rootChineseCalendar->get(UCAL_YEAR, status);
4153 int32_t month = rootChineseCalendar->get(UCAL_MONTH, status) + 1;
4154 int32_t isLeapMonth = rootChineseCalendar->get(UCAL_IS_LEAP_MONTH, status);
4155 int32_t day = rootChineseCalendar->get(UCAL_DATE, status);
4156 if ( ppos.getIndex() < result.length() || year != datePtr->year || month != datePtr->month || isLeapMonth != datePtr->isLeapMonth || day != datePtr->day ) {
4157 errln( UnicodeString("FAIL: Chinese calendar parse for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4158 ", string \"" + result + "\", expected " + datePtr->year +"-"+datePtr->month+"("+datePtr->isLeapMonth+")-"+datePtr->day + ", got pos " +
4159 ppos.getIndex() + " " + year +"-"+month+"("+isLeapMonth+")-"+day);
4160 }
4161 }
4162 }
4163 } else {
4164 dataerrln("Error creating SimpleDateFormat for Chinese calendar- %s", u_errorName(status));
4165 }
4166 delete dmft;
4167 } else {
4168 dataerrln("FAIL: Unable to create DateFormat for Chinese calendar- %s", u_errorName(status));
4169 }
4170 }
4171 delete rootChineseCalendar;
4172 } else {
4173 errln(UnicodeString("FAIL: Unable to create Calendar for root@calendar=chinese"));
4174 }
4175 }
4176
4177 typedef struct {
4178 const char * locale;
4179 UnicodeString pattern;
4180 UDisplayContext capitalizationContext;
4181 UnicodeString expectedFormat;
4182 } TestContextItem;
4183
4184 void DateFormatTest::TestContext()
4185 {
4186 const UDate july022008 = 1215000001979.0;
4187 const TestContextItem items[] = {
4188 //locale pattern capitalizationContext expected formatted date
4189 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_NONE, UnicodeString("juillet 2008") },
4190 #if !UCONFIG_NO_BREAK_ITERATION
4191 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UnicodeString("juillet 2008") },
4192 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, UnicodeString("Juillet 2008") },
4193 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, UnicodeString("juillet 2008") },
4194 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE, UnicodeString("Juillet 2008") },
4195 #endif
4196 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_NONE, CharsToUnicodeString("\\u010Dervenec 2008") },
4197 #if !UCONFIG_NO_BREAK_ITERATION
4198 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, CharsToUnicodeString("\\u010Dervenec 2008") },
4199 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, CharsToUnicodeString("\\u010Cervenec 2008") },
4200 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, CharsToUnicodeString("\\u010Cervenec 2008") },
4201 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE, CharsToUnicodeString("\\u010Dervenec 2008") },
4202 #endif
4203 // terminator
4204 { NULL, UnicodeString(""), (UDisplayContext)0, UnicodeString("") }
4205 };
4206 UErrorCode status = U_ZERO_ERROR;
4207 Calendar* cal = Calendar::createInstance(status);
4208 if (U_FAILURE(status)) {
4209 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4210 } else {
4211 cal->setTime(july022008, status);
4212 const TestContextItem * itemPtr;
4213 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4214 Locale locale = Locale::createFromName(itemPtr->locale);
4215 status = U_ZERO_ERROR;
4216 SimpleDateFormat * sdmft = new SimpleDateFormat(itemPtr->pattern, locale, status);
4217 if (U_FAILURE(status)) {
4218 dataerrln(UnicodeString("FAIL: Unable to create SimpleDateFormat for specified pattern with locale ") + UnicodeString(itemPtr->locale));
4219 } else {
4220 sdmft->setContext(itemPtr->capitalizationContext, status);
4221 UnicodeString result;
4222 FieldPosition pos(FieldPosition::DONT_CARE);
4223 sdmft->format(*cal, result, pos);
4224 if (result.compare(itemPtr->expectedFormat) != 0) {
4225 errln(UnicodeString("FAIL: format for locale ") + UnicodeString(itemPtr->locale) +
4226 ", status " + (int)status +
4227 ", capitalizationContext " + (int)itemPtr->capitalizationContext +
4228 ", expected " + itemPtr->expectedFormat + ", got " + result);
4229 }
4230 }
4231 if (sdmft) {
4232 delete sdmft;
4233 }
4234 }
4235 }
4236 if (cal) {
4237 delete cal;
4238 }
4239 }
4240
4241 // test item for a particular locale + calendar and date format
4242 typedef struct {
4243 int32_t era;
4244 int32_t year;
4245 int32_t month;
4246 int32_t day;
4247 int32_t hour;
4248 int32_t minute;
4249 UnicodeString formattedDate;
4250 } CalAndFmtTestItem;
4251
4252 // test item giving locale + calendar, date format, and CalAndFmtTestItems
4253 typedef struct {
4254 const char * locale; // with calendar
4255 DateFormat::EStyle style;
4256 UnicodeString pattern; // ignored unless style == DateFormat::kNone
4257 const CalAndFmtTestItem *caftItems;
4258 } TestNonGregoItem;
4259
4260 void DateFormatTest::TestNonGregoFmtParse()
4261 {
4262 // test items for he@calendar=hebrew, long date format
4263 const CalAndFmtTestItem cafti_he_hebrew_long[] = {
4264 { 0, 4999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05D3\\u05F3\\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4265 { 0, 5100, 0, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05E7\\u05F3") },
4266 { 0, 5774, 5, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05D0\\u05D3\\u05E8 \\u05D0\\u05F3 \\u05EA\\u05E9\\u05E2\\u05F4\\u05D3") },
4267 { 0, 5999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4268 { 0, 6100, 0, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05D5\\u05F3\\u05E7\\u05F3") },
4269 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4270 };
4271 const CalAndFmtTestItem cafti_zh_chinese_custU[] = {
4272 { 78, 31, 0, 1, 12, 0, CharsToUnicodeString("2014\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4273 { 77, 31, 0, 1, 12, 0, CharsToUnicodeString("1954\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4274 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4275 };
4276 const CalAndFmtTestItem cafti_zh_chinese_custNoU[] = {
4277 { 78, 31, 0, 1, 12, 0, CharsToUnicodeString("2014\\u5E74\\u6B63\\u67081") },
4278 { 77, 31, 0, 1, 12, 0, CharsToUnicodeString("1954\\u5E74\\u6B63\\u67081") },
4279 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4280 };
4281 const CalAndFmtTestItem cafti_ja_japanese_custGy[] = {
4282 {235, 26, 2, 5, 12, 0, CharsToUnicodeString("2014(\\u5E73\\u621026)\\u5E743\\u67085\\u65E5") },
4283 {234, 60, 2, 5, 12, 0, CharsToUnicodeString("1985(\\u662D\\u548C60)\\u5E743\\u67085\\u65E5") },
4284 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4285 };
4286 const CalAndFmtTestItem cafti_ja_japanese_custNoGy[] = {
4287 {235, 26, 2, 5, 12, 0, CharsToUnicodeString("2014\\u5E743\\u67085\\u65E5") },
4288 {234, 60, 2, 5, 12, 0, CharsToUnicodeString("1985\\u5E743\\u67085\\u65E5") },
4289 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4290 };
4291 const CalAndFmtTestItem cafti_en_islamic_cust[] = {
4292 { 0, 1384, 0, 1, 12, 0, UnicodeString("1 Muh. 1384 AH, 1964") },
4293 { 0, 1436, 0, 1, 12, 0, UnicodeString("1 Muh. 1436 AH, 2014") },
4294 { 0, 1487, 0, 1, 12, 0, UnicodeString("1 Muh. 1487 AH, 2064") },
4295 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4296 };
4297 // overal test items
4298 const TestNonGregoItem items[] = {
4299 { "he@calendar=hebrew", DateFormat::kLong, UnicodeString(""), cafti_he_hebrew_long },
4300 { "zh@calendar=chinese", DateFormat::kNone, CharsToUnicodeString("rU\\u5E74MMMd"), cafti_zh_chinese_custU },
4301 { "zh@calendar=chinese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74MMMd"), cafti_zh_chinese_custNoU },
4302 { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r(Gy)\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custGy },
4303 { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custNoGy },
4304 { "en@calendar=islamic", DateFormat::kNone, UnicodeString("d MMM y G, r"), cafti_en_islamic_cust },
4305 { NULL, DateFormat::kNone, UnicodeString(""), NULL } // terminator
4306 };
4307 const TestNonGregoItem * itemPtr;
4308 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++) {
4309 Locale locale = Locale::createFromName(itemPtr->locale);
4310 DateFormat * dfmt = NULL;
4311 UErrorCode status = U_ZERO_ERROR;
4312 if (itemPtr->style != DateFormat::kNone) {
4313 dfmt = DateFormat::createDateInstance(itemPtr->style, locale);
4314 } else {
4315 dfmt = new SimpleDateFormat(itemPtr->pattern, locale, status);
4316 }
4317 if (U_FAILURE(status)) {
4318 dataerrln("new SimpleDateFormat fails for locale %s", itemPtr->locale);
4319 } else if (dfmt == NULL) {
4320 dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->locale);
4321 } else {
4322 Calendar * cal = (dfmt->getCalendar())->clone();
4323 if (cal == NULL) {
4324 dataerrln("(DateFormat::getCalendar)->clone() fails for locale %s", itemPtr->locale);
4325 } else {
4326 const CalAndFmtTestItem * caftItemPtr;
4327 for (caftItemPtr = itemPtr->caftItems; caftItemPtr->year != 0; caftItemPtr++) {
4328 cal->clear();
4329 cal->set(UCAL_ERA, caftItemPtr->era);
4330 cal->set(UCAL_YEAR, caftItemPtr->year);
4331 cal->set(UCAL_MONTH, caftItemPtr->month);
4332 cal->set(UCAL_DATE, caftItemPtr->day);
4333 cal->set(UCAL_HOUR_OF_DAY, caftItemPtr->hour);
4334 cal->set(UCAL_MINUTE, caftItemPtr->minute);
4335 UnicodeString result;
4336 FieldPosition fpos(FieldPosition::DONT_CARE);
4337 dfmt->format(*cal, result, fpos);
4338 if ( result.compare(caftItemPtr->formattedDate) != 0 ) {
4339 errln( UnicodeString("FAIL: date format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4340 ", expected \"" + caftItemPtr->formattedDate + "\", got \"" + result + "\"");
4341 } else {
4342 // formatted OK, try parse
4343 ParsePosition ppos(0);
4344 dfmt->parse(result, *cal, ppos);
4345 status = U_ZERO_ERROR;
4346 int32_t era = cal->get(UCAL_ERA, status);
4347 int32_t year = cal->get(UCAL_YEAR, status);
4348 int32_t month = cal->get(UCAL_MONTH, status);
4349 int32_t day = cal->get(UCAL_DATE, status);
4350 if ( U_FAILURE(status) || ppos.getIndex() < result.length() || era != caftItemPtr->era ||
4351 year != caftItemPtr->year || month != caftItemPtr->month || day != caftItemPtr->day ) {
4352 errln( UnicodeString("FAIL: date parse for locale ") + UnicodeString(itemPtr->locale) +
4353 ", style " + itemPtr->style + ", string \"" + result + "\", expected " +
4354 caftItemPtr->era +":"+caftItemPtr->year +"-"+caftItemPtr->month+"-"+caftItemPtr->day + ", got pos " +
4355 ppos.getIndex() + " " + year +"-"+month+"-"+day + " status " + UnicodeString(u_errorName(status)) );
4356 }
4357 }
4358 }
4359 delete cal;
4360 }
4361 delete dfmt;
4362 }
4363 }
4364 }
4365
4366 typedef struct {
4367 const char* localeID;
4368 DateFormat::EStyle style;
4369 UnicodeString expectPattern;
4370 UnicodeString expectFormat;
4371 } TestFmtWithNumSysItem;
4372 enum { kBBufMax = 128 };
4373 void DateFormatTest::TestFormatsWithNumberSystems()
4374 {
4375 LocalPointer<TimeZone> zone(TimeZone::createTimeZone(UnicodeString("UTC")));
4376 const UDate date = 1451556000000.0; // for UTC: grego 31-Dec-2015 10 AM, hebrew 19 tevet 5776, chinese yi-wei 11mo 21day
4377 const TestFmtWithNumSysItem items[] = {
4378 { "haw@calendar=gregorian", DateFormat::kShort, UnicodeString("d/M/yy"), UnicodeString("31/xii/15") },
4379 { "he@calendar=hebrew", DateFormat::kLong, CharsToUnicodeString("d \\u05D1MMMM y"), CharsToUnicodeString("\\u05D9\\u05F4\\u05D8 \\u05D1\\u05D8\\u05D1\\u05EA \\u05EA\\u05E9\\u05E2\\u05F4\\u05D5") }, // "י״ט בטבת תשע״ו"
4380 { "zh@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u51AC\\u6708\\u5EFF\\u4E00") }, // "2015乙未年冬月廿一"
4381 { "zh_Hant@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u51AC\\u6708\\u5EFF\\u4E00") }, // "2015乙未年冬月廿一"
4382 { "ja@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("U\\u5E74MMMd\\u65E5"), CharsToUnicodeString("\\u4E59\\u672A\\u5E74\\u5341\\u4E00\\u6708\\u4E8C\\u5341\\u4E00\\u65E5") }, // "乙未年十一月二十一日"
4383 { NULL, DateFormat::kNone, UnicodeString(""), UnicodeString("") },
4384 };
4385 const TestFmtWithNumSysItem * itemPtr;
4386 for (itemPtr = items; itemPtr->localeID != NULL; itemPtr++) {
4387 char bExpected[kBBufMax];
4388 char bResult[kBBufMax];
4389 UErrorCode status = U_ZERO_ERROR;
4390 Locale locale = Locale::createFromName(itemPtr->localeID);
4391 LocalPointer<Calendar> cal(Calendar::createInstance(zone.orphan(), locale, status));
4392 if (U_FAILURE(status)) {
4393 dataerrln("Calendar::createInstance fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4394 continue;
4395 }
4396 cal->setTime(date, status);
4397 if (U_FAILURE(status)) {
4398 dataerrln("Calendar::setTime fails for locale %s, date %.1f, status %s", itemPtr->localeID, date, u_errorName(status));
4399 continue;
4400 }
4401 LocalPointer<SimpleDateFormat> sdfmt(static_cast<SimpleDateFormat *>(DateFormat::createDateInstance(itemPtr->style, locale)));
4402 if (sdfmt.isNull()) {
4403 dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->localeID);
4404 continue;
4405 }
4406 UnicodeString getFormat;
4407 sdfmt->format(*(cal.getAlias()), getFormat, NULL, status);
4408 if (U_FAILURE(status)) {
4409 errln("DateFormat::format fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4410 continue;
4411 }
4412 if (getFormat.compare(itemPtr->expectFormat) != 0) {
4413 itemPtr->expectFormat.extract(0, itemPtr->expectFormat.length(), bExpected, kBBufMax);
4414 getFormat.extract(0, getFormat.length(), bResult, kBBufMax);
4415 errln("DateFormat::format for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4416 }
4417 UnicodeString getPattern;
4418 sdfmt->toPattern(getPattern);
4419 if (getPattern.compare(itemPtr->expectPattern) != 0) {
4420 itemPtr->expectPattern.extract(0, itemPtr->expectPattern.length(), bExpected, kBBufMax);
4421 getPattern.extract(0, getPattern.length(), bResult, kBBufMax);
4422 errln("DateFormat::toPattern() for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4423 }
4424 }
4425 }
4426
4427 static const UDate TEST_DATE = 1326585600000.; // 2012-jan-15
4428
4429 void DateFormatTest::TestDotAndAtLeniency() {
4430 // Test for date/time parsing regression with CLDR 22.1/ICU 50 pattern strings.
4431 // For details see http://bugs.icu-project.org/trac/ticket/9789
4432 static const char *locales[] = { "en", "fr" };
4433 for (int32_t i = 0; i < UPRV_LENGTHOF(locales); ++i) {
4434 Locale locale(locales[i]);
4435
4436 for (DateFormat::EStyle dateStyle = DateFormat::FULL; dateStyle <= DateFormat::SHORT;
4437 dateStyle = static_cast<DateFormat::EStyle>(dateStyle + 1)) {
4438 LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance(dateStyle, locale));
4439
4440 for (DateFormat::EStyle timeStyle = DateFormat::FULL; timeStyle <= DateFormat::SHORT;
4441 timeStyle = static_cast<DateFormat::EStyle>(timeStyle + 1)) {
4442 LocalPointer<DateFormat> format(DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale));
4443 LocalPointer<DateFormat> timeFormat(DateFormat::createTimeInstance(timeStyle, locale));
4444 UnicodeString formattedString;
4445 if (format.isNull()) {
4446 dataerrln("Unable to create DateFormat");
4447 continue;
4448 }
4449 format->format(TEST_DATE, formattedString);
4450
4451 if (!showParse(*format, formattedString)) {
4452 errln(UnicodeString(" with date-time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4453 }
4454
4455 UnicodeString ds, ts;
4456 formattedString = dateFormat->format(TEST_DATE, ds) + " " + timeFormat->format(TEST_DATE, ts);
4457 if (!showParse(*format, formattedString)) {
4458 errln(UnicodeString(" with date sp sp time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4459 }
4460 if (formattedString.indexOf("n ") >= 0) { // will add "." after the end of text ending in 'n', like Jan.
4461 UnicodeString plusDot(formattedString);
4462 plusDot.findAndReplace("n ", "n. ").append(".");
4463 if (!showParse(*format, plusDot)) {
4464 errln(UnicodeString(" with date plus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4465 }
4466 }
4467 if (formattedString.indexOf(". ") >= 0) { // will subtract "." at the end of strings.
4468 UnicodeString minusDot(formattedString);
4469 minusDot.findAndReplace(". ", " ");
4470 if (!showParse(*format, minusDot)) {
4471 errln(UnicodeString(" with date minus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4472 }
4473 }
4474 }
4475 }
4476 }
4477 }
4478
4479 UBool DateFormatTest::showParse(DateFormat &format, const UnicodeString &formattedString) {
4480 ParsePosition parsePosition;
4481 UDate parsed = format.parse(formattedString, parsePosition);
4482 UBool ok = TEST_DATE == parsed && parsePosition.getIndex() == formattedString.length();
4483 UnicodeString pattern;
4484 static_cast<SimpleDateFormat &>(format).toPattern(pattern);
4485 if (ok) {
4486 logln(pattern + " parsed: " + formattedString);
4487 } else {
4488 errln(pattern + " fails to parse: " + formattedString);
4489 }
4490 return ok;
4491 }
4492
4493
4494 typedef struct {
4495 const char * locale;
4496 UBool leniency;
4497 UnicodeString parseString;
4498 UnicodeString pattern;
4499 UnicodeString expectedResult; // empty string indicates expected error
4500 } TestDateFormatLeniencyItem;
4501
4502 void DateFormatTest::TestDateFormatLeniency() {
4503 // For details see http://bugs.icu-project.org/trac/ticket/10261
4504
4505 const UDate july022008 = 1215000001979.0;
4506 const TestDateFormatLeniencyItem items[] = {
4507 //locale leniency parse String pattern expected result
4508 { "en", true, UnicodeString("2008-07 02"), UnicodeString("yyyy-LLLL dd"), UnicodeString("2008-July 02") },
4509 { "en", false, UnicodeString("2008-07 02"), UnicodeString("yyyy-LLLL dd"), UnicodeString("") },
4510 { "en", true, UnicodeString("2008-Jan 02"), UnicodeString("yyyy-LLL. dd"), UnicodeString("2008-Jan. 02") },
4511 { "en", false, UnicodeString("2008-Jan 02"), UnicodeString("yyyy-LLL. dd"), UnicodeString("") },
4512 { "en", true, UnicodeString("2008-Jan--02"), UnicodeString("yyyy-MMM' -- 'dd"), UnicodeString("2008-Jan -- 02") },
4513 { "en", false, UnicodeString("2008-Jan--02"), UnicodeString("yyyy-MMM' -- 'dd"), UnicodeString("") },
4514 // terminator
4515 { NULL, true, UnicodeString(""), UnicodeString(""), UnicodeString("") }
4516 };
4517 UErrorCode status = U_ZERO_ERROR;
4518 LocalPointer<Calendar> cal(Calendar::createInstance(status));
4519 if (U_FAILURE(status)) {
4520 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4521 return;
4522 }
4523 cal->setTime(july022008, status);
4524 const TestDateFormatLeniencyItem * itemPtr;
4525 LocalPointer<SimpleDateFormat> sdmft;
4526 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4527
4528 Locale locale = Locale::createFromName(itemPtr->locale);
4529 status = U_ZERO_ERROR;
4530 ParsePosition pos(0);
4531 sdmft.adoptInsteadAndCheckErrorCode(new SimpleDateFormat(itemPtr->pattern, locale, status), status);
4532 if (U_FAILURE(status)) {
4533 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4534 continue;
4535 }
4536 sdmft->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->leniency, status).
4537 setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->leniency, status).
4538 setBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, itemPtr->leniency, status);
4539 UDate d = sdmft->parse(itemPtr->parseString, pos);
4540
4541 if(itemPtr->expectedResult.length() == 0) {
4542 if(pos.getErrorIndex() != -1) {
4543 continue;
4544 } else {
4545 errln("error: unexpected parse success - " + itemPtr->parseString +
4546 " - pattern " + itemPtr->pattern +
4547 " - error index " + pos.getErrorIndex() +
4548 " - leniency " + itemPtr->leniency);
4549 continue;
4550 }
4551 }
4552 if(pos.getErrorIndex() != -1) {
4553 errln("error: parse error for string - " + itemPtr->parseString +
4554 " - pattern " + itemPtr->pattern +
4555 " - idx " + pos.getIndex() +
4556 " - error index "+pos.getErrorIndex() +
4557 " - leniency " + itemPtr->leniency);
4558 continue;
4559 }
4560
4561 UnicodeString formatResult("");
4562 sdmft->format(d, formatResult);
4563 if(formatResult.compare(itemPtr->expectedResult) != 0) {
4564 errln("error: unexpected format result. pattern["+itemPtr->pattern+"] expected[" + itemPtr->expectedResult + "] but result was[" + formatResult + "]");
4565 continue;
4566 } else {
4567 logln("formatted results match! - " + formatResult);
4568 }
4569
4570 }
4571 }
4572
4573
4574 typedef struct {
4575 UBool leniency;
4576 UnicodeString parseString;
4577 UnicodeString pattern;
4578 UnicodeString expectedResult; // empty string indicates expected error
4579 } TestMultiPatternMatchItem;
4580
4581 void DateFormatTest::TestParseMultiPatternMatch() {
4582 // For details see http://bugs.icu-project.org/trac/ticket/10336
4583 const TestMultiPatternMatchItem items[] = {
4584 // leniency parse String pattern expected result
4585 {true, UnicodeString("2013-Sep 13"), UnicodeString("yyyy-MMM dd"), UnicodeString("2013-Sep 13")},
4586 {true, UnicodeString("2013-September 14"), UnicodeString("yyyy-MMM dd"), UnicodeString("2013-Sep 14")},
4587 {false, UnicodeString("2013-September 15"), UnicodeString("yyyy-MMM dd"), UnicodeString("")},
4588 {false, UnicodeString("2013-September 16"), UnicodeString("yyyy-MMMM dd"), UnicodeString("2013-September 16")},
4589 {true, UnicodeString("2013-Sep 17"), UnicodeString("yyyy-LLL dd"), UnicodeString("2013-Sep 17")},
4590 {true, UnicodeString("2013-September 18"), UnicodeString("yyyy-LLL dd"), UnicodeString("2013-Sep 18")},
4591 {false, UnicodeString("2013-September 19"), UnicodeString("yyyy-LLL dd"), UnicodeString("")},
4592 {false, UnicodeString("2013-September 20"), UnicodeString("yyyy-LLLL dd"), UnicodeString("2013-September 20")},
4593 {true, UnicodeString("2013 Sat Sep 21"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("2013 Sat Sep 21")},
4594 {true, UnicodeString("2013 Sunday Sep 22"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("2013 Sun Sep 22")},
4595 {false, UnicodeString("2013 Monday Sep 23"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("")},
4596 {false, UnicodeString("2013 Tuesday Sep 24"), UnicodeString("yyyy EEEE MMM dd"), UnicodeString("2013 Tuesday Sep 24")},
4597 {true, UnicodeString("2013 Wed Sep 25"), UnicodeString("yyyy eee MMM dd"), UnicodeString("2013 Wed Sep 25")},
4598 {true, UnicodeString("2013 Thu Sep 26"), UnicodeString("yyyy eee MMM dd"), UnicodeString("2013 Thu Sep 26")},
4599 {false, UnicodeString("2013 Friday Sep 27"), UnicodeString("yyyy eee MMM dd"), UnicodeString("")},
4600 {false, UnicodeString("2013 Saturday Sep 28"), UnicodeString("yyyy eeee MMM dd"), UnicodeString("2013 Saturday Sep 28")},
4601 {true, UnicodeString("2013 Sun Sep 29"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("2013 Sun Sep 29")},
4602 {true, UnicodeString("2013 Monday Sep 30"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("2013 Mon Sep 30")},
4603 {false, UnicodeString("2013 Sunday Oct 13"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("")},
4604 {false, UnicodeString("2013 Monday Oct 14"), UnicodeString("yyyy cccc MMM dd"), UnicodeString("2013 Monday Oct 14")},
4605 {true, UnicodeString("2013 Oct 15 Q4"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 15 Q4")},
4606 {true, UnicodeString("2013 Oct 16 4th quarter"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 16 Q4")},
4607 {false, UnicodeString("2013 Oct 17 4th quarter"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("")},
4608 {false, UnicodeString("2013 Oct 18 Q4"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 18 Q4")},
4609 {true, UnicodeString("2013 Oct 19 Q4"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 19 4th quarter")},
4610 {true, UnicodeString("2013 Oct 20 4th quarter"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 20 4th quarter")},
4611 {false, UnicodeString("2013 Oct 21 Q4"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("")},
4612 {false, UnicodeString("2013 Oct 22 4th quarter"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 22 4th quarter")},
4613 {false, UnicodeString("--end--"), UnicodeString(""), UnicodeString("")},
4614 };
4615
4616 UErrorCode status = U_ZERO_ERROR;
4617 LocalPointer<Calendar> cal(Calendar::createInstance(status));
4618 if (U_FAILURE(status)) {
4619 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4620 return;
4621 }
4622 const TestMultiPatternMatchItem * itemPtr;
4623 DateFormat* sdmft = DateFormat::createDateInstance();
4624 if (sdmft == NULL) {
4625 dataerrln(UnicodeString("FAIL: Unable to create DateFormat"));
4626 return;
4627 }
4628 for (itemPtr = items; itemPtr->parseString != "--end--"; itemPtr++ ) {
4629 status = U_ZERO_ERROR;
4630 ParsePosition pos(0);
4631 ((SimpleDateFormat*) sdmft)->applyPattern(itemPtr->pattern);
4632 if (U_FAILURE(status)) {
4633 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4634 continue;
4635 }
4636 sdmft->setBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, itemPtr->leniency, status);
4637 UDate d = sdmft->parse(itemPtr->parseString, pos);
4638
4639 if(itemPtr->expectedResult.length() == 0) {
4640 if(pos.getErrorIndex() != -1) {
4641 continue;
4642 } else {
4643 errln("error: unexpected parse success - " + itemPtr->parseString +
4644 " - error index " + pos.getErrorIndex() +
4645 " - leniency " + itemPtr->leniency);
4646 continue;
4647 }
4648 }
4649 if(pos.getErrorIndex() != -1) {
4650 errln("error: parse error for string - " +itemPtr->parseString + " -- idx["+pos.getIndex()+"] errIdx["+pos.getErrorIndex()+"]");
4651 continue;
4652 }
4653
4654 UnicodeString formatResult("");
4655 sdmft->format(d, formatResult);
4656 if(formatResult.compare(itemPtr->expectedResult) != 0) {
4657 errln("error: unexpected format result. expected[" + itemPtr->expectedResult + "] but result was[" + formatResult + "]");
4658 } else {
4659 logln("formatted results match! - " + formatResult);
4660 }
4661 }
4662 delete sdmft;
4663 }
4664
4665 void DateFormatTest::TestParseLeniencyAPIs() {
4666 UErrorCode status = U_ZERO_ERROR;
4667 LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance());
4668 DateFormat *fmt = dateFormat.getAlias();
4669 if (fmt == NULL) {
4670 dataerrln("Failed calling dateFormat.getAlias()");
4671 return;
4672 }
4673
4674 assertTrue("isLenient default", fmt->isLenient());
4675 assertTrue("isCalendarLenient default", fmt->isCalendarLenient());
4676 assertTrue("ALLOW_WHITESPACE default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4677 assertTrue("ALLOW_NUMERIC default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4678 assertTrue("PARTIAL_MATCH default", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4679 assertTrue("MULTIPLE_PATTERNS default", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4680
4681 // Set calendar to strict
4682 fmt->setCalendarLenient(FALSE);
4683
4684 assertFalse("isLeninent after setCalendarLenient(FALSE)", fmt->isLenient());
4685 assertFalse("isCalendarLenient after setCalendarLenient(FALSE)", fmt->isCalendarLenient());
4686 assertTrue("ALLOW_WHITESPACE after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4687 assertTrue("ALLOW_NUMERIC after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4688
4689 // Set to strict
4690 fmt->setLenient(FALSE);
4691
4692 assertFalse("isLeninent after setLenient(FALSE)", fmt->isLenient());
4693 assertFalse("isCalendarLenient after setLenient(FALSE)", fmt->isCalendarLenient());
4694 assertFalse("ALLOW_WHITESPACE after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4695 assertFalse("ALLOW_NUMERIC after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4696 // These two boolean attributes are NOT affected according to the API specification
4697 assertTrue("PARTIAL_MATCH after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4698 assertTrue("MULTIPLE_PATTERNS after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4699
4700 // Allow white space leniency
4701 fmt->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, TRUE, status);
4702
4703 assertFalse("isLeninent after ALLOW_WHITESPACE/TRUE", fmt->isLenient());
4704 assertFalse("isCalendarLenient after ALLOW_WHITESPACE/TRUE", fmt->isCalendarLenient());
4705 assertTrue("ALLOW_WHITESPACE after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4706 assertFalse("ALLOW_NUMERIC after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4707
4708 // Set to lenient
4709 fmt->setLenient(TRUE);
4710
4711 assertTrue("isLenient after setLenient(TRUE)", fmt->isLenient());
4712 assertTrue("isCalendarLenient after setLenient(TRUE)", fmt->isCalendarLenient());
4713 assertTrue("ALLOW_WHITESPACE after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4714 assertTrue("ALLOW_NUMERIC after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4715 }
4716
4717 void DateFormatTest::TestNumberFormatOverride() {
4718 UErrorCode status = U_ZERO_ERROR;
4719 UnicodeString fields = (UnicodeString) "M";
4720
4721 LocalPointer<SimpleDateFormat> fmt;
4722 fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4723 if (!assertSuccess("SimpleDateFormat with pattern MM d", status)) {
4724 return;
4725 }
4726
4727
4728 for(int i=0; i<3; i++){
4729 NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4730 assertSuccess("NumberFormat en_US", status);
4731 fmt->adoptNumberFormat(fields, check_nf, status);
4732 assertSuccess("adoptNumberFormat check_nf", status);
4733
4734 const NumberFormat* get_nf = fmt->getNumberFormatForField((UChar)0x004D /*'M'*/);
4735 if (get_nf != check_nf) errln("FAIL: getter and setter do not work");
4736 }
4737 NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4738 assertSuccess("NumberFormat en_US", status);
4739 fmt->adoptNumberFormat(check_nf); // make sure using the same NF will not crash
4740
4741 const char * DATA [][2] = {
4742 { "", "\\u521D\\u516D \\u5341\\u4E94"},
4743 { "M", "\\u521D\\u516D 15"},
4744 { "Mo", "\\u521D\\u516D 15"},
4745 { "Md", "\\u521D\\u516D \\u5341\\u4E94"},
4746 { "MdMMd", "\\u521D\\u516D \\u5341\\u4E94"},
4747 { "mixed", "\\u521D\\u516D \\u5341\\u4E94"}
4748 };
4749
4750 UDate test_date = date(97, 6 - 1, 15);
4751
4752 for(int i=0; i < UPRV_LENGTHOF(DATA); i++){
4753 fields = DATA[i][0];
4754
4755 LocalPointer<SimpleDateFormat> fmt;
4756 fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4757 assertSuccess("SimpleDateFormat with pattern MM d", status);
4758 NumberFormat* overrideNF = NumberFormat::createInstance(Locale::createFromName("zh@numbers=hanidays"),status);
4759 assertSuccess("NumberFormat zh@numbers=hanidays", status);
4760
4761 if (fields == (UnicodeString) "") { // use the one w/o fields
4762 fmt->adoptNumberFormat(overrideNF);
4763 } else if (fields == (UnicodeString) "mixed") { // set 1 field at first but then full override, both(M & d) should be override
4764 NumberFormat* singleOverrideNF = NumberFormat::createInstance(Locale::createFromName("en@numbers=hebr"),status);
4765 assertSuccess("NumberFormat en@numbers=hebr", status);
4766
4767 fields = (UnicodeString) "M";
4768 fmt->adoptNumberFormat(fields, singleOverrideNF, status);
4769 assertSuccess("adoptNumberFormat singleOverrideNF", status);
4770
4771 fmt->adoptNumberFormat(overrideNF);
4772 } else if (fields == (UnicodeString) "Mo"){ // o is invlid field
4773 fmt->adoptNumberFormat(fields, overrideNF, status);
4774 if(status == U_INVALID_FORMAT_ERROR) {
4775 status = U_ZERO_ERROR;
4776 continue;
4777 }
4778 } else {
4779 fmt->adoptNumberFormat(fields, overrideNF, status);
4780 assertSuccess("adoptNumberFormat overrideNF", status);
4781 }
4782
4783 UnicodeString result;
4784 FieldPosition pos(FieldPosition::DONT_CARE);
4785 fmt->format(test_date,result, pos);
4786
4787 UnicodeString expected = ((UnicodeString)DATA[i][1]).unescape();;
4788
4789 if (result != expected)
4790 errln("FAIL: Expected " + expected + " get: " + result);
4791 }
4792 }
4793
4794 void DateFormatTest::TestCreateInstanceForSkeleton() {
4795 UErrorCode status = U_ZERO_ERROR;
4796 LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4797 "yMMMMd", "en", status));
4798 if (!assertSuccess("Create with pattern yMMMMd", status)) {
4799 return;
4800 }
4801 UnicodeString result;
4802 FieldPosition pos(FieldPosition::DONT_CARE);
4803 fmt->format(date(98, 5-1, 25), result, pos);
4804 assertEquals("format yMMMMd", "May 25, 1998", result);
4805 fmt.adoptInstead(DateFormat::createInstanceForSkeleton(
4806 "yMd", "en", status));
4807 if (!assertSuccess("Create with pattern yMd", status)) {
4808 return;
4809 }
4810 result.remove();
4811 fmt->format(date(98, 5-1, 25), result, pos);
4812 assertEquals("format yMd", "5/25/1998", result);
4813 }
4814
4815 void DateFormatTest::TestCreateInstanceForSkeletonDefault() {
4816 UErrorCode status = U_ZERO_ERROR;
4817 Locale savedLocale;
4818 Locale::setDefault(Locale::getUS(), status);
4819 LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4820 "yMMMd", status));
4821 Locale::setDefault(savedLocale, status);
4822 if (!assertSuccess("Create with pattern yMMMd", status)) {
4823 return;
4824 }
4825 UnicodeString result;
4826 FieldPosition pos(FieldPosition::DONT_CARE);
4827 fmt->format(date(98, 5-1, 25), result, pos);
4828 assertEquals("format yMMMd", "May 25, 1998", result);
4829 }
4830
4831 void DateFormatTest::TestCreateInstanceForSkeletonWithCalendar() {
4832 UErrorCode status = U_ZERO_ERROR;
4833 LocalPointer<DateFormat> fmt(
4834 DateFormat::createInstanceForSkeleton(
4835 Calendar::createInstance(
4836 TimeZone::createTimeZone("GMT-3:00"),
4837 status),
4838 "yMdHm", "en", status));
4839 if (!assertSuccess("Create with pattern yMMMMd", status)) {
4840 return;
4841 }
4842 UnicodeString result;
4843 FieldPosition pos(FieldPosition::DONT_CARE);
4844
4845 LocalPointer<Calendar> cal(Calendar::createInstance(
4846 TimeZone::createTimeZone("GMT-7:00"),
4847 status));
4848 if (!assertSuccess("Creating GMT-7 time zone failed", status)) {
4849 return;
4850 }
4851 cal->clear();
4852 cal->set(1998, 5-1, 25, 0, 0, 0);
4853
4854 // date format time zone should be 4 hours ahead.
4855 fmt->format(cal->getTime(status), result, pos);
4856 assertEquals("format yMdHm", "5/25/1998, 04:00", result);
4857 assertSuccess("", status);
4858 }
4859
4860 void DateFormatTest::TestDFSCreateForLocaleNonGregorianLocale() {
4861 UErrorCode status = U_ZERO_ERROR;
4862 Locale fa("fa");
4863 LocalPointer<DateFormatSymbols> sym(
4864 DateFormatSymbols::createForLocale(fa, status));
4865 if (!assertSuccess("", status)) {
4866 return;
4867 }
4868
4869 // Farsi should default to the persian calendar, not gregorian
4870 int32_t count;
4871 const UnicodeString *months = sym->getShortMonths(count);
4872
4873 // First persian month.
4874 UnicodeString expected("\\u0641\\u0631\\u0648\\u0631\\u062f\\u06cc\\u0646");
4875 assertEquals("", expected.unescape(), months[0]);
4876 }
4877
4878 void DateFormatTest::TestDFSCreateForLocaleWithCalendarInLocale() {
4879 UErrorCode status = U_ZERO_ERROR;
4880 Locale en_heb("en@calendar=hebrew");
4881 LocalPointer<DateFormatSymbols> sym(
4882 DateFormatSymbols::createForLocale(en_heb, status));
4883 if (!assertSuccess("", status)) {
4884 return;
4885 }
4886
4887 // We should get the months of the hebrew calendar, not the gregorian
4888 // calendar.
4889 int32_t count;
4890 const UnicodeString *months = sym->getShortMonths(count);
4891
4892 // First hebrew month.
4893 UnicodeString expected("Tishri");
4894 assertEquals("", expected, months[0]);
4895 }
4896
4897 void DateFormatTest::TestChangeCalendar() {
4898 UErrorCode status = U_ZERO_ERROR;
4899 Locale en("en");
4900 Locale en_heb("en@calendar=hebrew");
4901 LocalPointer<DateFormat> fmt(
4902 DateFormat::createInstanceForSkeleton("yMMMd", en, status));
4903 if (!assertSuccess("", status)) {
4904 return;
4905 }
4906 fmt->adoptCalendar(Calendar::createInstance(en_heb, status));
4907 if (!assertSuccess("", status)) {
4908 return;
4909 }
4910 UnicodeString result;
4911 FieldPosition pos(FieldPosition::DONT_CARE);
4912 fmt->format(date(98, 5-1, 25), result, pos);
4913 assertEquals("format yMMMd", "Iyar 29, 5758", result);
4914 }
4915
4916 void DateFormatTest::TestPatternFromSkeleton() {
4917 static const struct {
4918 const Locale& locale;
4919 const char* const skeleton;
4920 const char* const pattern;
4921 } TESTDATA[] = {
4922 // Ticket #11985
4923 {Locale::getEnglish(), "jjmm", "h:mm a"},
4924 {Locale::getEnglish(), "JJmm", "hh:mm"},
4925 {Locale::getGerman(), "jjmm", "HH:mm"},
4926 {Locale::getGerman(), "JJmm", "HH:mm"}
4927 };
4928
4929 for (size_t i = 0; i < UPRV_LENGTHOF(TESTDATA); i++) {
4930 UErrorCode status = U_ZERO_ERROR;
4931 LocalPointer<DateFormat> fmt(
4932 DateFormat::createInstanceForSkeleton(
4933 TESTDATA[i].skeleton, TESTDATA[i].locale, status));
4934 if (!assertSuccess("createInstanceForSkeleton", status)) {
4935 return;
4936 }
4937 UnicodeString pattern;
4938 static_cast<const SimpleDateFormat*>(fmt.getAlias())->toPattern(pattern);
4939 assertEquals("Format pattern", TESTDATA[i].pattern, pattern);
4940 }
4941 }
4942
4943 void DateFormatTest::TestAmPmMidnightNoon() {
4944 // Some times on 2015-11-13 (UTC+0).
4945 UDate k000000 = 1447372800000.0;
4946 UDate k000030 = 1447372830000.0;
4947 UDate k003000 = 1447374600000.0;
4948 UDate k060000 = 1447394400000.0;
4949 UDate k120000 = 1447416000000.0;
4950 UDate k180000 = 1447437600000.0;
4951
4952 UErrorCode errorCode = U_ZERO_ERROR;
4953 SimpleDateFormat sdf(UnicodeString(), errorCode);
4954 if (U_FAILURE(errorCode)) {
4955 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
4956 return;
4957 }
4958 const TimeZone *tz = TimeZone::getGMT();
4959 sdf.setTimeZone(*tz);
4960 UnicodeString out;
4961
4962 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
4963 // For ICU 57 output of "midnight" is temporarily suppressed.
4964
4965 // Short.
4966 sdf.applyPattern(UnicodeString("hh:mm:ss bbb"));
4967
4968 // assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4969 assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4970 assertEquals("hh:mm:ss bbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
4971 assertEquals("hh:mm:ss bbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
4972 assertEquals("hh:mm:ss bbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
4973 assertEquals("hh:mm:ss bbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
4974 assertEquals("hh:mm:ss bbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
4975
4976 sdf.applyPattern(UnicodeString("hh:mm bbb"));
4977
4978 // assertEquals("hh:mm bbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
4979 assertEquals("hh:mm bbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
4980 // assertEquals("hh:mm bbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
4981 assertEquals("hh:mm bbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
4982 assertEquals("hh:mm bbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
4983
4984 sdf.applyPattern(UnicodeString("hh bbb"));
4985
4986 // assertEquals("hh bbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
4987 assertEquals("hh bbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
4988 // assertEquals("hh bbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
4989 assertEquals("hh bbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
4990 // assertEquals("hh bbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
4991 assertEquals("hh bbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
4992
4993 // Wide.
4994 sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
4995
4996 // assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4997 assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4998 assertEquals("hh:mm:ss bbbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
4999 assertEquals("hh:mm:ss bbbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
5000 assertEquals("hh:mm:ss bbbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
5001 assertEquals("hh:mm:ss bbbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5002 assertEquals("hh:mm:ss bbbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
5003
5004 sdf.applyPattern(UnicodeString("hh:mm bbbb"));
5005
5006 // assertEquals("hh:mm bbbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5007 assertEquals("hh:mm bbbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
5008 // assertEquals("hh:mm bbbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5009 assertEquals("hh:mm bbbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
5010 assertEquals("hh:mm bbbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
5011
5012 sdf.applyPattern(UnicodeString("hh bbbb"));
5013
5014 // assertEquals("hh bbbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5015 assertEquals("hh bbbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
5016 // assertEquals("hh bbbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5017 assertEquals("hh bbbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
5018 // assertEquals("hh bbbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5019 assertEquals("hh bbbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
5020
5021 // Narrow.
5022 sdf.applyPattern(UnicodeString("hh:mm:ss bbbbb"));
5023
5024 // assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5025 assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 a", sdf.format(k000000, out.remove()));
5026 assertEquals("hh:mm:ss bbbbb | 00:00:30", "12:00:30 a", sdf.format(k000030, out.remove()));
5027 assertEquals("hh:mm:ss bbbbb | 00:30:00", "12:30:00 a", sdf.format(k003000, out.remove()));
5028 assertEquals("hh:mm:ss bbbbb | 06:00:00", "06:00:00 a", sdf.format(k060000, out.remove()));
5029 assertEquals("hh:mm:ss bbbbb | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5030 assertEquals("hh:mm:ss bbbbb | 18:00:00", "06:00:00 p", sdf.format(k180000, out.remove()));
5031
5032 sdf.applyPattern(UnicodeString("hh:mm bbbbb"));
5033
5034 // assertEquals("hh:mm bbbbb | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5035 assertEquals("hh:mm bbbbb | 00:00:00", "12:00 a", sdf.format(k000000, out.remove()));
5036 // assertEquals("hh:mm bbbbb | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5037 assertEquals("hh:mm bbbbb | 00:00:30", "12:00 a", sdf.format(k000030, out.remove()));
5038 assertEquals("hh:mm bbbbb | 00:30:00", "12:30 a", sdf.format(k003000, out.remove()));
5039
5040 sdf.applyPattern(UnicodeString("hh bbbbb"));
5041
5042 // assertEquals("hh bbbbb | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5043 assertEquals("hh bbbbb | 00:00:00", "12 a", sdf.format(k000000, out.remove()));
5044 // assertEquals("hh bbbbb | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5045 assertEquals("hh bbbbb | 00:00:30", "12 a", sdf.format(k000030, out.remove()));
5046 // assertEquals("hh bbbbb | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5047 assertEquals("hh bbbbb | 00:30:00", "12 a", sdf.format(k003000, out.remove()));
5048 }
5049
5050 void DateFormatTest::TestFlexibleDayPeriod() {
5051 // Some times on 2015-11-13 (UTC+0).
5052 UDate k000000 = 1447372800000.0;
5053 UDate k000030 = 1447372830000.0;
5054 UDate k003000 = 1447374600000.0;
5055 UDate k060000 = 1447394400000.0;
5056 UDate k120000 = 1447416000000.0;
5057 UDate k180000 = 1447437600000.0;
5058
5059 UErrorCode errorCode = U_ZERO_ERROR;
5060 SimpleDateFormat sdf(UnicodeString(), errorCode);
5061 if (U_FAILURE(errorCode)) {
5062 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5063 return;
5064 }
5065 const TimeZone *tz = TimeZone::getGMT();
5066 sdf.setTimeZone(*tz);
5067 UnicodeString out;
5068
5069 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5070 // For ICU 57 output of "midnight" is temporarily suppressed.
5071
5072 // Short.
5073 sdf.applyPattern(UnicodeString("hh:mm:ss BBB"));
5074
5075 // assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5076 assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5077 assertEquals("hh:mm:ss BBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5078 assertEquals("hh:mm:ss BBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5079 assertEquals("hh:mm:ss BBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5080 assertEquals("hh:mm:ss BBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5081 assertEquals("hh:mm:ss BBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5082
5083 sdf.applyPattern(UnicodeString("hh:mm BBB"));
5084
5085 // assertEquals("hh:mm BBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5086 assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5087 // assertEquals("hh:mm BBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5088 assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5089 assertEquals("hh:mm BBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5090
5091 sdf.applyPattern(UnicodeString("hh BBB"));
5092
5093 // assertEquals("hh BBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5094 assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5095 // assertEquals("hh BBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5096 assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5097 // assertEquals("hh BBB | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5098 assertEquals("hh BBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5099
5100 // Wide.
5101 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5102
5103 // assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5104 assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5105 assertEquals("hh:mm:ss BBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5106 assertEquals("hh:mm:ss BBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5107 assertEquals("hh:mm:ss BBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5108 assertEquals("hh:mm:ss BBBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5109 assertEquals("hh:mm:ss BBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5110
5111 sdf.applyPattern(UnicodeString("hh:mm BBBB"));
5112
5113 // assertEquals("hh:mm BBBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5114 assertEquals("hh:mm BBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5115 // assertEquals("hh:mm BBBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5116 assertEquals("hh:mm BBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5117 assertEquals("hh:mm BBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5118
5119 sdf.applyPattern(UnicodeString("hh BBBB"));
5120
5121 // assertEquals("hh BBBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5122 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5123 // assertEquals("hh BBBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5124 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5125 // assertEquals("hh BBBB | 00:80:00", "12 midnight", sdf.format(k003000, out.remove()));
5126 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5127
5128 // Narrow.
5129 sdf.applyPattern(UnicodeString("hh:mm:ss BBBBB"));
5130
5131 // assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5132 assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5133 assertEquals("hh:mm:ss BBBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5134 assertEquals("hh:mm:ss BBBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5135 assertEquals("hh:mm:ss BBBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5136 assertEquals("hh:mm:ss BBBBB | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5137 assertEquals("hh:mm:ss BBBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5138
5139 sdf.applyPattern(UnicodeString("hh:mm BBBBB"));
5140
5141 // assertEquals("hh:mm BBBBB | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5142 assertEquals("hh:mm BBBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5143 // assertEquals("hh:mm BBBBB | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5144 assertEquals("hh:mm BBBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5145 assertEquals("hh:mm BBBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5146
5147 sdf.applyPattern(UnicodeString("hh BBBBB"));
5148
5149 // assertEquals("hh BBBBB | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5150 assertEquals("hh BBBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5151 // assertEquals("hh BBBBB | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5152 assertEquals("hh BBBBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5153 // assertEquals("hh BBBBB | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5154 assertEquals("hh BBBBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5155 }
5156
5157 void DateFormatTest::TestDayPeriodWithLocales() {
5158 // Some times on 2015-11-13 (UTC+0).
5159 UDate k000000 = 1447372800000.0;
5160 UDate k010000 = 1447376400000.0;
5161 UDate k120000 = 1447416000000.0;
5162 UDate k220000 = 1447452000000.0;
5163
5164 UErrorCode errorCode = U_ZERO_ERROR;
5165 const TimeZone *tz = TimeZone::getGMT();
5166 UnicodeString out;
5167
5168 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5169 // For ICU 57 output of "midnight" and its localized equivalentns is temporarily suppressed.
5170
5171 // Locale de has a word for midnight, but not noon.
5172 SimpleDateFormat sdf(UnicodeString(), Locale::getGermany(), errorCode);
5173 if (U_FAILURE(errorCode)) {
5174 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5175 return;
5176 }
5177 sdf.setTimeZone(*tz);
5178
5179 sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
5180
5181 // assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 Mitternacht",
5182 // sdf.format(k000000, out.remove()));
5183 assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 AM" /* change for Apple data */,
5184 sdf.format(k000000, out.remove()));
5185 assertEquals("hh:mm:ss bbbb | 12:00:00 | de", "12:00:00 PM" /* change for Apple data */,
5186 sdf.format(k120000, out.remove()));
5187
5188 // Locale ee has a rule that wraps around midnight (21h - 4h).
5189 sdf = SimpleDateFormat(UnicodeString(), Locale("ee"), errorCode);
5190 sdf.setTimeZone(*tz);
5191
5192 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5193
5194 assertEquals("hh:mm:ss BBBB | 22:00:00 | ee", UnicodeString("10:00:00 z\\u00E3").unescape(),
5195 sdf.format(k220000, out.remove()));
5196 assertEquals("hh:mm:ss BBBB | 00:00:00 | ee", UnicodeString("12:00:00 z\\u00E3").unescape(),
5197 sdf.format(k000000, out.remove()));
5198 assertEquals("hh:mm:ss BBBB | 01:00:00 | ee", UnicodeString("01:00:00 z\\u00E3").unescape(),
5199 sdf.format(k010000, out.remove()));
5200
5201 // Locale root has rules for AM/PM only.
5202 sdf = SimpleDateFormat(UnicodeString(), Locale("root"), errorCode);
5203 sdf.setTimeZone(*tz);
5204
5205 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5206
5207 assertEquals("hh:mm:ss BBBB | 00:00:00 | root", "12:00:00 AM",
5208 sdf.format(k000000, out.remove()));
5209 assertEquals("hh:mm:ss BBBB | 12:00:00 | root", "12:00:00 PM",
5210 sdf.format(k120000, out.remove()));
5211
5212 // Empty string should behave exactly as root.
5213 sdf = SimpleDateFormat(UnicodeString(), Locale(""), errorCode);
5214 sdf.setTimeZone(*tz);
5215
5216 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5217
5218 assertEquals("hh:mm:ss BBBB | 00:00:00 | \"\" (root)", "12:00:00 AM",
5219 sdf.format(k000000, out.remove()));
5220 assertEquals("hh:mm:ss BBBB | 12:00:00 | \"\" (root)", "12:00:00 PM",
5221 sdf.format(k120000, out.remove()));
5222
5223 // Locale en_US should fall back to en.
5224 sdf = SimpleDateFormat(UnicodeString(), Locale("en_US"), errorCode);
5225 sdf.setTimeZone(*tz);
5226
5227 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5228
5229 // assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 midnight",
5230 // sdf.format(k000000, out.remove()));
5231 assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 at night",
5232 sdf.format(k000000, out.remove()));
5233 assertEquals("hh:mm:ss BBBB | 01:00:00 | en_US", "01:00:00 at night",
5234 sdf.format(k010000, out.remove()));
5235 assertEquals("hh:mm:ss BBBB | 12:00:00 | en_US", "12:00:00 noon",
5236 sdf.format(k120000, out.remove()));
5237
5238 // Locale es_CO should not fall back to es and should have a
5239 // different string for 1 in the morning.
5240 // (es_CO: "de la manana" (first n has a tilde) vs. es: "de la madrugada")
5241 sdf = SimpleDateFormat(UnicodeString(), Locale("es_CO"), errorCode);
5242 sdf.setTimeZone(*tz);
5243
5244 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5245 assertEquals("hh:mm:ss BBBB | 01:00:00 | es_CO", UnicodeString("01:00:00 de la ma\\u00F1ana").unescape(),
5246 sdf.format(k010000, out.remove()));
5247
5248 sdf = SimpleDateFormat(UnicodeString(), Locale("es"), errorCode);
5249 sdf.setTimeZone(*tz);
5250
5251 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5252 assertEquals("hh:mm:ss BBBB | 01:00:00 | es", "01:00:00 de la madrugada",
5253 sdf.format(k010000, out.remove()));
5254 }
5255
5256 void DateFormatTest::TestMinuteSecondFieldsInOddPlaces() {
5257 // Some times on 2015-11-13 (UTC+0).
5258 UDate k000000 = 1447372800000.0;
5259 UDate k000030 = 1447372830000.0;
5260 UDate k003000 = 1447374600000.0;
5261 UDate k060030 = 1447394430000.0;
5262 UDate k063000 = 1447396200000.0;
5263
5264 UErrorCode errorCode = U_ZERO_ERROR;
5265 const TimeZone *tz = TimeZone::getGMT();
5266 UnicodeString out;
5267
5268 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5269 // For ICU 57 output of "midnight" is temporarily suppressed.
5270
5271 // Seconds field is not present.
5272
5273 // Apply pattern through constructor to make sure parsePattern() is called during initialization.
5274 SimpleDateFormat sdf(UnicodeString("hh:mm 'ss' bbbb"), errorCode);
5275 if (U_FAILURE(errorCode)) {
5276 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5277 return;
5278 }
5279 sdf.setTimeZone(*tz);
5280
5281 // assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss midnight",
5282 // sdf.format(k000030, out.remove()));
5283 assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss AM",
5284 sdf.format(k000030, out.remove()));
5285 assertEquals("hh:mm 'ss' bbbb | 06:00:30", "06:00 ss AM",
5286 sdf.format(k060030, out.remove()));
5287
5288 sdf.applyPattern(UnicodeString("hh:mm 'ss' BBBB"));
5289
5290 // assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss midnight",
5291 // sdf.format(k000030, out.remove()));
5292 assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss at night",
5293 sdf.format(k000030, out.remove()));
5294 assertEquals("hh:mm 'ss' BBBB | 06:00:30", "06:00 ss in the morning",
5295 sdf.format(k060030, out.remove()));
5296
5297 // Minutes field is not present.
5298 sdf.applyPattern(UnicodeString("hh 'mm ss' bbbb"));
5299
5300 // assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss midnight",
5301 // sdf.format(k003000, out.remove()));
5302 assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss AM",
5303 sdf.format(k003000, out.remove()));
5304 assertEquals("hh 'mm ss' bbbb | 06:30:00", "06 mm ss AM",
5305 sdf.format(k063000, out.remove()));
5306
5307 sdf.applyPattern(UnicodeString("hh 'mm ss' BBBB"));
5308
5309 // assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss midnight",
5310 // sdf.format(k003000, out.remove()));
5311 assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss at night",
5312 sdf.format(k003000, out.remove()));
5313 assertEquals("hh 'mm ss' BBBB | 06:30:00", "06 mm ss in the morning",
5314 sdf.format(k063000, out.remove()));
5315
5316 // Minutes and seconds fields appear after day periods.
5317 sdf.applyPattern(UnicodeString("bbbb hh:mm:ss"));
5318
5319 // assertEquals("bbbb hh:mm:ss | 00:00:00", "midnight 12:00:00",
5320 // sdf.format(k000000, out.remove()));
5321 assertEquals("bbbb hh:mm:ss | 00:00:00", "AM 12:00:00",
5322 sdf.format(k000000, out.remove()));
5323 assertEquals("bbbb hh:mm:ss | 00:00:30", "AM 12:00:30",
5324 sdf.format(k000030, out.remove()));
5325 assertEquals("bbbb hh:mm:ss | 00:30:00", "AM 12:30:00",
5326 sdf.format(k003000, out.remove()));
5327
5328 sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5329
5330 // assertEquals("BBBB hh:mm:ss | 00:00:00", "midnight 12:00:00",
5331 // sdf.format(k000000, out.remove()));
5332 assertEquals("BBBB hh:mm:ss | 00:00:00", "at night 12:00:00",
5333 sdf.format(k000000, out.remove()));
5334 assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5335 sdf.format(k000030, out.remove()));
5336 assertEquals("BBBB hh:mm:ss | 00:30:00", "at night 12:30:00",
5337 sdf.format(k003000, out.remove()));
5338
5339 // Confirm applyPattern() reparses the pattern string.
5340 sdf.applyPattern(UnicodeString("BBBB hh"));
5341 // assertEquals("BBBB hh | 00:00:30", "midnight 12",
5342 // sdf.format(k000030, out.remove()));
5343 assertEquals("BBBB hh | 00:00:30", "at night 12",
5344 sdf.format(k000030, out.remove()));
5345
5346 sdf.applyPattern(UnicodeString("BBBB hh:mm:'ss'"));
5347 // assertEquals("BBBB hh:mm:'ss' | 00:00:30", "midnight 12:00:ss",
5348 // sdf.format(k000030, out.remove()));
5349 assertEquals("BBBB hh | 00:00:30", "at night 12:00:ss",
5350 sdf.format(k000030, out.remove()));
5351
5352 sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5353 assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5354 sdf.format(k000030, out.remove()));
5355 }
5356
5357 void DateFormatTest::TestDayPeriodParsing() {
5358 // Some times on 2015-11-13 (UTC+0).
5359 UDate k000000 = 1447372800000.0;
5360 UDate k003700 = 1447375020000.0;
5361 UDate k010000 = 1447376400000.0;
5362 UDate k013000 = 1447378200000.0;
5363 UDate k030000 = 1447383600000.0;
5364 UDate k090000 = 1447405200000.0;
5365 UDate k120000 = 1447416000000.0;
5366 UDate k130000 = 1447419600000.0;
5367 UDate k133700 = 1447421820000.0;
5368 UDate k150000 = 1447426800000.0;
5369 UDate k190000 = 1447441200000.0;
5370 UDate k193000 = 1447443000000.0;
5371 UDate k200000 = 1447444800000.0;
5372 UDate k210000 = 1447448400000.0;
5373
5374 UErrorCode errorCode = U_ZERO_ERROR;
5375 SimpleDateFormat sdf(UnicodeString(), errorCode);
5376 if (U_FAILURE(errorCode)) {
5377 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5378 return;
5379 }
5380 const TimeZone *tz = TimeZone::getGMT();
5381 sdf.setTimeZone(*tz);
5382 UnicodeString out;
5383
5384 // 'B' -- flexible day periods
5385 // A day period on its own parses to the center of that period.
5386 sdf.applyPattern(UnicodeString("yyyy-MM-dd B"));
5387 assertEquals("yyyy-MM-dd B | 2015-11-13 midnight",
5388 k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5389 assertEquals("yyyy-MM-dd B | 2015-11-13 noon",
5390 k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5391 assertEquals("yyyy-MM-dd B | 2015-11-13 in the afternoon",
5392 k150000, sdf.parse(UnicodeString("2015-11-13 in the afternoon"), errorCode));
5393 assertEquals("yyyy-MM-dd B | 2015-11-13 in the evening",
5394 k193000, sdf.parse(UnicodeString("2015-11-13 in the evening"), errorCode));
5395 assertEquals("yyyy-MM-dd B | 2015-11-13 at night",
5396 k013000, sdf.parse(UnicodeString("2015-11-13 at night"), errorCode));
5397
5398 // If time and day period are consistent with each other then time is parsed accordingly.
5399 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5400 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 midnight",
5401 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5402 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 noon",
5403 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5404 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 at night",
5405 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5406 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 in the afternoon",
5407 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5408 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 in the morning",
5409 k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5410 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 at night",
5411 k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5412
5413 // If the hour is 13 thru 23 then day period has no effect on time (since time is assumed
5414 // to be in 24-hour format).
5415 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5416 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 midnight",
5417 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5418 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 noon",
5419 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5420 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5421 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5422 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the afternoon",
5423 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the afternoon"), errorCode));
5424 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the morning",
5425 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the morning"), errorCode));
5426 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5427 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5428
5429 // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5430 // This unfortunately means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5431 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5432 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 midnight",
5433 k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5434 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 noon",
5435 k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5436
5437 // But when parsed with 'H', 0 indicates a 24-hour time, therefore we disregard the day period.
5438 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5439 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 midnight",
5440 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5441 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 noon",
5442 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5443 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5444 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5445 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the afternoon",
5446 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the afternoon"), errorCode));
5447 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the morning",
5448 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the morning"), errorCode));
5449 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5450 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5451
5452 // Even when parsed with 'H', hours 1 thru 12 are considered 12-hour time and takes
5453 // day period into account in parsing.
5454 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5455 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 midnight",
5456 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5457 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 noon",
5458 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5459 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 at night",
5460 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5461 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 in the afternoon",
5462 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5463 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 in the morning",
5464 k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5465 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 at night",
5466 k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5467
5468 // If a 12-hour time and the day period don't agree with each other, time is parsed as close
5469 // to the given day period as possible.
5470 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5471
5472 // AFTERNOON1 is [12, 18), but "7 in the afternoon" parses to 19:00.
5473 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 07:00 in the afternoon",
5474 k190000, sdf.parse(UnicodeString("2015-11-13 07:00 in the afternoon"), errorCode));
5475 // NIGHT1 is [21, 6), but "8 at night" parses to 20:00.
5476 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 08:00 at night",
5477 k200000, sdf.parse(UnicodeString("2015-11-13 08:00 at night"), errorCode));
5478
5479 // 'b' -- fixed day periods (AM, PM, midnight, noon)
5480 // On their own, "midnight" parses to 00:00 and "noon" parses to 12:00.
5481 // AM and PM are handled by the 'a' parser (which doesn't handle this case well).
5482 sdf.applyPattern(UnicodeString("yyyy-MM-dd b"));
5483 assertEquals("yyyy-MM-dd b | 2015-11-13 midnight",
5484 k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5485 assertEquals("yyyy-MM-dd b | 2015-11-13 noon",
5486 k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5487
5488 // For 12-hour times, AM and PM should be parsed as if with pattern character 'a'.
5489 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5490 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 AM",
5491 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 AM"), errorCode));
5492 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 PM",
5493 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 PM"), errorCode));
5494
5495 // 12 midnight parses to 00:00, and 12 noon parses to 12:00.
5496 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 midnight",
5497 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5498 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 noon",
5499 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5500
5501 // Hours 13-23 indicate 24-hour time so we disregard "midnight" or "noon".
5502 // Again, AM and PM are handled by the 'a' parser which doesn't handle this case well.
5503 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5504 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 midnight",
5505 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5506 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 noon",
5507 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5508
5509 // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5510 // Again, this means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5511 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5512 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 midnight",
5513 k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5514 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 noon",
5515 k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5516
5517 // With 'H' though 0 indicates a 24-hour time, therefore we disregard the day period.
5518 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5519 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 midnight",
5520 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5521 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 noon",
5522 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5523
5524 // If "midnight" or "noon" is parsed with a 12-hour time other than 12:00, choose
5525 // the version that's closer to the period given.
5526 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5527 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 midnight",
5528 k030000, sdf.parse(UnicodeString("2015-11-13 03:00 midnight"), errorCode));
5529 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 noon",
5530 k150000, sdf.parse(UnicodeString("2015-11-13 03:00 noon"), errorCode));
5531 }
5532
5533 #endif /* #if !UCONFIG_NO_FORMATTING */
5534
5535 //eof