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