]> git.saurik.com Git - apple/icu.git/blame_incremental - icuSources/test/intltest/dtfmttst.cpp
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / intltest / dtfmttst.cpp
... / ...
CommitLineData
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
3/********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 ********************************************************************/
8
9#include "unicode/utypes.h"
10
11#if !UCONFIG_NO_FORMATTING
12
13#include "dtfmttst.h"
14#include "unicode/localpointer.h"
15#include "unicode/timezone.h"
16#include "unicode/gregocal.h"
17#include "unicode/smpdtfmt.h"
18#include "unicode/datefmt.h"
19#include "unicode/dtptngen.h"
20#include "unicode/simpletz.h"
21#include "unicode/strenum.h"
22#include "unicode/dtfmtsym.h"
23#include "cmemory.h"
24#include "cstring.h"
25#include "caltest.h" // for fieldName
26#include <stdio.h> // for sprintf
27
28#if U_PLATFORM_USES_ONLY_WIN32_API
29#include "windttst.h"
30#endif
31
32#define ASSERT_OK(status) UPRV_BLOCK_MACRO_BEGIN { \
33 if(U_FAILURE(status)) { \
34 errcheckln(status, #status " = %s @ %s:%d", u_errorName(status), __FILE__, __LINE__); \
35 return; \
36 } \
37} UPRV_BLOCK_MACRO_END
38
39// *****************************************************************************
40// class DateFormatTest
41// *****************************************************************************
42
43void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
44{
45 if(exec) {
46 logln("TestSuite DateFormatTest: ");
47 }
48 TESTCASE_AUTO_BEGIN;
49 TESTCASE_AUTO(TestPatterns);
50 TESTCASE_AUTO(TestEquals);
51 TESTCASE_AUTO(TestTwoDigitYearDSTParse);
52 TESTCASE_AUTO(TestFieldPosition);
53 TESTCASE_AUTO(TestPartialParse994);
54 TESTCASE_AUTO(TestRunTogetherPattern985);
55 TESTCASE_AUTO(TestRunTogetherPattern917);
56 TESTCASE_AUTO(TestCzechMonths459);
57 TESTCASE_AUTO(TestLetterDPattern212);
58 TESTCASE_AUTO(TestDayOfYearPattern195);
59 TESTCASE_AUTO(TestQuotePattern161);
60 TESTCASE_AUTO(TestBadInput135);
61 TESTCASE_AUTO(TestBadInput135a);
62 TESTCASE_AUTO(TestTwoDigitYear);
63 TESTCASE_AUTO(TestDateFormatZone061);
64 TESTCASE_AUTO(TestDateFormatZone146);
65 TESTCASE_AUTO(TestLocaleDateFormat);
66 TESTCASE_AUTO(TestFormattingLocaleTimeSeparator);
67 TESTCASE_AUTO(TestWallyWedel);
68 TESTCASE_AUTO(TestDateFormatCalendar);
69 TESTCASE_AUTO(TestSpaceParsing);
70 TESTCASE_AUTO(TestExactCountFormat);
71 TESTCASE_AUTO(TestWhiteSpaceParsing);
72 TESTCASE_AUTO(TestInvalidPattern);
73 TESTCASE_AUTO(TestGeneral);
74 TESTCASE_AUTO(TestGreekMay);
75 TESTCASE_AUTO(TestGenericTime);
76 TESTCASE_AUTO(TestGenericTimeZoneOrder);
77 TESTCASE_AUTO(TestHost);
78 TESTCASE_AUTO(TestEras);
79 TESTCASE_AUTO(TestNarrowNames);
80 TESTCASE_AUTO(TestShortDays);
81 TESTCASE_AUTO(TestStandAloneDays);
82 TESTCASE_AUTO(TestStandAloneMonths);
83 TESTCASE_AUTO(TestQuarters);
84 TESTCASE_AUTO(TestZTimeZoneParsing);
85 TESTCASE_AUTO(TestRelative);
86 TESTCASE_AUTO(TestRelativeClone);
87 TESTCASE_AUTO(TestHostClone);
88 TESTCASE_AUTO(TestHebrewClone);
89 TESTCASE_AUTO(TestDateFormatSymbolsClone);
90 TESTCASE_AUTO(TestTimeZoneDisplayName);
91 TESTCASE_AUTO(TestRoundtripWithCalendar);
92 TESTCASE_AUTO(Test6338);
93 TESTCASE_AUTO(Test6726);
94 TESTCASE_AUTO(TestGMTParsing);
95 TESTCASE_AUTO(Test6880);
96 TESTCASE_AUTO(TestISOEra);
97 TESTCASE_AUTO(TestFormalChineseDate);
98 TESTCASE_AUTO(TestNumberAsStringParsing);
99 TESTCASE_AUTO(TestStandAloneGMTParse);
100 TESTCASE_AUTO(TestParsePosition);
101 TESTCASE_AUTO(TestMonthPatterns);
102 TESTCASE_AUTO(TestContext);
103 TESTCASE_AUTO(TestNonGregoFmtParse);
104 TESTCASE_AUTO(TestFormatsWithNumberSystems);
105 /*
106 TESTCASE_AUTO(TestRelativeError);
107 TESTCASE_AUTO(TestRelativeOther);
108 */
109 TESTCASE_AUTO(TestDotAndAtLeniency);
110 TESTCASE_AUTO(TestDateFormatLeniency);
111 TESTCASE_AUTO(TestParseMultiPatternMatch);
112
113 TESTCASE_AUTO(TestParseLeniencyAPIs);
114 TESTCASE_AUTO(TestNumberFormatOverride);
115 TESTCASE_AUTO(TestCreateInstanceForSkeleton);
116 TESTCASE_AUTO(TestCreateInstanceForSkeletonDefault);
117 TESTCASE_AUTO(TestCreateInstanceForSkeletonWithCalendar);
118 TESTCASE_AUTO(TestDFSCreateForLocaleNonGregorianLocale);
119 TESTCASE_AUTO(TestDFSCreateForLocaleWithCalendarInLocale);
120 TESTCASE_AUTO(TestChangeCalendar);
121
122 TESTCASE_AUTO(TestPatternFromSkeleton);
123
124 TESTCASE_AUTO(TestAmPmMidnightNoon);
125 TESTCASE_AUTO(TestFlexibleDayPeriod);
126 TESTCASE_AUTO(TestDayPeriodWithLocales);
127 TESTCASE_AUTO(TestMinuteSecondFieldsInOddPlaces);
128 TESTCASE_AUTO(TestDayPeriodParsing);
129 TESTCASE_AUTO(TestParseRegression13744);
130 TESTCASE_AUTO(TestAdoptCalendarLeak);
131
132 TESTCASE_AUTO_END;
133}
134
135void DateFormatTest::TestPatterns() {
136 static const struct {
137 const char *actualPattern;
138 const char *expectedPattern;
139 const char *localeID;
140 const char *expectedLocalPattern;
141 } EXPECTED[] = {
142 {UDAT_YEAR, "y","en","y"},
143
144 {UDAT_QUARTER, "QQQQ", "en", "QQQQ"},
145 {UDAT_ABBR_QUARTER, "QQQ", "en", "QQQ"},
146 {UDAT_YEAR_QUARTER, "yQQQQ", "en", "QQQQ y"},
147 {UDAT_YEAR_ABBR_QUARTER, "yQQQ", "en", "QQQ y"},
148
149 {UDAT_NUM_MONTH, "M", "en", "L"},
150 {UDAT_ABBR_MONTH, "MMM", "en", "LLL"},
151 {UDAT_MONTH, "MMMM", "en", "LLLL"},
152 {UDAT_YEAR_NUM_MONTH, "yM","en","M/y"},
153 {UDAT_YEAR_ABBR_MONTH, "yMMM","en","MMM y"},
154 {UDAT_YEAR_MONTH, "yMMMM","en","MMMM y"},
155
156 {UDAT_DAY, "d","en","d"},
157 {UDAT_YEAR_NUM_MONTH_DAY, "yMd", "en", "M/d/y"},
158 {UDAT_YEAR_ABBR_MONTH_DAY, "yMMMd", "en", "MMM d, y"},
159 {UDAT_YEAR_MONTH_DAY, "yMMMMd", "en", "MMMM d, y"},
160 {UDAT_YEAR_NUM_MONTH_WEEKDAY_DAY, "yMEd", "en", "EEE, M/d/y"},
161 {UDAT_YEAR_ABBR_MONTH_WEEKDAY_DAY, "yMMMEd", "en", "EEE, MMM d, y"},
162 {UDAT_YEAR_MONTH_WEEKDAY_DAY, "yMMMMEEEEd", "en", "EEEE, MMMM d, y"},
163
164 {UDAT_NUM_MONTH_DAY, "Md","en","M/d"},
165 {UDAT_ABBR_MONTH_DAY, "MMMd","en","MMM d"},
166 {UDAT_MONTH_DAY, "MMMMd","en","MMMM d"},
167 {UDAT_NUM_MONTH_WEEKDAY_DAY, "MEd","en","EEE, M/d"},
168 {UDAT_ABBR_MONTH_WEEKDAY_DAY, "MMMEd","en","EEE, MMM d"},
169 {UDAT_MONTH_WEEKDAY_DAY, "MMMMEEEEd","en","EEEE, MMMM d"},
170
171 {UDAT_HOUR, "j", "en", "h a"}, // (fixed expected result per ticket 6872<-6626)
172 {UDAT_HOUR24, "H", "en", "HH"}, // (fixed expected result per ticket 6872<-6626
173
174 {UDAT_MINUTE, "m", "en", "m"},
175 {UDAT_HOUR_MINUTE, "jm","en","h:mm a"}, // (fixed expected result per ticket 6872<-7180)
176 {UDAT_HOUR24_MINUTE, "Hm", "en", "HH:mm"}, // (fixed expected result per ticket 6872<-6626)
177
178 {UDAT_SECOND, "s", "en", "s"},
179 {UDAT_HOUR_MINUTE_SECOND, "jms","en","h:mm:ss a"}, // (fixed expected result per ticket 6872<-7180)
180 {UDAT_HOUR24_MINUTE_SECOND, "Hms","en","HH:mm:ss"}, // (fixed expected result per ticket 6872<-6626)
181 {UDAT_MINUTE_SECOND, "ms", "en", "mm:ss"}, // (fixed expected result per ticket 6872<-6626)
182
183 {UDAT_LOCATION_TZ, "VVVV", "en", "VVVV"},
184 {UDAT_GENERIC_TZ, "vvvv", "en", "vvvv"},
185 {UDAT_ABBR_GENERIC_TZ, "v", "en", "v"},
186 {UDAT_SPECIFIC_TZ, "zzzz", "en", "zzzz"},
187 {UDAT_ABBR_SPECIFIC_TZ, "z", "en", "z"},
188 {UDAT_ABBR_UTC_TZ, "ZZZZ", "en", "ZZZZ"},
189
190 {UDAT_YEAR_NUM_MONTH_DAY UDAT_ABBR_UTC_TZ, "yMdZZZZ", "en", "M/d/y, ZZZZ"},
191 {UDAT_MONTH_DAY UDAT_LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d, VVVV"}
192 };
193
194 IcuTestErrorCode errorCode(*this, "TestPatterns()");
195 for (int32_t i = 0; i < UPRV_LENGTHOF(EXPECTED); i++) {
196 // Verify that patterns have the correct values
197 UnicodeString actualPattern(EXPECTED[i].actualPattern, -1, US_INV);
198 UnicodeString expectedPattern(EXPECTED[i].expectedPattern, -1, US_INV);
199 Locale locale(EXPECTED[i].localeID);
200 if (actualPattern != expectedPattern) {
201 errln("FAILURE! Expected pattern: " + expectedPattern +
202 " but was: " + actualPattern);
203 }
204
205 // Verify that DataFormat instances produced contain the correct
206 // localized patterns
207 // TODO: use DateFormat::getInstanceForSkeleton(), ticket #9029
208 // Java test code:
209 // DateFormat date1 = DateFormat.getPatternInstance(actualPattern,
210 // locale);
211 // DateFormat date2 = DateFormat.getPatternInstance(Calendar.getInstance(locale),
212 // actualPattern, locale);
213 LocalPointer<DateTimePatternGenerator> generator(
214 DateTimePatternGenerator::createInstance(locale, errorCode));
215 if(errorCode.errDataIfFailureAndReset("DateTimePatternGenerator::createInstance() failed for locale ID \"%s\"", EXPECTED[i].localeID)) {
216 continue;
217 }
218 UnicodeString pattern = generator->getBestPattern(actualPattern, errorCode);
219 SimpleDateFormat date1(pattern, locale, errorCode);
220 SimpleDateFormat date2(pattern, locale, errorCode);
221 date2.adoptCalendar(Calendar::createInstance(locale, errorCode));
222 if(errorCode.errIfFailureAndReset("DateFormat::getInstanceForSkeleton() failed")) {
223 errln(" for actualPattern \"%s\" & locale ID \"%s\"",
224 EXPECTED[i].actualPattern, EXPECTED[i].localeID);
225 continue;
226 }
227
228 UnicodeString expectedLocalPattern(EXPECTED[i].expectedLocalPattern, -1, US_INV);
229 UnicodeString actualLocalPattern1;
230 UnicodeString actualLocalPattern2;
231 date1.toLocalizedPattern(actualLocalPattern1, errorCode);
232 date2.toLocalizedPattern(actualLocalPattern2, errorCode);
233 if (actualLocalPattern1 != expectedLocalPattern) {
234 errln("FAILURE! Expected local pattern: " + expectedLocalPattern
235 + " but was: " + actualLocalPattern1);
236 }
237 if (actualLocalPattern2 != expectedLocalPattern) {
238 errln("FAILURE! Expected local pattern: " + expectedLocalPattern
239 + " but was: " + actualLocalPattern2);
240 }
241 }
242}
243
244// Test written by Wally Wedel and emailed to me.
245void DateFormatTest::TestWallyWedel()
246{
247 UErrorCode status = U_ZERO_ERROR;
248 /*
249 * Instantiate a TimeZone so we can get the ids.
250 */
251 TimeZone *tz = new SimpleTimeZone(7,"");
252 /*
253 * Computational variables.
254 */
255 int32_t offset, hours, minutes, seconds;
256 /*
257 * Instantiate a SimpleDateFormat set up to produce a full time
258 zone name.
259 */
260 SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)"zzzz", status);
261 /*
262 * A String array for the time zone ids.
263 */
264 int32_t ids_length;
265 StringEnumeration* ids = TimeZone::createEnumeration();
266 if (ids == NULL) {
267 dataerrln("Unable to create TimeZone enumeration.");
268 if (sdf != NULL) {
269 delete sdf;
270 }
271 return;
272 }
273 ids_length = ids->count(status);
274 /*
275 * How many ids do we have?
276 */
277 logln("Time Zone IDs size: %d", ids_length);
278 /*
279 * Column headings (sort of)
280 */
281 logln("Ordinal ID offset(h:m) name");
282 /*
283 * Loop through the tzs.
284 */
285 UDate today = Calendar::getNow();
286 Calendar *cal = Calendar::createInstance(status);
287 for (int32_t i = 0; i < ids_length; i++) {
288 // logln(i + " " + ids[i]);
289 const UnicodeString* id = ids->snext(status);
290 TimeZone *ttz = TimeZone::createTimeZone(*id);
291 // offset = ttz.getRawOffset();
292 cal->setTimeZone(*ttz);
293 cal->setTime(today, status);
294 offset = cal->get(UCAL_ZONE_OFFSET, status) + cal->get(UCAL_DST_OFFSET, status);
295 // logln(i + " " + ids[i] + " offset " + offset);
296 const char* sign = "+";
297 if (offset < 0) {
298 sign = "-";
299 offset = -offset;
300 }
301 hours = offset/3600000;
302 minutes = (offset%3600000)/60000;
303 seconds = (offset%60000)/1000;
304 UnicodeString dstOffset = (UnicodeString)"" + sign + (hours < 10 ? "0" : "") +
305 (int32_t)hours + ":" + (minutes < 10 ? "0" : "") + (int32_t)minutes;
306 if (seconds != 0) {
307 dstOffset = dstOffset + ":" + (seconds < 10 ? "0" : "") + seconds;
308 }
309 /*
310 * Instantiate a date so we can display the time zone name.
311 */
312 sdf->setTimeZone(*ttz);
313 /*
314 * Format the output.
315 */
316 UnicodeString fmtOffset;
317 FieldPosition pos(FieldPosition::DONT_CARE);
318 sdf->format(today,fmtOffset, pos);
319 // UnicodeString fmtOffset = tzS.toString();
320 UnicodeString *fmtDstOffset = 0;
321 if (fmtOffset.startsWith("GMT") && fmtOffset.length() != 3)
322 {
323 //fmtDstOffset = fmtOffset->substring(3);
324 fmtDstOffset = new UnicodeString();
325 fmtOffset.extract(3, fmtOffset.length(), *fmtDstOffset);
326 }
327 /*
328 * Show our result.
329 */
330 UBool ok = fmtDstOffset == 0 || *fmtDstOffset == dstOffset;
331 if (ok)
332 {
333 logln(UnicodeString() + i + " " + *id + " " + dstOffset +
334 " " + fmtOffset +
335 (fmtDstOffset != 0 ? " ok" : " ?"));
336 }
337 else
338 {
339 errln(UnicodeString() + i + " " + *id + " " + dstOffset +
340 " " + fmtOffset + " *** FAIL ***");
341 }
342 delete ttz;
343 delete fmtDstOffset;
344 }
345 delete cal;
346 // delete ids; // TODO: BAD API
347 delete ids;
348 delete sdf;
349 delete tz;
350}
351
352// -------------------------------------
353
354/**
355 * Test operator==
356 */
357void
358DateFormatTest::TestEquals()
359{
360 DateFormat* fmtA = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
361 DateFormat* fmtB = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL);
362 if ( fmtA == NULL || fmtB == NULL){
363 dataerrln("Error calling DateFormat::createDateTimeInstance");
364 delete fmtA;
365 delete fmtB;
366 return;
367 }
368
369 if (!(*fmtA == *fmtB)) errln((UnicodeString)"FAIL");
370 delete fmtA;
371 delete fmtB;
372
373 TimeZone* test = TimeZone::createTimeZone("PDT");
374 delete test;
375}
376
377// -------------------------------------
378
379/**
380 * Test the parsing of 2-digit years.
381 */
382void
383DateFormatTest::TestTwoDigitYearDSTParse(void)
384{
385 UErrorCode status = U_ZERO_ERROR;
386 SimpleDateFormat fullFmt((UnicodeString)"EEE MMM dd HH:mm:ss.SSS zzz yyyy G", status);
387 SimpleDateFormat fmt((UnicodeString)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status);
388 //DateFormat* fmt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, Locale::ENGLISH);
389 UnicodeString s(u"03-Apr-04 2:20:47 o'clock AM PST");
390 LocalPointer<TimeZone> defaultTZ(TimeZone::createDefault());
391 LocalPointer<TimeZone> PST(TimeZone::createTimeZone("PST"));
392 int32_t defaultOffset = defaultTZ->getRawOffset();
393 int32_t PSTOffset = PST->getRawOffset();
394 int32_t hour = 2 + (defaultOffset - PSTOffset) / (60*60*1000);
395 // hour is the expected hour of day, in units of seconds
396 hour = ((hour < 0) ? hour + 24 : hour) * 60*60;
397
398 UnicodeString str;
399
400 if(U_FAILURE(status)) {
401 dataerrln("Could not set up test. exitting - %s", u_errorName(status));
402 return;
403 }
404
405 UDate d = fmt.parse(s, status);
406 logln(s + " P> " + fullFmt.format(d, str));
407 int32_t y, m, day, hr, min, sec;
408 dateToFields(d, y, m, day, hr, min, sec);
409 hour += defaultTZ->inDaylightTime(d, status) ? 1 : 0;
410 hr = hr*60*60;
411 if (hr != hour)
412 errln((UnicodeString)"FAIL: Should parse to hour " + hour + " but got " + hr);
413
414 if (U_FAILURE(status))
415 errln((UnicodeString)"FAIL: " + (int32_t)status);
416}
417
418// -------------------------------------
419
420UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
421
422UnicodeString&
423DateFormatTest::escape(UnicodeString& s)
424{
425 UnicodeString buf;
426 for (int32_t i=0; i<s.length(); ++i)
427 {
428 UChar c = s[(int32_t)i];
429 if (c <= (UChar)0x7F) buf += c;
430 else {
431 buf += (UChar)0x5c; buf += (UChar)0x55;
432 buf += toHexString((c & 0xF000) >> 12);
433 buf += toHexString((c & 0x0F00) >> 8);
434 buf += toHexString((c & 0x00F0) >> 4);
435 buf += toHexString(c & 0x000F);
436 }
437 }
438 return (s = buf);
439}
440
441// -------------------------------------
442
443/**
444 * This MUST be kept in sync with DateFormatSymbols.gPatternChars.
445 */
446#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
447static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:";
448#else
449static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB";
450#endif
451
452/**
453 * A list of the names of all the fields in DateFormat.
454 * This MUST be kept in sync with DateFormat.
455 */
456static const char* DATEFORMAT_FIELD_NAMES[] = {
457 "ERA_FIELD",
458 "YEAR_FIELD",
459 "MONTH_FIELD",
460 "DATE_FIELD",
461 "HOUR_OF_DAY1_FIELD",
462 "HOUR_OF_DAY0_FIELD",
463 "MINUTE_FIELD",
464 "SECOND_FIELD",
465 "MILLISECOND_FIELD",
466 "DAY_OF_WEEK_FIELD",
467 "DAY_OF_YEAR_FIELD",
468 "DAY_OF_WEEK_IN_MONTH_FIELD",
469 "WEEK_OF_YEAR_FIELD",
470 "WEEK_OF_MONTH_FIELD",
471 "AM_PM_FIELD",
472 "HOUR1_FIELD",
473 "HOUR0_FIELD",
474 "TIMEZONE_FIELD",
475 "YEAR_WOY_FIELD",
476 "DOW_LOCAL_FIELD",
477 "EXTENDED_YEAR_FIELD",
478 "JULIAN_DAY_FIELD",
479 "MILLISECONDS_IN_DAY_FIELD",
480 "TIMEZONE_RFC_FIELD",
481 "GENERIC_TIMEZONE_FIELD",
482 "STAND_ALONE_DAY_FIELD",
483 "STAND_ALONE_MONTH_FIELD",
484 "QUARTER_FIELD",
485 "STAND_ALONE_QUARTER_FIELD",
486 "TIMEZONE_SPECIAL_FIELD",
487 "YEAR_NAME_FIELD",
488 "TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD",
489 "TIMEZONE_ISO_FIELD",
490 "TIMEZONE_ISO_LOCAL_FIELD",
491 "RELATED_YEAR_FIELD",
492 "AM_PM_MIDNIGHT_NOON_FIELD",
493 "FLEXIBLE_DAY_PERIOD_FIELD",
494 "UDAT_TIME_SEPARATOR_FIELD",
495};
496
497static const int32_t DATEFORMAT_FIELD_NAMES_LENGTH =
498 UPRV_LENGTHOF(DATEFORMAT_FIELD_NAMES);
499
500/**
501 * Verify that returned field position indices are correct.
502 */
503void DateFormatTest::TestFieldPosition() {
504 UErrorCode ec = U_ZERO_ERROR;
505 int32_t i, j, exp;
506 UnicodeString buf;
507
508 // Verify data
509 DateFormatSymbols rootSyms(Locale(""), ec);
510 if (U_FAILURE(ec)) {
511 dataerrln("Unable to create DateFormatSymbols - %s", u_errorName(ec));
512 return;
513 }
514
515 // local pattern chars data is not longer loaded
516 // from icu locale bundle
517 assertEquals("patternChars", PATTERN_CHARS, rootSyms.getLocalPatternChars(buf));
518 assertEquals("patternChars", PATTERN_CHARS, DateFormatSymbols::getPatternUChars());
519 assertTrue("DATEFORMAT_FIELD_NAMES", DATEFORMAT_FIELD_NAMES_LENGTH == UDAT_FIELD_COUNT);
520#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
521 assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS));
522#else
523 assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS) + 1); // +1 for missing TIME_SEPARATOR pattern char
524#endif
525
526 // Create test formatters
527 const int32_t COUNT = 4;
528 DateFormat* dateFormats[COUNT];
529 dateFormats[0] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getUS());
530 dateFormats[1] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getFrance());
531 // Make the pattern "G y M d..."
532 buf.remove().append(PATTERN_CHARS);
533 for (j=buf.length()-1; j>=0; --j) buf.insert(j, (UChar)32/*' '*/);
534 dateFormats[2] = new SimpleDateFormat(buf, Locale::getUS(), ec);
535 // Make the pattern "GGGG yyyy MMMM dddd..."
536 for (j=buf.length()-1; j>=0; j-=2) {
537 for (i=0; i<3; ++i) {
538 buf.insert(j, buf.charAt(j));
539 }
540 }
541 dateFormats[3] = new SimpleDateFormat(buf, Locale::getUS(), ec);
542 if(U_FAILURE(ec)){
543 errln(UnicodeString("Could not create SimpleDateFormat object for locale en_US. Error: " )+ UnicodeString(u_errorName(ec)));
544 return;
545 }
546 UDate aug13 = 871508052513.0;
547
548 // Expected output field values for above DateFormats on aug13
549 // Fields are given in order of DateFormat field number
550 const char* EXPECTED[] = {
551 "", "1997", "August", "13", "", "", "34", "12", "", "Wednesday",
552 "", "", "", "", "PM", "2", "", "Pacific Daylight Time", "", "",
553 "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
554#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
555 ":",
556#else
557 "",
558#endif
559
560 "", "1997", "ao\\u00FBt", "13", "", "14", "34", "12", "", "mercredi",
561 "", "", "", "", "", "", "", "heure d\\u2019\\u00E9t\\u00E9 du Pacifique", "", "",
562 "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
563#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
564 ":",
565#else
566 "",
567#endif
568
569 "AD", "1997", "8", "13", "14", "14", "34", "12", "5", "Wed",
570 "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4",
571 "1997", "2450674", "52452513", "-0700", "PT", "4", "8", "3", "3", "uslax",
572 "1997", "GMT-7", "-07", "-07", "1997", "PM", "in the afternoon",
573#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
574 ":",
575#else
576 "",
577#endif
578
579 "Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130", "Wednesday",
580 "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "Wednesday",
581 "1997", "2450674", "52452513", "GMT-07:00", "Pacific Time", "Wednesday", "August", "3rd quarter", "3rd quarter", "Los Angeles Time",
582 "1997", "GMT-07:00", "-0700", "-0700", "1997", "PM", "in the afternoon",
583#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
584 ":",
585#else
586 "",
587#endif
588 };
589
590 const int32_t EXPECTED_LENGTH = UPRV_LENGTHOF(EXPECTED);
591
592 assertTrue("data size", EXPECTED_LENGTH == COUNT * UDAT_FIELD_COUNT);
593
594 TimeZone* PT = TimeZone::createTimeZone("America/Los_Angeles");
595 for (j = 0, exp = 0; j < COUNT; ++j) {
596 // String str;
597 DateFormat* df = dateFormats[j];
598 df->setTimeZone(*PT);
599 SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
600 if (sdtfmt != NULL) {
601 logln(" Pattern = " + sdtfmt->toPattern(buf.remove()));
602 } else {
603 logln(" Pattern = ? (not a SimpleDateFormat)");
604 }
605 logln((UnicodeString)" Result = " + df->format(aug13, buf.remove()));
606
607 int32_t expBase = exp; // save for later
608 for (i = 0; i < UDAT_FIELD_COUNT; ++i, ++exp) {
609 FieldPosition pos(i);
610 buf.remove();
611 df->format(aug13, buf, pos);
612 UnicodeString field;
613 buf.extractBetween(pos.getBeginIndex(), pos.getEndIndex(), field);
614 assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
615 ctou(EXPECTED[exp]), field);
616 }
617
618 // test FieldPositionIterator API
619 logln("FieldPositionIterator");
620 {
621 UErrorCode status = U_ZERO_ERROR;
622 FieldPositionIterator posIter;
623 FieldPosition fp;
624
625 buf.remove();
626 df->format(aug13, buf, &posIter, status);
627 while (posIter.next(fp)) {
628 int32_t i = fp.getField();
629 UnicodeString field;
630 buf.extractBetween(fp.getBeginIndex(), fp.getEndIndex(), field);
631 assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i],
632 ctou(EXPECTED[expBase + i]), field);
633 }
634
635 }
636 }
637
638
639 // test null posIter
640 buf.remove();
641 UErrorCode status = U_ZERO_ERROR;
642 dateFormats[0]->format(aug13, buf, NULL, status);
643 // if we didn't crash, we succeeded.
644
645 for (i=0; i<COUNT; ++i) {
646 delete dateFormats[i];
647 }
648 delete PT;
649}
650
651// -------------------------------------
652
653/**
654 * General parse/format tests. Add test cases as needed.
655 */
656void DateFormatTest::TestGeneral() {
657 const char* DATA[] = {
658 "yyyy MM dd HH:mm:ss.SSS",
659
660 // Milliseconds are left-justified, since they format as fractions of a second
661 "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",
662 "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",
663 "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567",
664 "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",
665 };
666 expect(DATA, UPRV_LENGTHOF(DATA), Locale("en", "", ""));
667}
668
669// -------------------------------------
670
671/**
672 * Verify that strings which contain incomplete specifications are parsed
673 * correctly. In some instances, this means not being parsed at all, and
674 * returning an appropriate error.
675 */
676void
677DateFormatTest::TestPartialParse994()
678{
679 UErrorCode status = U_ZERO_ERROR;
680 SimpleDateFormat* f = new SimpleDateFormat(status);
681 if (U_FAILURE(status)) {
682 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
683 delete f;
684 return;
685 }
686 UDate null = 0;
687 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", date(97, 1 - 1, 17, 10, 11, 42));
688 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null);
689 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null);
690 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null);
691 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null);
692 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
693 delete f;
694}
695
696// -------------------------------------
697
698void
699DateFormatTest::tryPat994(SimpleDateFormat* format, const char* pat, const char* str, UDate expected)
700{
701 UErrorCode status = U_ZERO_ERROR;
702 UDate null = 0;
703 logln(UnicodeString("Pattern \"") + pat + "\" String \"" + str + "\"");
704 //try {
705 format->applyPattern(pat);
706 UDate date = format->parse(str, status);
707 if (U_FAILURE(status) || date == null)
708 {
709 logln((UnicodeString)"ParseException: " + (int32_t)status);
710 if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
711 }
712 else
713 {
714 UnicodeString f;
715 ((DateFormat*)format)->format(date, f);
716 logln(UnicodeString(" parse(") + str + ") -> " + dateToString(date));
717 logln((UnicodeString)" format -> " + f);
718 if (expected == null ||
719 !(date == expected)) errln((UnicodeString)"FAIL: Expected null");//" + expected);
720 if (!(f == str)) errln(UnicodeString("FAIL: Expected ") + str);
721 }
722 //}
723 //catch(ParseException e) {
724 // logln((UnicodeString)"ParseException: " + e.getMessage());
725 // if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
726 //}
727 //catch(Exception e) {
728 // errln((UnicodeString)"*** Exception:");
729 // e.printStackTrace();
730 //}
731}
732
733// -------------------------------------
734
735/**
736 * Verify the behavior of patterns in which digits for different fields run together
737 * without intervening separators.
738 */
739void
740DateFormatTest::TestRunTogetherPattern985()
741{
742 UErrorCode status = U_ZERO_ERROR;
743 UnicodeString format("yyyyMMddHHmmssSSS");
744 UnicodeString now, then;
745 //UBool flag;
746 SimpleDateFormat *formatter = new SimpleDateFormat(format, status);
747 if (U_FAILURE(status)) {
748 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
749 delete formatter;
750 return;
751 }
752 UDate date1 = Calendar::getNow();
753 ((DateFormat*)formatter)->format(date1, now);
754 logln(now);
755 ParsePosition pos(0);
756 UDate date2 = formatter->parse(now, pos);
757 if (date2 == 0) then = UnicodeString("Parse stopped at ") + pos.getIndex();
758 else ((DateFormat*)formatter)->format(date2, then);
759 logln(then);
760 if (!(date2 == date1)) errln((UnicodeString)"FAIL");
761 delete formatter;
762 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
763}
764
765// -------------------------------------
766
767/**
768 * Verify the behavior of patterns in which digits for different fields run together
769 * without intervening separators.
770 */
771void
772DateFormatTest::TestRunTogetherPattern917()
773{
774 UErrorCode status = U_ZERO_ERROR;
775 SimpleDateFormat* fmt;
776 UnicodeString myDate;
777 fmt = new SimpleDateFormat((UnicodeString)"yyyy/MM/dd", status);
778 if (U_FAILURE(status)) {
779 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
780 delete fmt;
781 return;
782 }
783 myDate = "1997/02/03";
784 testIt917(fmt, myDate, date(97, 2 - 1, 3));
785 delete fmt;
786 fmt = new SimpleDateFormat((UnicodeString)"yyyyMMdd", status);
787 myDate = "19970304";
788 testIt917(fmt, myDate, date(97, 3 - 1, 4));
789 delete fmt;
790 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
791}
792
793// -------------------------------------
794
795void
796DateFormatTest::testIt917(SimpleDateFormat* fmt, UnicodeString& str, UDate expected)
797{
798 UErrorCode status = U_ZERO_ERROR;
799 UnicodeString pattern;
800 logln((UnicodeString)"pattern=" + fmt->toPattern(pattern) + " string=" + str);
801 Formattable o;
802 //try {
803 ((Format*)fmt)->parseObject(str, o, status);
804 //}
805 if (U_FAILURE(status)) return;
806 //catch(ParseException e) {
807 // e.printStackTrace();
808 // return;
809 //}
810 logln((UnicodeString)"Parsed object: " + dateToString(o.getDate()));
811 if (!(o.getDate() == expected)) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
812 UnicodeString formatted; ((Format*)fmt)->format(o, formatted, status);
813 logln((UnicodeString)"Formatted string: " + formatted);
814 if (!(formatted == str)) errln((UnicodeString)"FAIL: Expected " + str);
815 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
816}
817
818// -------------------------------------
819
820/**
821 * Verify the handling of Czech June and July, which have the unique attribute that
822 * one is a proper prefix substring of the other.
823 */
824void
825DateFormatTest::TestCzechMonths459()
826{
827 UErrorCode status = U_ZERO_ERROR;
828 DateFormat* fmt = DateFormat::createDateInstance(DateFormat::FULL, Locale("cs", "", ""));
829 if (fmt == NULL){
830 dataerrln("Error calling DateFormat::createDateInstance()");
831 return;
832 }
833
834 UnicodeString pattern;
835 logln((UnicodeString)"Pattern " + ((SimpleDateFormat*) fmt)->toPattern(pattern));
836 UDate june = date(97, UCAL_JUNE, 15);
837 UDate july = date(97, UCAL_JULY, 15);
838 UnicodeString juneStr; fmt->format(june, juneStr);
839 UnicodeString julyStr; fmt->format(july, julyStr);
840 //try {
841 logln((UnicodeString)"format(June 15 1997) = " + juneStr);
842 UDate d = fmt->parse(juneStr, status);
843 UnicodeString s; fmt->format(d, s);
844 int32_t month,yr,day,hr,min,sec; dateToFields(d,yr,month,day,hr,min,sec);
845 logln((UnicodeString)" -> parse -> " + s + " (month = " + month + ")");
846 if (month != UCAL_JUNE) errln((UnicodeString)"FAIL: Month should be June");
847 logln((UnicodeString)"format(July 15 1997) = " + julyStr);
848 d = fmt->parse(julyStr, status);
849 fmt->format(d, s);
850 dateToFields(d,yr,month,day,hr,min,sec);
851 logln((UnicodeString)" -> parse -> " + s + " (month = " + month + ")");
852 if (month != UCAL_JULY) errln((UnicodeString)"FAIL: Month should be July");
853 //}
854 //catch(ParseException e) {
855 if (U_FAILURE(status))
856 errln((UnicodeString)"Exception: " + (int32_t)status);
857 //}
858 delete fmt;
859}
860
861// -------------------------------------
862
863/**
864 * Test the handling of 'D' in patterns.
865 */
866void
867DateFormatTest::TestLetterDPattern212()
868{
869 UErrorCode status = U_ZERO_ERROR;
870 UnicodeString dateString("1995-040.05:01:29");
871 UnicodeString bigD("yyyy-DDD.hh:mm:ss");
872 UnicodeString littleD("yyyy-ddd.hh:mm:ss");
873 UDate expLittleD = date(95, 0, 1, 5, 1, 29);
874 UDate expBigD = expLittleD + 39 * 24 * 3600000.0;
875 expLittleD = expBigD; // Expect the same, with default lenient parsing
876 logln((UnicodeString)"dateString= " + dateString);
877 SimpleDateFormat *formatter = new SimpleDateFormat(bigD, status);
878 if (U_FAILURE(status)) {
879 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
880 delete formatter;
881 return;
882 }
883 ParsePosition pos(0);
884 UDate myDate = formatter->parse(dateString, pos);
885 logln((UnicodeString)"Using " + bigD + " -> " + myDate);
886 if (myDate != expBigD) errln((UnicodeString)"FAIL: bigD - Expected " + dateToString(expBigD));
887 delete formatter;
888 formatter = new SimpleDateFormat(littleD, status);
889 ASSERT_OK(status);
890 pos = ParsePosition(0);
891 myDate = formatter->parse(dateString, pos);
892 logln((UnicodeString)"Using " + littleD + " -> " + dateToString(myDate));
893 if (myDate != expLittleD) errln((UnicodeString)"FAIL: littleD - Expected " + dateToString(expLittleD));
894 delete formatter;
895 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
896}
897
898// -------------------------------------
899
900/**
901 * Test the day of year pattern.
902 */
903void
904DateFormatTest::TestDayOfYearPattern195()
905{
906 UErrorCode status = U_ZERO_ERROR;
907 UDate today = Calendar::getNow();
908 int32_t year,month,day,hour,min,sec; dateToFields(today,year,month,day,hour,min,sec);
909 UDate expected = date(year, month, day);
910 logln((UnicodeString)"Test Date: " + dateToString(today));
911 SimpleDateFormat* sdf = (SimpleDateFormat*)DateFormat::createDateInstance();
912 if (sdf == NULL){
913 dataerrln("Error calling DateFormat::createDateInstance()");
914 return;
915 }
916 tryPattern(*sdf, today, 0, expected);
917 tryPattern(*sdf, today, "G yyyy DDD", expected);
918 delete sdf;
919 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
920}
921
922// -------------------------------------
923
924void
925DateFormatTest::tryPattern(SimpleDateFormat& sdf, UDate d, const char* pattern, UDate expected)
926{
927 UErrorCode status = U_ZERO_ERROR;
928 if (pattern != 0) sdf.applyPattern(pattern);
929 UnicodeString thePat;
930 logln((UnicodeString)"pattern: " + sdf.toPattern(thePat));
931 UnicodeString formatResult; (*(DateFormat*)&sdf).format(d, formatResult);
932 logln((UnicodeString)" format -> " + formatResult);
933 // try {
934 UDate d2 = sdf.parse(formatResult, status);
935 logln((UnicodeString)" parse(" + formatResult + ") -> " + dateToString(d2));
936 if (d2 != expected) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
937 UnicodeString format2; (*(DateFormat*)&sdf).format(d2, format2);
938 logln((UnicodeString)" format -> " + format2);
939 if (!(formatResult == format2)) errln((UnicodeString)"FAIL: Round trip drift");
940 //}
941 //catch(Exception e) {
942 if (U_FAILURE(status))
943 errln((UnicodeString)"Error: " + (int32_t)status);
944 //}
945}
946
947// -------------------------------------
948
949/**
950 * Test the handling of single quotes in patterns.
951 */
952void
953DateFormatTest::TestQuotePattern161()
954{
955 UErrorCode status = U_ZERO_ERROR;
956 SimpleDateFormat* formatter = new SimpleDateFormat((UnicodeString)"MM/dd/yyyy 'at' hh:mm:ss a zzz", status);
957 if (U_FAILURE(status)) {
958 dataerrln("Fail new SimpleDateFormat: %s", u_errorName(status));
959 delete formatter;
960 return;
961 }
962 UDate currentTime_1 = date(97, UCAL_AUGUST, 13, 10, 42, 28);
963 UnicodeString dateString; ((DateFormat*)formatter)->format(currentTime_1, dateString);
964 UnicodeString exp("08/13/1997 at 10:42:28 AM ");
965 logln((UnicodeString)"format(" + dateToString(currentTime_1) + ") = " + dateString);
966 if (0 != dateString.compareBetween(0, exp.length(), exp, 0, exp.length())) errln((UnicodeString)"FAIL: Expected " + exp);
967 delete formatter;
968 if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
969}
970
971// -------------------------------------
972
973/**
974 * Verify the correct behavior when handling invalid input strings.
975 */
976void
977DateFormatTest::TestBadInput135()
978{
979 UErrorCode status = U_ZERO_ERROR;
980 DateFormat::EStyle looks[] = {
981 DateFormat::SHORT, DateFormat::MEDIUM, DateFormat::LONG, DateFormat::FULL
982 };
983 int32_t looks_length = UPRV_LENGTHOF(looks);
984 const char* strings[] = {
985 "Mar 15", "Mar 15 1997", "asdf", "3/1/97 1:23:", "3/1/00 1:23:45 AM"
986 };
987 int32_t strings_length = UPRV_LENGTHOF(strings);
988 DateFormat *full = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::LONG);
989 if(full==NULL) {
990 dataerrln("could not create date time instance");
991 return;
992 }
993 UnicodeString expected("March 1, 2000 at 1:23:45 AM ");
994 for (int32_t i = 0; i < strings_length;++i) {
995 const char* text = strings[i];
996 for (int32_t j = 0; j < looks_length;++j) {
997 DateFormat::EStyle dateLook = looks[j];
998 for (int32_t k = 0; k < looks_length;++k) {
999 DateFormat::EStyle timeLook = looks[k];
1000 DateFormat *df = DateFormat::createDateTimeInstance(dateLook, timeLook);
1001 if (df == NULL){
1002 dataerrln("Error calling DateFormat::createDateTimeInstance()");
1003 continue;
1004 }
1005 UnicodeString prefix = UnicodeString(text) + ", " + dateLook + "/" + timeLook + ": ";
1006 //try {
1007 UDate when = df->parse(text, status);
1008 if (when == 0 && U_SUCCESS(status)) {
1009 errln(prefix + "SHOULD NOT HAPPEN: parse returned 0.");
1010 continue;
1011 }
1012 if (U_SUCCESS(status))
1013 {
1014 UnicodeString format;
1015 UnicodeString pattern;
1016 SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(df);
1017 if (sdtfmt != NULL) {
1018 sdtfmt->toPattern(pattern);
1019 }
1020 full->format(when, format);
1021 logln(prefix + "OK: " + format);
1022 if (0!=format.compareBetween(0, expected.length(), expected, 0, expected.length()))
1023 errln((UnicodeString)"FAIL: Parse \"" + text + "\", pattern \"" + pattern + "\", expected " + expected + " got " + format);
1024 }
1025 //}
1026 //catch(ParseException e) {
1027 else
1028 status = U_ZERO_ERROR;
1029 //}
1030 //catch(StringIndexOutOfBoundsException e) {
1031 // errln(prefix + "SHOULD NOT HAPPEN: " + (int)status);
1032 //}
1033 delete df;
1034 }
1035 }
1036 }
1037 delete full;
1038 if (U_FAILURE(status))
1039 errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1040}
1041
1042static const char* const parseFormats[] = {
1043 "MMMM d, yyyy",
1044 "MMMM d yyyy",
1045 "M/d/yy",
1046 "d MMMM, yyyy",
1047 "d MMMM yyyy",
1048 "d MMMM",
1049 "MMMM d",
1050 "yyyy",
1051 "h:mm a MMMM d, yyyy"
1052};
1053
1054#if 0
1055// strict inputStrings
1056static const char* const inputStrings[] = {
1057 "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1058 "April 1, 1997", "April 1, 1997", 0, 0, 0, 0, 0, "April 1", 0, 0,
1059 "Jan 1, 1970", "January 1, 1970", 0, 0, 0, 0, 0, "January 1", 0, 0,
1060 "Jan 1 2037", 0, "January 1 2037", 0, 0, 0, 0, "January 1", 0, 0,
1061 "1/1/70", 0, 0, "1/1/70", 0, 0, 0, 0, "0001", 0,
1062 "5 May 1997", 0, 0, 0, 0, "5 May 1997", "5 May", 0, "0005", 0,
1063 "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1064 "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1065 "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1066 "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1067 "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1068};
1069#else
1070// lenient inputStrings
1071static const char* const inputStrings[] = {
1072 "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
1073 "April 1, 1997", "April 1, 1997", "April 1 1997", "4/1/97", 0, 0, 0, "April 1", 0, 0,
1074 "Jan 1, 1970", "January 1, 1970", "January 1 1970", "1/1/70", 0, 0, 0, "January 1", 0, 0,
1075 "Jan 1 2037", "January 1, 2037", "January 1 2037", "1/1/37", 0, 0, 0, "January 1", 0, 0,
1076 "1/1/70", "January 1, 0070", "January 1 0070", "1/1/70", "1 January, 0070", "1 January 0070", "1 January", "January 1", "0001", 0,
1077 "5 May 1997", 0, 0, 0, "5 May, 1997", "5 May 1997", "5 May", 0, "0005", 0,
1078 "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
1079 "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
1080 "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
1081 "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
1082 "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
1083};
1084#endif
1085
1086// -------------------------------------
1087
1088/**
1089 * Verify the correct behavior when parsing an array of inputs against an
1090 * array of patterns, with known results. The results are encoded after
1091 * the input strings in each row.
1092 */
1093void
1094DateFormatTest::TestBadInput135a()
1095{
1096 UErrorCode status = U_ZERO_ERROR;
1097 SimpleDateFormat* dateParse = new SimpleDateFormat(status);
1098 if(U_FAILURE(status)) {
1099 dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1100 delete dateParse;
1101 return;
1102 }
1103 const char* s;
1104 UDate date;
1105 const uint32_t PF_LENGTH = UPRV_LENGTHOF(parseFormats);
1106 const uint32_t INPUT_LENGTH = UPRV_LENGTHOF(inputStrings);
1107
1108 dateParse->applyPattern("d MMMM, yyyy");
1109 dateParse->adoptTimeZone(TimeZone::createDefault());
1110 s = "not parseable";
1111 UnicodeString thePat;
1112 logln(UnicodeString("Trying to parse \"") + s + "\" with " + dateParse->toPattern(thePat));
1113 //try {
1114 date = dateParse->parse(s, status);
1115 if (U_SUCCESS(status))
1116 errln((UnicodeString)"FAIL: Expected exception during parse");
1117 //}
1118 //catch(Exception ex) {
1119 else
1120 logln((UnicodeString)"Exception during parse: " + (int32_t)status);
1121 status = U_ZERO_ERROR;
1122 //}
1123 for (uint32_t i = 0; i < INPUT_LENGTH; i += (PF_LENGTH + 1)) {
1124 ParsePosition parsePosition(0);
1125 UnicodeString s( inputStrings[i]);
1126 for (uint32_t index = 0; index < PF_LENGTH;++index) {
1127 const char* expected = inputStrings[i + 1 + index];
1128 dateParse->applyPattern(parseFormats[index]);
1129 dateParse->adoptTimeZone(TimeZone::createDefault());
1130 //try {
1131 parsePosition.setIndex(0);
1132 date = dateParse->parse(s, parsePosition);
1133 if (parsePosition.getIndex() != 0) {
1134 UnicodeString s1, s2;
1135 s.extract(0, parsePosition.getIndex(), s1);
1136 s.extract(parsePosition.getIndex(), s.length(), s2);
1137 if (date == 0) {
1138 errln((UnicodeString)"ERROR: null result fmt=\"" +
1139 parseFormats[index] +
1140 "\" pos=" + parsePosition.getIndex() + " " +
1141 s1 + "|" + s2);
1142 }
1143 else {
1144 UnicodeString result;
1145 ((DateFormat*)dateParse)->format(date, result);
1146 logln((UnicodeString)"Parsed \"" + s + "\" using \"" + dateParse->toPattern(thePat) + "\" to: " + result);
1147 if (expected == 0)
1148 errln((UnicodeString)"FAIL: Expected parse failure, got " + result);
1149 else if (!(result == expected))
1150 errln(UnicodeString("FAIL: Parse \"") + s + UnicodeString("\", expected ") + expected + UnicodeString(", got ") + result);
1151 }
1152 }
1153 else if (expected != 0) {
1154 errln(UnicodeString("FAIL: Expected ") + expected + " from \"" +
1155 s + "\" with \"" + dateParse->toPattern(thePat) + "\"");
1156 }
1157 //}
1158 //catch(Exception ex) {
1159 if (U_FAILURE(status))
1160 errln((UnicodeString)"An exception was thrown during parse: " + (int32_t)status);
1161 //}
1162 }
1163 }
1164 delete dateParse;
1165 if (U_FAILURE(status))
1166 errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status);
1167}
1168
1169// -------------------------------------
1170
1171/**
1172 * Test the parsing of two-digit years.
1173 */
1174void
1175DateFormatTest::TestTwoDigitYear()
1176{
1177 UErrorCode ec = U_ZERO_ERROR;
1178 SimpleDateFormat fmt("dd/MM/yy", Locale::getUK(), ec);
1179 if (U_FAILURE(ec)) {
1180 dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1181 return;
1182 }
1183 parse2DigitYear(fmt, "5/6/30", date(130, UCAL_JUNE, 5));
1184 parse2DigitYear(fmt, "4/6/50", date(50, UCAL_JUNE, 4));
1185}
1186
1187// -------------------------------------
1188
1189void
1190DateFormatTest::parse2DigitYear(DateFormat& fmt, const char* str, UDate expected)
1191{
1192 UErrorCode status = U_ZERO_ERROR;
1193 //try {
1194 UDate d = fmt.parse(str, status);
1195 UnicodeString thePat;
1196 logln(UnicodeString("Parsing \"") + str + "\" with " + ((SimpleDateFormat*)&fmt)->toPattern(thePat) +
1197 " => " + dateToString(d));
1198 if (d != expected) errln((UnicodeString)"FAIL: Expected " + expected);
1199 //}
1200 //catch(ParseException e) {
1201 if (U_FAILURE(status))
1202 errln((UnicodeString)"FAIL: Got exception");
1203 //}
1204}
1205
1206// -------------------------------------
1207
1208/**
1209 * Test the formatting of time zones.
1210 */
1211void
1212DateFormatTest::TestDateFormatZone061()
1213{
1214 UErrorCode status = U_ZERO_ERROR;
1215 UDate date;
1216 DateFormat *formatter;
1217 date= 859248000000.0;
1218 logln((UnicodeString)"Date 1997/3/25 00:00 GMT: " + date);
1219 formatter = new SimpleDateFormat((UnicodeString)"dd-MMM-yyyyy HH:mm", Locale::getUK(), status);
1220 if(U_FAILURE(status)) {
1221 dataerrln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status));
1222 delete formatter;
1223 return;
1224 }
1225 formatter->adoptTimeZone(TimeZone::createTimeZone("GMT"));
1226 UnicodeString temp; formatter->format(date, temp);
1227 logln((UnicodeString)"Formatted in GMT to: " + temp);
1228 //try {
1229 UDate tempDate = formatter->parse(temp, status);
1230 logln((UnicodeString)"Parsed to: " + dateToString(tempDate));
1231 if (tempDate != date) errln((UnicodeString)"FAIL: Expected " + dateToString(date));
1232 //}
1233 //catch(Throwable t) {
1234 if (U_FAILURE(status))
1235 errln((UnicodeString)"Date Formatter throws: " + (int32_t)status);
1236 //}
1237 delete formatter;
1238}
1239
1240// -------------------------------------
1241
1242/**
1243 * Test the formatting of time zones.
1244 */
1245void
1246DateFormatTest::TestDateFormatZone146()
1247{
1248 TimeZone *saveDefault = TimeZone::createDefault();
1249
1250 //try {
1251 TimeZone *thedefault = TimeZone::createTimeZone("GMT");
1252 TimeZone::setDefault(*thedefault);
1253 // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
1254
1255 // check to be sure... its GMT all right
1256 TimeZone *testdefault = TimeZone::createDefault();
1257 UnicodeString testtimezone;
1258 testdefault->getID(testtimezone);
1259 if (testtimezone == "GMT")
1260 logln("Test timezone = " + testtimezone);
1261 else
1262 dataerrln("Test timezone should be GMT, not " + testtimezone);
1263
1264 UErrorCode status = U_ZERO_ERROR;
1265 // now try to use the default GMT time zone
1266 GregorianCalendar *greenwichcalendar =
1267 new GregorianCalendar(1997, 3, 4, 23, 0, status);
1268 if (U_FAILURE(status)) {
1269 dataerrln("Fail new GregorianCalendar: %s", u_errorName(status));
1270 } else {
1271 //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
1272 //greenwichcalendar.set(1997, 3, 4, 23, 0);
1273 // try anything to set hour to 23:00 !!!
1274 greenwichcalendar->set(UCAL_HOUR_OF_DAY, 23);
1275 // get time
1276 UDate greenwichdate = greenwichcalendar->getTime(status);
1277 // format every way
1278 UnicodeString DATA [] = {
1279 UnicodeString("simple format: "), UnicodeString("04/04/97 23:00 GMT"),
1280 UnicodeString("MM/dd/yy HH:mm z"),
1281 UnicodeString("full format: "), UnicodeString("Friday, April 4, 1997 11:00:00 o'clock PM GMT"),
1282 UnicodeString("EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z"),
1283 UnicodeString("long format: "), UnicodeString("April 4, 1997 11:00:00 PM GMT"),
1284 UnicodeString("MMMM d, yyyy h:mm:ss a z"),
1285 UnicodeString("default format: "), UnicodeString("04-Apr-97 11:00:00 PM"),
1286 UnicodeString("dd-MMM-yy h:mm:ss a"),
1287 UnicodeString("short format: "), UnicodeString("4/4/97 11:00 PM"),
1288 UnicodeString("M/d/yy h:mm a")
1289 };
1290 int32_t DATA_length = UPRV_LENGTHOF(DATA);
1291
1292 for (int32_t i=0; i<DATA_length; i+=3) {
1293 SimpleDateFormat fmt(DATA[i+2], Locale::getEnglish(), status);
1294 if (U_FAILURE(status)) {
1295 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
1296 break;
1297 }
1298 fmt.setCalendar(*greenwichcalendar);
1299 UnicodeString result;
1300 result = fmt.format(greenwichdate, result);
1301 logln(DATA[i] + result);
1302 if (result != DATA[i+1])
1303 errln("FAIL: Expected " + DATA[i+1] + ", got " + result);
1304 }
1305 }
1306 //}
1307 //finally {
1308 TimeZone::adoptDefault(saveDefault);
1309 //}
1310 delete testdefault;
1311 delete greenwichcalendar;
1312 delete thedefault;
1313
1314
1315}
1316
1317// -------------------------------------
1318
1319/**
1320 * Test the formatting of dates in different locales.
1321 */
1322void
1323DateFormatTest::TestLocaleDateFormat() // Bug 495
1324{
1325 UDate testDate = date(97, UCAL_SEPTEMBER, 15);
1326 DateFormat *dfFrench = DateFormat::createDateTimeInstance(DateFormat::FULL,
1327 DateFormat::FULL, Locale::getFrench());
1328 DateFormat *dfUS = DateFormat::createDateTimeInstance(DateFormat::FULL,
1329 DateFormat::FULL, Locale::getUS());
1330 UnicodeString expectedFRENCH ( "lundi 15 septembre 1997 \\u00E0 00:00:00 heure d\\u2019\\u00E9t\\u00E9 du Pacifique", -1, US_INV );
1331 expectedFRENCH = expectedFRENCH.unescape();
1332 UnicodeString expectedUS ( "Monday, September 15, 1997 at 12:00:00 AM Pacific Daylight Time" );
1333 logln((UnicodeString)"Date set to : " + dateToString(testDate));
1334 UnicodeString out;
1335 if (dfUS == NULL || dfFrench == NULL){
1336 dataerrln("Error calling DateFormat::createDateTimeInstance)");
1337 delete dfUS;
1338 delete dfFrench;
1339 return;
1340 }
1341
1342 dfFrench->format(testDate, out);
1343 logln((UnicodeString)"Date Formated with French Locale " + out);
1344 if (!(out == expectedFRENCH))
1345 errln((UnicodeString)"FAIL: Expected " + expectedFRENCH);
1346 out.truncate(0);
1347 dfUS->format(testDate, out);
1348 logln((UnicodeString)"Date Formated with US Locale " + out);
1349 if (!(out == expectedUS))
1350 errln((UnicodeString)"FAIL: Expected " + expectedUS);
1351 delete dfUS;
1352 delete dfFrench;
1353}
1354
1355void
1356DateFormatTest::TestFormattingLocaleTimeSeparator()
1357{
1358 // This test not as useful as it once was, since timeSeparator
1359 // in the Arabic locale is changed back to ":" in CLDR 28.
1360 const UDate testDate = 874266720000.; // Sun Sep 14 21:52:00 CET 1997
1361 logln((UnicodeString)"Date set to : " + dateToString(testDate));
1362
1363 const LocalPointer<const TimeZone> tz(TimeZone::createTimeZone("CET"));
1364
1365 const LocalPointer<DateFormat> dfArab(DateFormat::createTimeInstance(
1366 DateFormat::SHORT, Locale("ar", "EG")));
1367
1368 const LocalPointer<DateFormat> dfLatn(DateFormat::createTimeInstance(
1369 DateFormat::SHORT, Locale("ar", "EG", NULL, "numbers=latn")));
1370
1371 if (dfLatn.isNull() || dfArab.isNull()) {
1372 dataerrln("Error calling DateFormat::createTimeInstance()");
1373 return;
1374 }
1375
1376 dfArab->setTimeZone(*tz);
1377 dfLatn->setTimeZone(*tz);
1378
1379 const UnicodeString expectedArab = UnicodeString(
1380 "\\u0669:\\u0665\\u0662\\u00A0\\u0645", -1, US_INV).unescape();
1381
1382 const UnicodeString expectedLatn = UnicodeString(
1383 "9:52\\u00A0\\u0645", -1, US_INV).unescape();
1384
1385 UnicodeString actualArab;
1386 UnicodeString actualLatn;
1387
1388 dfArab->format(testDate, actualArab);
1389 dfLatn->format(testDate, actualLatn);
1390
1391 assertEquals("Arab", expectedArab, actualArab);
1392 assertEquals("Latn", expectedLatn, actualLatn);
1393}
1394
1395/**
1396 * Test DateFormat(Calendar) API
1397 */
1398void DateFormatTest::TestDateFormatCalendar() {
1399 DateFormat *date=0, *time=0, *full=0;
1400 Calendar *cal=0;
1401 UnicodeString str;
1402 ParsePosition pos;
1403 UDate when;
1404 UErrorCode ec = U_ZERO_ERROR;
1405
1406 /* Create a formatter for date fields. */
1407 date = DateFormat::createDateInstance(DateFormat::kShort, Locale::getUS());
1408 if (date == NULL) {
1409 dataerrln("FAIL: createDateInstance failed");
1410 goto FAIL;
1411 }
1412
1413 /* Create a formatter for time fields. */
1414 time = DateFormat::createTimeInstance(DateFormat::kShort, Locale::getUS());
1415 if (time == NULL) {
1416 errln("FAIL: createTimeInstance failed");
1417 goto FAIL;
1418 }
1419
1420 /* Create a full format for output */
1421 full = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull,
1422 Locale::getUS());
1423 if (full == NULL) {
1424 errln("FAIL: createInstance failed");
1425 goto FAIL;
1426 }
1427
1428 /* Create a calendar */
1429 cal = Calendar::createInstance(Locale::getUS(), ec);
1430 if (cal == NULL || U_FAILURE(ec)) {
1431 errln((UnicodeString)"FAIL: Calendar::createInstance failed with " +
1432 u_errorName(ec));
1433 goto FAIL;
1434 }
1435
1436 /* Parse the date */
1437 cal->clear();
1438 str = UnicodeString("4/5/2001", "");
1439 pos.setIndex(0);
1440 date->parse(str, *cal, pos);
1441 if (pos.getIndex() != str.length()) {
1442 errln((UnicodeString)"FAIL: DateFormat::parse(4/5/2001) failed at " +
1443 pos.getIndex());
1444 goto FAIL;
1445 }
1446
1447 /* Parse the time */
1448 str = UnicodeString("5:45 PM", "");
1449 pos.setIndex(0);
1450 time->parse(str, *cal, pos);
1451 if (pos.getIndex() != str.length()) {
1452 errln((UnicodeString)"FAIL: DateFormat::parse(17:45) failed at " +
1453 pos.getIndex());
1454 goto FAIL;
1455 }
1456
1457 /* Check result */
1458 when = cal->getTime(ec);
1459 if (U_FAILURE(ec)) {
1460 errln((UnicodeString)"FAIL: cal->getTime() failed with " + u_errorName(ec));
1461 goto FAIL;
1462 }
1463 str.truncate(0);
1464 full->format(when, str);
1465 // Thursday, April 5, 2001 5:45:00 PM PDT 986517900000
1466 if (when == 986517900000.0) {
1467 logln("Ok: Parsed result: " + str);
1468 } else {
1469 errln("FAIL: Parsed result: " + str + ", exp 4/5/2001 5:45 PM");
1470 }
1471
1472 FAIL:
1473 delete date;
1474 delete time;
1475 delete full;
1476 delete cal;
1477}
1478
1479/**
1480 * Test DateFormat's parsing of space characters. See jitterbug 1916.
1481 */
1482void DateFormatTest::TestSpaceParsing() {
1483 const char* DATA[] = {
1484 "yyyy MM dd HH:mm:ss",
1485
1486 // pattern, input, expected parse or NULL if expect parse failure
1487 "MMMM d yy", " 04 05 06", "2006 04 05 00:00:00",
1488 NULL, "04 05 06", "2006 04 05 00:00:00",
1489
1490 "MM d yy", " 04 05 06", "2006 04 05 00:00:00",
1491 NULL, "04 05 06", "2006 04 05 00:00:00",
1492 NULL, "04/05/06", "2006 04 05 00:00:00",
1493 NULL, "04-05-06", "2006 04 05 00:00:00",
1494 NULL, "04.05.06", "2006 04 05 00:00:00",
1495 NULL, "04 / 05 / 06", "2006 04 05 00:00:00",
1496 NULL, "Apr / 05/ 06", "2006 04 05 00:00:00",
1497 NULL, "Apr-05-06", "2006 04 05 00:00:00",
1498 NULL, "Apr 05, 2006", "2006 04 05 00:00:00",
1499
1500 "MMMM d yy", " Apr 05 06", "2006 04 05 00:00:00",
1501 NULL, "Apr 05 06", "2006 04 05 00:00:00",
1502 NULL, "Apr05 06", "2006 04 05 00:00:00",
1503
1504 "hh:mm:ss a", "12:34:56 PM", "1970 01 01 12:34:56",
1505 NULL, "12:34:56PM", "1970 01 01 12:34:56",
1506 NULL, "12.34.56PM", "1970 01 01 12:34:56",
1507 NULL, "12 : 34 : 56 PM", "1970 01 01 12:34:56",
1508
1509 "MM d yy 'at' hh:mm:ss a", "04/05/06 12:34:56 PM", "2006 04 05 12:34:56",
1510
1511 "MMMM dd yyyy hh:mm a", "September 27, 1964 21:56 PM", "1964 09 28 09:56:00",
1512 NULL, "November 4, 2008 0:13 AM", "2008 11 04 00:13:00",
1513
1514 "HH'h'mm'min'ss's'", "12h34min56s", "1970 01 01 12:34:56",
1515 NULL, "12h34mi56s", "1970 01 01 12:34:56",
1516 NULL, "12h34m56s", "1970 01 01 12:34:56",
1517 NULL, "12:34:56", "1970 01 01 12:34:56"
1518 };
1519 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1520
1521 expectParse(DATA, DATA_len, Locale("en"));
1522}
1523
1524/**
1525 * Test handling of "HHmmss" pattern.
1526 */
1527void DateFormatTest::TestExactCountFormat() {
1528 const char* DATA[] = {
1529 "yyyy MM dd HH:mm:ss",
1530
1531 // pattern, input, expected parse or NULL if expect parse failure
1532 "HHmmss", "123456", "1970 01 01 12:34:56",
1533 NULL, "12345", "1970 01 01 01:23:45",
1534 NULL, "1234", NULL,
1535 NULL, "00-05", NULL,
1536 NULL, "12-34", NULL,
1537 NULL, "00+05", NULL,
1538 "ahhmm", "PM730", "1970 01 01 19:30:00",
1539 };
1540 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1541
1542 expectParse(DATA, DATA_len, Locale("en"));
1543}
1544
1545/**
1546 * Test handling of white space.
1547 */
1548void DateFormatTest::TestWhiteSpaceParsing() {
1549 const char* DATA[] = {
1550 "yyyy MM dd",
1551
1552 // pattern, input, expected parse or null if expect parse failure
1553
1554 // Pattern space run should parse input text space run
1555 "MM d yy", " 04 01 03", "2003 04 01",
1556 NULL, " 04 01 03 ", "2003 04 01",
1557 };
1558 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
1559
1560 expectParse(DATA, DATA_len, Locale("en"));
1561}
1562
1563
1564void DateFormatTest::TestInvalidPattern() {
1565 UErrorCode ec = U_ZERO_ERROR;
1566 SimpleDateFormat f(UnicodeString("Yesterday"), ec);
1567 if (U_FAILURE(ec)) {
1568 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1569 return;
1570 }
1571 UnicodeString out;
1572 FieldPosition pos;
1573 f.format((UDate)0, out, pos);
1574 logln(out);
1575 // The bug is that the call to format() will crash. By not
1576 // crashing, the test passes.
1577}
1578
1579void DateFormatTest::TestGreekMay() {
1580 UErrorCode ec = U_ZERO_ERROR;
1581 UDate date = -9896080848000.0;
1582 SimpleDateFormat fmt("EEEE, dd MMMM yyyy h:mm:ss a", Locale("el", "", ""), ec);
1583 if (U_FAILURE(ec)) {
1584 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
1585 return;
1586 }
1587 UnicodeString str;
1588 fmt.format(date, str);
1589 ParsePosition pos(0);
1590 UDate d2 = fmt.parse(str, pos);
1591 if (date != d2) {
1592 errln("FAIL: unable to parse strings where case-folding changes length");
1593 }
1594}
1595
1596void DateFormatTest::TestStandAloneMonths()
1597{
1598 const char *EN_DATA[] = {
1599 "yyyy MM dd HH:mm:ss",
1600
1601 "yyyy LLLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 March 10 16:36:31", "2004 03 10 16:36:31",
1602 "yyyy LLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31",
1603 "yyyy LLLL dd H:mm:ss", "F", "2004 03 10 16:36:31", "2004 March 10 16:36:31",
1604 "yyyy LLL dd H:mm:ss", "pf", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31",
1605
1606 "LLLL", "fp", "1970 01 01 0:00:00", "January", "1970 01 01 0:00:00",
1607 "LLLL", "fp", "1970 02 01 0:00:00", "February", "1970 02 01 0:00:00",
1608 "LLLL", "fp", "1970 03 01 0:00:00", "March", "1970 03 01 0:00:00",
1609 "LLLL", "fp", "1970 04 01 0:00:00", "April", "1970 04 01 0:00:00",
1610 "LLLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1611 "LLLL", "fp", "1970 06 01 0:00:00", "June", "1970 06 01 0:00:00",
1612 "LLLL", "fp", "1970 07 01 0:00:00", "July", "1970 07 01 0:00:00",
1613 "LLLL", "fp", "1970 08 01 0:00:00", "August", "1970 08 01 0:00:00",
1614 "LLLL", "fp", "1970 09 01 0:00:00", "September", "1970 09 01 0:00:00",
1615 "LLLL", "fp", "1970 10 01 0:00:00", "October", "1970 10 01 0:00:00",
1616 "LLLL", "fp", "1970 11 01 0:00:00", "November", "1970 11 01 0:00:00",
1617 "LLLL", "fp", "1970 12 01 0:00:00", "December", "1970 12 01 0:00:00",
1618
1619 "LLL", "fp", "1970 01 01 0:00:00", "Jan", "1970 01 01 0:00:00",
1620 "LLL", "fp", "1970 02 01 0:00:00", "Feb", "1970 02 01 0:00:00",
1621 "LLL", "fp", "1970 03 01 0:00:00", "Mar", "1970 03 01 0:00:00",
1622 "LLL", "fp", "1970 04 01 0:00:00", "Apr", "1970 04 01 0:00:00",
1623 "LLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1624 "LLL", "fp", "1970 06 01 0:00:00", "Jun", "1970 06 01 0:00:00",
1625 "LLL", "fp", "1970 07 01 0:00:00", "Jul", "1970 07 01 0:00:00",
1626 "LLL", "fp", "1970 08 01 0:00:00", "Aug", "1970 08 01 0:00:00",
1627 "LLL", "fp", "1970 09 01 0:00:00", "Sep", "1970 09 01 0:00:00",
1628 "LLL", "fp", "1970 10 01 0:00:00", "Oct", "1970 10 01 0:00:00",
1629 "LLL", "fp", "1970 11 01 0:00:00", "Nov", "1970 11 01 0:00:00",
1630 "LLL", "fp", "1970 12 01 0:00:00", "Dec", "1970 12 01 0:00:00",
1631 };
1632
1633 const char *CS_DATA[] = {
1634 "yyyy MM dd HH:mm:ss",
1635
1636 "yyyy LLLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 duben 10 16:36:31", "2004 04 10 16:36:31",
1637 "yyyy MMMM dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31",
1638 "yyyy LLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 dub 10 16:36:31", "2004 04 10 16:36:31",
1639 "yyyy LLLL dd H:mm:ss", "F", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1640 "yyyy MMMM dd H:mm:ss", "F", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1641 "yyyy LLLL dd H:mm:ss", "pf", "2004 duben 10 16:36:31", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1642 "yyyy MMMM dd H:mm:ss", "pf", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1643
1644 "LLLL", "fp", "1970 01 01 0:00:00", "leden", "1970 01 01 0:00:00",
1645 "LLLL", "fp", "1970 02 01 0:00:00", "\\u00FAnor", "1970 02 01 0:00:00",
1646 "LLLL", "fp", "1970 03 01 0:00:00", "b\\u0159ezen", "1970 03 01 0:00:00",
1647 "LLLL", "fp", "1970 04 01 0:00:00", "duben", "1970 04 01 0:00:00",
1648 "LLLL", "fp", "1970 05 01 0:00:00", "kv\\u011Bten", "1970 05 01 0:00:00",
1649 "LLLL", "fp", "1970 06 01 0:00:00", "\\u010Derven", "1970 06 01 0:00:00",
1650 "LLLL", "fp", "1970 07 01 0:00:00", "\\u010Dervenec", "1970 07 01 0:00:00",
1651 "LLLL", "fp", "1970 08 01 0:00:00", "srpen", "1970 08 01 0:00:00",
1652 "LLLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159\\u00ED", "1970 09 01 0:00:00",
1653 "LLLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDjen", "1970 10 01 0:00:00",
1654 "LLLL", "fp", "1970 11 01 0:00:00", "listopad", "1970 11 01 0:00:00",
1655 "LLLL", "fp", "1970 12 01 0:00:00", "prosinec", "1970 12 01 0:00:00",
1656
1657 "LLL", "fp", "1970 01 01 0:00:00", "led", "1970 01 01 0:00:00",
1658 "LLL", "fp", "1970 02 01 0:00:00", "\\u00FAno", "1970 02 01 0:00:00",
1659 "LLL", "fp", "1970 03 01 0:00:00", "b\\u0159e", "1970 03 01 0:00:00",
1660 "LLL", "fp", "1970 04 01 0:00:00", "dub", "1970 04 01 0:00:00",
1661 "LLL", "fp", "1970 05 01 0:00:00", "kv\\u011B", "1970 05 01 0:00:00",
1662 "LLL", "fp", "1970 06 01 0:00:00", "\\u010Dvn", "1970 06 01 0:00:00",
1663 "LLL", "fp", "1970 07 01 0:00:00", "\\u010Dvc", "1970 07 01 0:00:00",
1664 "LLL", "fp", "1970 08 01 0:00:00", "srp", "1970 08 01 0:00:00",
1665 "LLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159", "1970 09 01 0:00:00",
1666 "LLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDj", "1970 10 01 0:00:00",
1667 "LLL", "fp", "1970 11 01 0:00:00", "lis", "1970 11 01 0:00:00",
1668 "LLL", "fp", "1970 12 01 0:00:00", "pro", "1970 12 01 0:00:00",
1669 };
1670
1671 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1672 expect(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1673}
1674
1675void DateFormatTest::TestStandAloneDays()
1676{
1677 const char *EN_DATA[] = {
1678 "yyyy MM dd HH:mm:ss",
1679
1680 "cccc", "fp", "1970 01 04 0:00:00", "Sunday", "1970 01 04 0:00:00",
1681 "cccc", "fp", "1970 01 05 0:00:00", "Monday", "1970 01 05 0:00:00",
1682 "cccc", "fp", "1970 01 06 0:00:00", "Tuesday", "1970 01 06 0:00:00",
1683 "cccc", "fp", "1970 01 07 0:00:00", "Wednesday", "1970 01 07 0:00:00",
1684 "cccc", "fp", "1970 01 01 0:00:00", "Thursday", "1970 01 01 0:00:00",
1685 "cccc", "fp", "1970 01 02 0:00:00", "Friday", "1970 01 02 0:00:00",
1686 "cccc", "fp", "1970 01 03 0:00:00", "Saturday", "1970 01 03 0:00:00",
1687
1688 "ccc", "fp", "1970 01 04 0:00:00", "Sun", "1970 01 04 0:00:00",
1689 "ccc", "fp", "1970 01 05 0:00:00", "Mon", "1970 01 05 0:00:00",
1690 "ccc", "fp", "1970 01 06 0:00:00", "Tue", "1970 01 06 0:00:00",
1691 "ccc", "fp", "1970 01 07 0:00:00", "Wed", "1970 01 07 0:00:00",
1692 "ccc", "fp", "1970 01 01 0:00:00", "Thu", "1970 01 01 0:00:00",
1693 "ccc", "fp", "1970 01 02 0:00:00", "Fri", "1970 01 02 0:00:00",
1694 "ccc", "fp", "1970 01 03 0:00:00", "Sat", "1970 01 03 0:00:00",
1695 };
1696
1697 const char *CS_DATA[] = {
1698 "yyyy MM dd HH:mm:ss",
1699
1700 "cccc", "fp", "1970 01 04 0:00:00", "ned\\u011Ble", "1970 01 04 0:00:00",
1701 "cccc", "fp", "1970 01 05 0:00:00", "pond\\u011Bl\\u00ED", "1970 01 05 0:00:00",
1702 "cccc", "fp", "1970 01 06 0:00:00", "\\u00FAter\\u00FD", "1970 01 06 0:00:00",
1703 "cccc", "fp", "1970 01 07 0:00:00", "st\\u0159eda", "1970 01 07 0:00:00",
1704 "cccc", "fp", "1970 01 01 0:00:00", "\\u010Dtvrtek", "1970 01 01 0:00:00",
1705 "cccc", "fp", "1970 01 02 0:00:00", "p\\u00E1tek", "1970 01 02 0:00:00",
1706 "cccc", "fp", "1970 01 03 0:00:00", "sobota", "1970 01 03 0:00:00",
1707
1708 "ccc", "fp", "1970 01 04 0:00:00", "ne", "1970 01 04 0:00:00",
1709 "ccc", "fp", "1970 01 05 0:00:00", "po", "1970 01 05 0:00:00",
1710 "ccc", "fp", "1970 01 06 0:00:00", "\\u00FAt", "1970 01 06 0:00:00",
1711 "ccc", "fp", "1970 01 07 0:00:00", "st", "1970 01 07 0:00:00",
1712 "ccc", "fp", "1970 01 01 0:00:00", "\\u010Dt", "1970 01 01 0:00:00",
1713 "ccc", "fp", "1970 01 02 0:00:00", "p\\u00E1", "1970 01 02 0:00:00",
1714 "ccc", "fp", "1970 01 03 0:00:00", "so", "1970 01 03 0:00:00",
1715 };
1716
1717 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1718 expect(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1719}
1720
1721void DateFormatTest::TestShortDays()
1722{
1723 const char *EN_DATA[] = {
1724 "yyyy MM dd HH:mm:ss",
1725
1726 "EEEEEE, MMM d y", "fp", "2013 01 13 0:00:00", "Su, Jan 13 2013", "2013 01 13 0:00:00",
1727 "EEEEEE, MMM d y", "fp", "2013 01 16 0:00:00", "We, Jan 16 2013", "2013 01 16 0:00:00",
1728 "EEEEEE d", "fp", "1970 01 17 0:00:00", "Sa 17", "1970 01 17 0:00:00",
1729 "cccccc d", "fp", "1970 01 17 0:00:00", "Sa 17", "1970 01 17 0:00:00",
1730 "cccccc", "fp", "1970 01 03 0:00:00", "Sa", "1970 01 03 0:00:00",
1731 };
1732 const char *SV_DATA[] = {
1733 "yyyy MM dd HH:mm:ss",
1734
1735 "EEEEEE d MMM y", "fp", "2013 01 13 0:00:00", "s\\u00F6 13 jan. 2013", "2013 01 13 0:00:00",
1736 "EEEEEE d MMM y", "fp", "2013 01 16 0:00:00", "on 16 jan. 2013", "2013 01 16 0:00:00",
1737 "EEEEEE d", "fp", "1970 01 17 0:00:00", "l\\u00F6 17", "1970 01 17 0:00:00",
1738 "cccccc d", "fp", "1970 01 17 0:00:00", "l\\u00F6 17", "1970 01 17 0:00:00",
1739 "cccccc", "fp", "1970 01 03 0:00:00", "l\\u00F6", "1970 01 03 0:00:00",
1740 };
1741 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1742 expect(SV_DATA, UPRV_LENGTHOF(SV_DATA), Locale("sv", "", ""));
1743}
1744
1745void DateFormatTest::TestNarrowNames()
1746{
1747 const char *EN_DATA[] = {
1748 "yyyy MM dd HH:mm:ss",
1749
1750 "yyyy MMMMM dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1751 "yyyy LLLLL dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1752
1753 "MMMMM", "1970 01 01 0:00:00", "J",
1754 "MMMMM", "1970 02 01 0:00:00", "F",
1755 "MMMMM", "1970 03 01 0:00:00", "M",
1756 "MMMMM", "1970 04 01 0:00:00", "A",
1757 "MMMMM", "1970 05 01 0:00:00", "M",
1758 "MMMMM", "1970 06 01 0:00:00", "J",
1759 "MMMMM", "1970 07 01 0:00:00", "J",
1760 "MMMMM", "1970 08 01 0:00:00", "A",
1761 "MMMMM", "1970 09 01 0:00:00", "S",
1762 "MMMMM", "1970 10 01 0:00:00", "O",
1763 "MMMMM", "1970 11 01 0:00:00", "N",
1764 "MMMMM", "1970 12 01 0:00:00", "D",
1765
1766 "LLLLL", "1970 01 01 0:00:00", "J",
1767 "LLLLL", "1970 02 01 0:00:00", "F",
1768 "LLLLL", "1970 03 01 0:00:00", "M",
1769 "LLLLL", "1970 04 01 0:00:00", "A",
1770 "LLLLL", "1970 05 01 0:00:00", "M",
1771 "LLLLL", "1970 06 01 0:00:00", "J",
1772 "LLLLL", "1970 07 01 0:00:00", "J",
1773 "LLLLL", "1970 08 01 0:00:00", "A",
1774 "LLLLL", "1970 09 01 0:00:00", "S",
1775 "LLLLL", "1970 10 01 0:00:00", "O",
1776 "LLLLL", "1970 11 01 0:00:00", "N",
1777 "LLLLL", "1970 12 01 0:00:00", "D",
1778
1779 "EEEEE", "1970 01 04 0:00:00", "S",
1780 "EEEEE", "1970 01 05 0:00:00", "M",
1781 "EEEEE", "1970 01 06 0:00:00", "T",
1782 "EEEEE", "1970 01 07 0:00:00", "W",
1783 "EEEEE", "1970 01 01 0:00:00", "T",
1784 "EEEEE", "1970 01 02 0:00:00", "F",
1785 "EEEEE", "1970 01 03 0:00:00", "S",
1786
1787 "ccccc", "1970 01 04 0:00:00", "S",
1788 "ccccc", "1970 01 05 0:00:00", "M",
1789 "ccccc", "1970 01 06 0:00:00", "T",
1790 "ccccc", "1970 01 07 0:00:00", "W",
1791 "ccccc", "1970 01 01 0:00:00", "T",
1792 "ccccc", "1970 01 02 0:00:00", "F",
1793 "ccccc", "1970 01 03 0:00:00", "S",
1794
1795 "h:mm a", "2015 01 01 10:00:00", "10:00 AM",
1796 "h:mm a", "2015 01 01 22:00:00", "10:00 PM",
1797 "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a",
1798 "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p",
1799 };
1800
1801 const char *CS_DATA[] = {
1802 "yyyy MM dd HH:mm:ss",
1803
1804 "yyyy LLLLL dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1805 "yyyy MMMMM dd H:mm:ss", "2004 04 10 16:36:31", "2004 4 10 16:36:31",
1806
1807 "MMMMM", "1970 01 01 0:00:00", "1",
1808 "MMMMM", "1970 02 01 0:00:00", "2",
1809 "MMMMM", "1970 03 01 0:00:00", "3",
1810 "MMMMM", "1970 04 01 0:00:00", "4",
1811 "MMMMM", "1970 05 01 0:00:00", "5",
1812 "MMMMM", "1970 06 01 0:00:00", "6",
1813 "MMMMM", "1970 07 01 0:00:00", "7",
1814 "MMMMM", "1970 08 01 0:00:00", "8",
1815 "MMMMM", "1970 09 01 0:00:00", "9",
1816 "MMMMM", "1970 10 01 0:00:00", "10",
1817 "MMMMM", "1970 11 01 0:00:00", "11",
1818 "MMMMM", "1970 12 01 0:00:00", "12",
1819
1820 "LLLLL", "1970 01 01 0:00:00", "1",
1821 "LLLLL", "1970 02 01 0:00:00", "2",
1822 "LLLLL", "1970 03 01 0:00:00", "3",
1823 "LLLLL", "1970 04 01 0:00:00", "4",
1824 "LLLLL", "1970 05 01 0:00:00", "5",
1825 "LLLLL", "1970 06 01 0:00:00", "6",
1826 "LLLLL", "1970 07 01 0:00:00", "7",
1827 "LLLLL", "1970 08 01 0:00:00", "8",
1828 "LLLLL", "1970 09 01 0:00:00", "9",
1829 "LLLLL", "1970 10 01 0:00:00", "10",
1830 "LLLLL", "1970 11 01 0:00:00", "11",
1831 "LLLLL", "1970 12 01 0:00:00", "12",
1832
1833 "EEEEE", "1970 01 04 0:00:00", "N",
1834 "EEEEE", "1970 01 05 0:00:00", "P",
1835 "EEEEE", "1970 01 06 0:00:00", "\\u00DA",
1836 "EEEEE", "1970 01 07 0:00:00", "S",
1837 "EEEEE", "1970 01 01 0:00:00", "\\u010C",
1838 "EEEEE", "1970 01 02 0:00:00", "P",
1839 "EEEEE", "1970 01 03 0:00:00", "S",
1840
1841 "ccccc", "1970 01 04 0:00:00", "N",
1842 "ccccc", "1970 01 05 0:00:00", "P",
1843 "ccccc", "1970 01 06 0:00:00", "\\u00DA",
1844 "ccccc", "1970 01 07 0:00:00", "S",
1845 "ccccc", "1970 01 01 0:00:00", "\\u010C",
1846 "ccccc", "1970 01 02 0:00:00", "P",
1847 "ccccc", "1970 01 03 0:00:00", "S",
1848
1849 "h:mm a", "2015 01 01 10:00:00", "10:00 dop.",
1850 "h:mm a", "2015 01 01 22:00:00", "10:00 odp.",
1851 "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 dop.",
1852 "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 odp.",
1853 };
1854
1855 const char *CA_DATA[] = {
1856 "yyyy MM dd HH:mm:ss",
1857
1858 "h:mm a", "2015 01 01 10:00:00", "10:00 a.\\u00A0m.",
1859 "h:mm a", "2015 01 01 22:00:00", "10:00 p.\\u00A0m.",
1860 "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a.m.",
1861 "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p.m.",
1862 };
1863
1864 expectFormat(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1865 expectFormat(CS_DATA, UPRV_LENGTHOF(CS_DATA), Locale("cs", "", ""));
1866 expectFormat(CA_DATA, UPRV_LENGTHOF(CA_DATA), Locale("ca", "", ""));
1867}
1868
1869void DateFormatTest::TestEras()
1870{
1871 const char *EN_DATA[] = {
1872 "yyyy MM dd",
1873
1874 "MMMM dd yyyy G", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1875 "MMMM dd yyyy GG", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1876 "MMMM dd yyyy GGG", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1877 "MMMM dd yyyy GGGG", "fp", "1951 07 17", "July 17 1951 Anno Domini", "1951 07 17",
1878
1879 "MMMM dd yyyy G", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1880 "MMMM dd yyyy GG", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1881 "MMMM dd yyyy GGG", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1882 "MMMM dd yyyy GGGG", "fp", "-438 07 17", "July 17 0439 Before Christ", "-438 07 17",
1883 };
1884
1885 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1886}
1887
1888void DateFormatTest::TestQuarters()
1889{
1890 const char *EN_DATA[] = {
1891 "yyyy MM dd",
1892
1893 "Q", "fp", "1970 01 01", "1", "1970 01 01",
1894 "QQ", "fp", "1970 04 01", "02", "1970 04 01",
1895 "QQQ", "fp", "1970 07 01", "Q3", "1970 07 01",
1896 "QQQQ", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1897
1898 "q", "fp", "1970 01 01", "1", "1970 01 01",
1899 "qq", "fp", "1970 04 01", "02", "1970 04 01",
1900 "qqq", "fp", "1970 07 01", "Q3", "1970 07 01",
1901 "qqqq", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1902
1903 "Qyy", "fp", "2015 04 01", "215", "2015 04 01",
1904 "QQyy", "fp", "2015 07 01", "0315", "2015 07 01",
1905 };
1906
1907 expect(EN_DATA, UPRV_LENGTHOF(EN_DATA), Locale("en", "", ""));
1908}
1909
1910/**
1911 * Test parsing. Input is an array that starts with the following
1912 * header:
1913 *
1914 * [0] = pattern string to parse [i+2] with
1915 *
1916 * followed by test cases, each of which is 3 array elements:
1917 *
1918 * [i] = pattern, or NULL to reuse prior pattern
1919 * [i+1] = input string
1920 * [i+2] = expected parse result (parsed with pattern [0])
1921 *
1922 * If expect parse failure, then [i+2] should be NULL.
1923 */
1924void DateFormatTest::expectParse(const char** data, int32_t data_length,
1925 const Locale& loc) {
1926 const UDate FAIL = (UDate) -1;
1927 const UnicodeString FAIL_STR("parse failure");
1928 int32_t i = 0;
1929
1930 UErrorCode ec = U_ZERO_ERROR;
1931 SimpleDateFormat fmt("", loc, ec);
1932 SimpleDateFormat ref(data[i++], loc, ec);
1933 SimpleDateFormat gotfmt("G yyyy MM dd HH:mm:ss z", loc, ec);
1934 if (U_FAILURE(ec)) {
1935 dataerrln("FAIL: SimpleDateFormat constructor - %s", u_errorName(ec));
1936 return;
1937 }
1938
1939 const char* currentPat = NULL;
1940 while (i<data_length) {
1941 const char* pattern = data[i++];
1942 const char* input = data[i++];
1943 const char* expected = data[i++];
1944
1945 ec = U_ZERO_ERROR;
1946 if (pattern != NULL) {
1947 fmt.applyPattern(pattern);
1948 currentPat = pattern;
1949 }
1950 UDate got = fmt.parse(input, ec);
1951 UnicodeString gotstr(FAIL_STR);
1952 if (U_FAILURE(ec)) {
1953 got = FAIL;
1954 } else {
1955 gotstr.remove();
1956 gotfmt.format(got, gotstr);
1957 }
1958
1959 UErrorCode ec2 = U_ZERO_ERROR;
1960 UDate exp = FAIL;
1961 UnicodeString expstr(FAIL_STR);
1962 if (expected != NULL) {
1963 expstr = expected;
1964 exp = ref.parse(expstr, ec2);
1965 if (U_FAILURE(ec2)) {
1966 // This only happens if expected is in wrong format --
1967 // should never happen once test is debugged.
1968 errln("FAIL: Internal test error");
1969 return;
1970 }
1971 }
1972
1973 if (got == exp) {
1974 logln((UnicodeString)"Ok: " + input + " x " +
1975 currentPat + " => " + gotstr);
1976 } else {
1977 errln((UnicodeString)"FAIL: " + input + " x " +
1978 currentPat + " => " + gotstr + ", expected " +
1979 expstr);
1980 }
1981 }
1982}
1983
1984/**
1985 * Test formatting and parsing. Input is an array that starts
1986 * with the following header:
1987 *
1988 * [0] = pattern string to parse [i+2] with
1989 *
1990 * followed by test cases, each of which is 3 array elements:
1991 *
1992 * [i] = pattern, or null to reuse prior pattern
1993 * [i+1] = control string, either "fp", "pf", or "F".
1994 * [i+2..] = data strings
1995 *
1996 * The number of data strings depends on the control string.
1997 * Examples:
1998 * 1. "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.56", "2004 03 10 16:36:31.560",
1999 * 'f': Format date [i+2] (as parsed using pattern [0]) and expect string [i+3].
2000 * 'p': Parse string [i+3] and expect date [i+4].
2001 *
2002 * 2. "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567"
2003 * 'F': Format date [i+2] and expect string [i+3],
2004 * then parse string [i+3] and expect date [i+2].
2005 *
2006 * 3. "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.5670",
2007 * 'p': Parse string [i+2] and expect date [i+3].
2008 * 'f': Format date [i+3] and expect string [i+4].
2009 */
2010void DateFormatTest::expect(const char** data, int32_t data_length,
2011 const Locale& loc) {
2012 int32_t i = 0;
2013 UErrorCode ec = U_ZERO_ERROR;
2014 UnicodeString str, str2;
2015 SimpleDateFormat fmt("", loc, ec);
2016 SimpleDateFormat ref(data[i++], loc, ec);
2017 SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2018 if (U_FAILURE(ec)) {
2019 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2020 return;
2021 }
2022
2023 UnicodeString currentPat;
2024 while (i<data_length) {
2025 const char* pattern = data[i++];
2026 if (pattern != NULL) {
2027 fmt.applyPattern(pattern);
2028 currentPat = pattern;
2029 }
2030
2031 const char* control = data[i++];
2032
2033 if (uprv_strcmp(control, "fp") == 0) {
2034 // 'f'
2035 const char* datestr = data[i++];
2036 const char* string = data[i++];
2037 UDate date = ref.parse(ctou(datestr), ec);
2038 if (!assertSuccess("parse", ec)) return;
2039 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2040 ctou(string),
2041 fmt.format(date, str.remove()));
2042 // 'p'
2043 datestr = data[i++];
2044 date = ref.parse(ctou(datestr), ec);
2045 if (!assertSuccess("parse", ec)) return;
2046 UDate parsedate = fmt.parse(ctou(string), ec);
2047 if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2048 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2049 univ.format(date, str.remove()),
2050 univ.format(parsedate, str2.remove()));
2051 }
2052 }
2053
2054 else if (uprv_strcmp(control, "pf") == 0) {
2055 // 'p'
2056 const char* string = data[i++];
2057 const char* datestr = data[i++];
2058 UDate date = ref.parse(ctou(datestr), ec);
2059 if (!assertSuccess("parse", ec)) return;
2060 UDate parsedate = fmt.parse(ctou(string), ec);
2061 if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2062 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2063 univ.format(date, str.remove()),
2064 univ.format(parsedate, str2.remove()));
2065 }
2066 // 'f'
2067 string = data[i++];
2068 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2069 ctou(string),
2070 fmt.format(date, str.remove()));
2071 }
2072
2073 else if (uprv_strcmp(control, "F") == 0) {
2074 const char* datestr = data[i++];
2075 const char* string = data[i++];
2076 UDate date = ref.parse(ctou(datestr), ec);
2077 if (!assertSuccess("parse", ec)) return;
2078 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2079 ctou(string),
2080 fmt.format(date, str.remove()));
2081
2082 UDate parsedate = fmt.parse(string, ec);
2083 if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) {
2084 assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")",
2085 univ.format(date, str.remove()),
2086 univ.format(parsedate, str2.remove()));
2087 }
2088 }
2089
2090 else {
2091 errln((UnicodeString)"FAIL: Invalid control string " + control);
2092 return;
2093 }
2094 }
2095}
2096
2097/**
2098 * Test formatting. Input is an array that starts
2099 * with the following header:
2100 *
2101 * [0] = pattern string to parse [i+2] with
2102 *
2103 * followed by test cases, each of which is 3 array elements:
2104 *
2105 * [i] = pattern, or null to reuse prior pattern
2106 * [i+1] = data string a
2107 * [i+2] = data string b
2108 *
2109 * Examples:
2110 * Format date [i+1] and expect string [i+2].
2111 *
2112 * "y/M/d H:mm:ss.SSSS", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567"
2113 */
2114void DateFormatTest::expectFormat(const char** data, int32_t data_length,
2115 const Locale& loc) {
2116 int32_t i = 0;
2117 UErrorCode ec = U_ZERO_ERROR;
2118 UnicodeString str, str2;
2119 SimpleDateFormat fmt("", loc, ec);
2120 SimpleDateFormat ref(data[i++], loc, ec);
2121 SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec);
2122 if (U_FAILURE(ec)) {
2123 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(ec));
2124 return;
2125 }
2126
2127 UnicodeString currentPat;
2128
2129 while (i<data_length) {
2130 const char* pattern = data[i++];
2131 if (pattern != NULL) {
2132 fmt.applyPattern(pattern);
2133 currentPat = pattern;
2134 }
2135
2136 const char* datestr = data[i++];
2137 const char* string = data[i++];
2138 UDate date = ref.parse(ctou(datestr), ec);
2139 if (!assertSuccess("parse", ec)) return;
2140 assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")",
2141 ctou(string),
2142 fmt.format(date, str.remove()));
2143 }
2144}
2145
2146void DateFormatTest::TestGenericTime() {
2147 const Locale en("en");
2148 // Note: We no longer parse strings in different styles.
2149/*
2150 const char* ZDATA[] = {
2151 "yyyy MM dd HH:mm zzz",
2152 // round trip
2153 "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2154 "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2155 "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2156 "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2157 // non-generic timezone string influences dst offset even if wrong for date/time
2158 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
2159 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 Pacific Time",
2160 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
2161 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 Pacific Time",
2162 // generic timezone generates dst offset appropriate for local time
2163 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2164 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2165 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2166 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2167 // daylight savings time transition edge cases.
2168 // time to parse does not really exist, PT interpreted as earlier time
2169 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2170 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2171 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
2172 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2173 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2174 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT",
2175 "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2176 // time to parse is ambiguous, PT interpreted as later time
2177 "y/M/d H:mm zzz", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PST",
2178 "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PT",
2179 "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2180
2181 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2182 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2183 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
2184 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2185 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2186 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PT",
2187 "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2188 };
2189*/
2190 const char* ZDATA[] = {
2191 "yyyy MM dd HH:mm zzz",
2192 // round trip
2193 "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
2194 "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2195 "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2196 "y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
2197 // non-generic timezone string influences dst offset even if wrong for date/time
2198 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
2199 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
2200 // generic timezone generates dst offset appropriate for local time
2201 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PST", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2202 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 Pacific Time", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2203 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2204 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 Pacific Time", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2205 // daylight savings time transition edge cases.
2206 // time to parse does not really exist, PT interpreted as earlier time
2207 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
2208 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
2209 "y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
2210 "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
2211 // time to parse is ambiguous, PT interpreted as later time
2212 "y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PT",
2213 "y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
2214
2215 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
2216 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
2217 "y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
2218 "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
2219 };
2220
2221 const int32_t ZDATA_length = UPRV_LENGTHOF(ZDATA);
2222 expect(ZDATA, ZDATA_length, en);
2223
2224 UErrorCode status = U_ZERO_ERROR;
2225
2226 logln("cross format/parse tests"); // Note: We no longer support cross format/parse
2227 UnicodeString basepat("yy/MM/dd H:mm ");
2228 SimpleDateFormat formats[] = {
2229 SimpleDateFormat(basepat + "vvv", en, status),
2230 SimpleDateFormat(basepat + "vvvv", en, status),
2231 SimpleDateFormat(basepat + "zzz", en, status),
2232 SimpleDateFormat(basepat + "zzzz", en, status)
2233 };
2234 if (U_FAILURE(status)) {
2235 dataerrln("Fail construct SimpleDateFormat: %s", u_errorName(status));
2236 return;
2237 }
2238 const int32_t formats_length = UPRV_LENGTHOF(formats);
2239
2240 UnicodeString test;
2241 SimpleDateFormat univ("yyyy MM dd HH:mm zzz", en, status);
2242 ASSERT_OK(status);
2243 const UnicodeString times[] = {
2244 "2004 01 02 03:04 PST",
2245 "2004 07 08 09:10 PDT"
2246 };
2247 int32_t times_length = UPRV_LENGTHOF(times);
2248 for (int i = 0; i < times_length; ++i) {
2249 UDate d = univ.parse(times[i], status);
2250 logln(UnicodeString("\ntime: ") + d);
2251 for (int j = 0; j < formats_length; ++j) {
2252 test.remove();
2253 formats[j].format(d, test);
2254 logln("\ntest: '" + test + "'");
2255 for (int k = 0; k < formats_length; ++k) {
2256 UDate t = formats[k].parse(test, status);
2257 if (U_SUCCESS(status)) {
2258 if (d != t) {
2259 errln((UnicodeString)"FAIL: format " + k +
2260 " incorrectly parsed output of format " + j +
2261 " (" + test + "), returned " +
2262 dateToString(t) + " instead of " + dateToString(d));
2263 } else {
2264 logln((UnicodeString)"OK: format " + k + " parsed ok");
2265 }
2266 } else if (status == U_PARSE_ERROR) {
2267 errln((UnicodeString)"FAIL: format " + k +
2268 " could not parse output of format " + j +
2269 " (" + test + ")");
2270 }
2271 }
2272 }
2273 }
2274}
2275
2276void DateFormatTest::TestGenericTimeZoneOrder() {
2277 // generic times should parse the same no matter what the placement of the time zone string
2278
2279 // Note: We no longer support cross style format/parse
2280
2281 //const char* XDATA[] = {
2282 // "yyyy MM dd HH:mm zzz",
2283 // // standard time, explicit daylight/standard
2284 // "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2285 // "y/M/d zzz H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
2286 // "zzz y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
2287
2288 // // standard time, generic
2289 // "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2290 // "y/M/d vvvv H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
2291 // "vvvv y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
2292
2293 // // dahylight time, explicit daylight/standard
2294 // "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2295 // "y/M/d zzz H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
2296 // "zzz y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
2297
2298 // // daylight time, generic
2299 // "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
2300 // "y/M/d vvvv H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 Pacific Time 1:00",
2301 // "vvvv y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "Pacific Time 2004/7/1 1:00",
2302 //};
2303 const char* XDATA[] = {
2304 "yyyy MM dd HH:mm zzz",
2305 // standard time, explicit daylight/standard
2306 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PST", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
2307 "y/M/d zzz H:mm", "pf", "2004/1/1 PST 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
2308 "zzz y/M/d H:mm", "pf", "PST 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
2309
2310 // standard time, generic
2311 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 Pacific Time", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
2312 "y/M/d vvvv H:mm", "pf", "2004/1/1 Pacific Time 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
2313 "vvvv y/M/d H:mm", "pf", "Pacific Time 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
2314
2315 // dahylight time, explicit daylight/standard
2316 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PDT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
2317 "y/M/d zzz H:mm", "pf", "2004/7/1 PDT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
2318 "zzz y/M/d H:mm", "pf", "PDT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
2319
2320 // daylight time, generic
2321 "y/M/d H:mm v", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PT",
2322 "y/M/d v H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PT 1:00",
2323 "v y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PT 2004/7/1 1:00",
2324 };
2325 const int32_t XDATA_length = UPRV_LENGTHOF(XDATA);
2326 Locale en("en");
2327 expect(XDATA, XDATA_length, en);
2328}
2329
2330void DateFormatTest::TestZTimeZoneParsing(void) {
2331 UErrorCode status = U_ZERO_ERROR;
2332 const Locale en("en");
2333 UnicodeString test;
2334 //SimpleDateFormat univ("yyyy-MM-dd'T'HH:mm Z", en, status);
2335 SimpleDateFormat univ("HH:mm Z", en, status);
2336 if (failure(status, "construct SimpleDateFormat", TRUE)) return;
2337 const TimeZone *t = TimeZone::getGMT();
2338 univ.setTimeZone(*t);
2339
2340 univ.setLenient(false);
2341 ParsePosition pp(0);
2342 struct {
2343 UnicodeString input;
2344 UnicodeString expected_result;
2345 } tests[] = {
2346 { "11:00 -0200", "13:00 +0000" },
2347 { "11:00 +0200", "09:00 +0000" },
2348 { "11:00 +0400", "07:00 +0000" },
2349 { "11:00 +0530", "05:30 +0000" }
2350 };
2351
2352 UnicodeString result;
2353 int32_t tests_length = UPRV_LENGTHOF(tests);
2354 for (int i = 0; i < tests_length; ++i) {
2355 pp.setIndex(0);
2356 UDate d = univ.parse(tests[i].input, pp);
2357 if(pp.getIndex() != tests[i].input.length()){
2358 errln("Test %i: setZoneString() did not succeed. Consumed: %i instead of %i",
2359 i, pp.getIndex(), tests[i].input.length());
2360 return;
2361 }
2362 result.remove();
2363 univ.format(d, result);
2364 if(result != tests[i].expected_result) {
2365 errln("Expected " + tests[i].expected_result
2366 + " got " + result);
2367 return;
2368 }
2369 logln("SUCCESS: Parsed " + tests[i].input
2370 + " got " + result
2371 + " expected " + tests[i].expected_result);
2372 }
2373}
2374
2375void DateFormatTest::TestHost(void)
2376{
2377#if U_PLATFORM_USES_ONLY_WIN32_API
2378 Win32DateTimeTest::testLocales(this);
2379#endif
2380}
2381
2382// Relative Date Tests
2383
2384void DateFormatTest::TestRelative(int daysdelta,
2385 const Locale& loc,
2386 const char *expectChars) {
2387 char banner[25];
2388 sprintf(banner, "%d", daysdelta);
2389 UnicodeString bannerStr(banner, "");
2390
2391 UErrorCode status = U_ZERO_ERROR;
2392
2393 FieldPosition pos(FieldPosition::DONT_CARE);
2394 UnicodeString test;
2395 Locale en("en");
2396 DateFormat *fullrelative = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2397
2398 if (fullrelative == NULL) {
2399 dataerrln("DateFormat::createDateInstance(DateFormat::kFullRelative, %s) returned NULL", loc.getName());
2400 return;
2401 }
2402
2403 DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull , loc);
2404
2405 if (full == NULL) {
2406 errln("DateFormat::createDateInstance(DateFormat::kFull, %s) returned NULL", loc.getName());
2407 return;
2408 }
2409
2410 DateFormat *en_full = DateFormat::createDateInstance(DateFormat::kFull, en);
2411
2412 if (en_full == NULL) {
2413 errln("DateFormat::createDateInstance(DateFormat::kFull, en) returned NULL");
2414 return;
2415 }
2416
2417 DateFormat *en_fulltime = DateFormat::createDateTimeInstance(DateFormat::kFull,DateFormat::kFull,en);
2418
2419 if (en_fulltime == NULL) {
2420 errln("DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, en) returned NULL");
2421 return;
2422 }
2423
2424 UnicodeString result;
2425 UnicodeString normalResult;
2426 UnicodeString expect;
2427 UnicodeString parseResult;
2428
2429 Calendar *c = Calendar::createInstance(status);
2430
2431 // Today = Today
2432 c->setTime(Calendar::getNow(), status);
2433 if(daysdelta != 0) {
2434 c->add(Calendar::DATE,daysdelta,status);
2435 }
2436 ASSERT_OK(status);
2437
2438 // calculate the expected string
2439 if(expectChars != NULL) {
2440 expect = expectChars;
2441 } else {
2442 full->format(*c, expect, pos); // expected = normal full
2443 }
2444
2445 fullrelative ->format(*c, result, pos);
2446 en_full ->format(*c, normalResult, pos);
2447
2448 if(result != expect) {
2449 errln("FAIL: Relative Format ["+bannerStr+"] of "+normalResult+" failed, expected "+expect+" but got " + result);
2450 } else {
2451 logln("PASS: Relative Format ["+bannerStr+"] of "+normalResult+" got " + result);
2452 }
2453
2454
2455 //verify
2456 UDate d = fullrelative->parse(result, status);
2457 ASSERT_OK(status);
2458
2459 UnicodeString parseFormat; // parse rel->format full
2460 en_full->format(d, parseFormat, status);
2461
2462 UnicodeString origFormat;
2463 en_full->format(*c, origFormat, pos);
2464
2465 if(parseFormat!=origFormat) {
2466 errln("FAIL: Relative Parse ["+bannerStr+"] of "+result+" failed, expected "+parseFormat+" but got "+origFormat);
2467 } else {
2468 logln("PASS: Relative Parse ["+bannerStr+"] of "+result+" passed, got "+parseFormat);
2469 }
2470
2471 delete full;
2472 delete fullrelative;
2473 delete en_fulltime;
2474 delete en_full;
2475 delete c;
2476}
2477
2478
2479void DateFormatTest::TestRelative(void)
2480{
2481 Locale en("en");
2482 TestRelative( 0, en, "today");
2483 TestRelative(-1, en, "yesterday");
2484 TestRelative( 1, en, "tomorrow");
2485 TestRelative( 2, en, NULL);
2486 TestRelative( -2, en, NULL);
2487 TestRelative( 3, en, NULL);
2488 TestRelative( -3, en, NULL);
2489 TestRelative( 300, en, NULL);
2490 TestRelative( -300, en, NULL);
2491}
2492
2493void DateFormatTest::TestRelativeClone(void)
2494{
2495 /*
2496 Verify that a cloned formatter gives the same results
2497 and is useable after the original has been deleted.
2498 */
2499 UErrorCode status = U_ZERO_ERROR;
2500 Locale loc("en");
2501 UDate now = Calendar::getNow();
2502 DateFormat *full = DateFormat::createDateInstance(DateFormat::kFullRelative, loc);
2503 if (full == NULL) {
2504 dataerrln("FAIL: Can't create Relative date instance");
2505 return;
2506 }
2507 UnicodeString result1;
2508 full->format(now, result1, status);
2509 Format *fullClone = full->clone();
2510 delete full;
2511 full = NULL;
2512
2513 UnicodeString result2;
2514 fullClone->format(now, result2, status);
2515 ASSERT_OK(status);
2516 if (result1 != result2) {
2517 errln("FAIL: Clone returned different result from non-clone.");
2518 }
2519 delete fullClone;
2520}
2521
2522void DateFormatTest::TestHostClone(void)
2523{
2524 /*
2525 Verify that a cloned formatter gives the same results
2526 and is useable after the original has been deleted.
2527 */
2528 // This is mainly important on Windows.
2529 UErrorCode status = U_ZERO_ERROR;
2530 Locale loc("en_US@compat=host");
2531 UDate now = Calendar::getNow();
2532 DateFormat *full = DateFormat::createDateInstance(DateFormat::kFull, loc);
2533 if (full == NULL) {
2534 dataerrln("FAIL: Can't create host date instance");
2535 return;
2536 }
2537 UnicodeString result1;
2538 full->format(now, result1, status);
2539 Format *fullClone = full->clone();
2540 delete full;
2541 full = NULL;
2542
2543 UnicodeString result2;
2544 fullClone->format(now, result2, status);
2545 ASSERT_OK(status);
2546 if (result1 != result2) {
2547 errln("FAIL: Clone returned different result from non-clone.");
2548 }
2549 delete fullClone;
2550}
2551
2552void DateFormatTest::TestHebrewClone(void)
2553{
2554 /*
2555 Verify that a cloned formatter gives the same results
2556 and is useable after the original has been deleted.
2557 */
2558 UErrorCode status = U_ZERO_ERROR;
2559 Locale loc("he@calendar=hebrew");
2560 UDate now = Calendar::getNow();
2561 LocalPointer<DateFormat> fmt(
2562 DateFormat::createDateInstance(DateFormat::kLong, loc));
2563 if (fmt.isNull()) {
2564 dataerrln("FAIL: Can't create Hebrew date instance");
2565 return;
2566 }
2567 UnicodeString result1;
2568 fmt->format(now, result1, status);
2569 LocalPointer<Format> fmtClone(fmt->clone());
2570
2571 // free fmt to be sure that fmtClone is independent of fmt.
2572 fmt.adoptInstead(NULL);
2573
2574 UnicodeString result2;
2575 fmtClone->format(now, result2, status);
2576 ASSERT_OK(status);
2577 if (result1 != result2) {
2578 errln("FAIL: Clone returned different result from non-clone.");
2579 }
2580}
2581
2582static UBool getActualAndValidLocales(
2583 const Format &fmt, Locale &valid, Locale &actual) {
2584 const SimpleDateFormat* dat = dynamic_cast<const SimpleDateFormat*>(&fmt);
2585 if (dat == NULL) {
2586 return FALSE;
2587 }
2588 const DateFormatSymbols *sym = dat->getDateFormatSymbols();
2589 if (sym == NULL) {
2590 return FALSE;
2591 }
2592 UErrorCode status = U_ZERO_ERROR;
2593 valid = sym->getLocale(ULOC_VALID_LOCALE, status);
2594 actual = sym->getLocale(ULOC_ACTUAL_LOCALE, status);
2595 return U_SUCCESS(status);
2596}
2597
2598void DateFormatTest::TestDateFormatSymbolsClone(void)
2599{
2600 /*
2601 Verify that a cloned formatter gives the same results
2602 and is useable after the original has been deleted.
2603 */
2604 Locale loc("de_CH_LUCERNE");
2605 LocalPointer<DateFormat> fmt(
2606 DateFormat::createDateInstance(DateFormat::kDefault, loc));
2607 if (fmt.isNull()) {
2608 dataerrln("FAIL: DateFormat::createDateInstance failed for %s", loc.getName());
2609 return;
2610 }
2611 Locale valid1;
2612 Locale actual1;
2613 if (!getActualAndValidLocales(*fmt, valid1, actual1)) {
2614 dataerrln("FAIL: Could not fetch valid + actual locales");
2615 return;
2616 }
2617 LocalPointer<Format> fmtClone(fmt->clone());
2618
2619 // Free fmt to be sure that fmtClone is really independent of fmt.
2620 fmt.adoptInstead(NULL);
2621 Locale valid2;
2622 Locale actual2;
2623 if (!getActualAndValidLocales(*fmtClone, valid2, actual2)) {
2624 errln("FAIL: Could not fetch valid + actual locales");
2625 return;
2626 }
2627 if (valid1 != valid2 || actual1 != actual2) {
2628 errln("Date format symbol locales of clone don't match original");
2629 }
2630}
2631
2632void DateFormatTest::TestTimeZoneDisplayName()
2633{
2634 // This test data was ported from ICU4J. Don't know why the 6th column in there because it's not being
2635 // used currently.
2636 const char *fallbackTests[][6] = {
2637 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2638 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2639 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZZ", "-08:00", "-8:00" },
2640 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "PST", "America/Los_Angeles" },
2641 { "en", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Pacific Standard Time", "America/Los_Angeles" },
2642 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2643 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2644 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "PDT", "America/Los_Angeles" },
2645 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Pacific Daylight Time", "America/Los_Angeles" },
2646 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "PT", "America/Los_Angeles" },
2647 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Pacific Time", "America/Los_Angeles" },
2648 { "en", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "Los Angeles Time", "America/Los_Angeles" },
2649 { "en_GB", "America/Los_Angeles", "2004-01-15T12:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2650 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "Z", "-0700", "-7:00" },
2651 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2652 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2653 { "en", "America/Phoenix", "2004-01-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2654 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2655 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2656 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "z", "MST", "America/Phoenix" },
2657 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "zzzz", "Mountain Standard Time", "America/Phoenix" },
2658 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "v", "MST", "America/Phoenix" },
2659 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "vvvv", "Mountain Standard Time", "America/Phoenix" },
2660 { "en", "America/Phoenix", "2004-07-15T00:00:00Z", "VVVV", "Phoenix Time", "America/Phoenix" },
2661
2662 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2663 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2664 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2665 { "en", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2666 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2667 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2668 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2669 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2670 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2671 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2672 { "en", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2673
2674 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2675 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2676 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2677 { "en", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2678 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2679 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2680 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2681 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentina Standard Time", "-3:00" },
2682 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Time", "America/Buenos_Aires" },
2683 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentina Standard Time", "America/Buenos_Aires" },
2684 { "en", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "VVVV", "Buenos Aires Time", "America/Buenos_Aires" },
2685
2686 { "en", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2687 { "en", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2688 { "en", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2689 { "en", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Cuba Standard Time", "-5:00" },
2690 { "en", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2691 { "en", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2692 { "en", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2693 { "en", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Cuba Daylight Time", "-4:00" },
2694 { "en", "America/Havana", "2004-07-15T00:00:00Z", "v", "Cuba Time", "America/Havana" },
2695 { "en", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Cuba Time", "America/Havana" },
2696 { "en", "America/Havana", "2004-07-15T00:00:00Z", "VVVV", "Cuba Time", "America/Havana" },
2697
2698 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2699 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2700 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2701 { "en", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2702 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2703 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2704 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2705 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2706 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2707 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2708 { "en", "Australia/ACT", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2709
2710 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2711 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2712 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2713 { "en", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Australian Eastern Daylight Time", "+11:00" },
2714 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2715 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2716 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2717 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Australian Eastern Standard Time", "+10:00" },
2718 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Time", "Australia/Sydney" },
2719 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Eastern Australia Time", "Australia/Sydney" },
2720 { "en", "Australia/Sydney", "2004-07-15T00:00:00Z", "VVVV", "Sydney Time", "Australia/Sydney" },
2721
2722 { "en", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2723 { "en", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2724 { "en", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2725 { "en", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Greenwich Mean Time", "+0:00" },
2726 { "en", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2727 { "en", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2728 { "en", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "Europe/London" },
2729 { "en", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "British Summer Time", "Europe/London" },
2730 // icu en.txt has exemplar city for this time zone
2731 { "en", "Europe/London", "2004-07-15T00:00:00Z", "v", "United Kingdom Time", "Europe/London" },
2732 { "en", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "United Kingdom Time", "Europe/London" },
2733 { "en", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "United Kingdom Time", "Europe/London" },
2734
2735 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2736 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2737 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2738 { "en", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2739 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2740 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2741 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2742 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2743 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2744 { "en", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2745
2746 // JB#5150
2747 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2748 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2749 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2750 { "en", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2751 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2752 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2753 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2754 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "India Standard Time", "+5:30" },
2755 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "India Time", "Asia/Calcutta" },
2756 { "en", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "India Standard Time", "Asia/Calcutta" },
2757
2758 // Proper CLDR primary zone support #9733
2759 { "en", "America/Santiago", "2013-01-01T00:00:00Z", "VVVV", "Chile Time", "America/Santiago" },
2760 { "en", "Pacific/Easter", "2013-01-01T00:00:00Z", "VVVV", "Easter Time", "Pacific/Easter" },
2761
2762 // ==========
2763
2764 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2765 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2766 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2767 { "de", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Normalzeit", "-8:00" },
2768 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2769 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2770 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2771 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "Nordamerikanische Westk\\u00fcsten-Sommerzeit", "-7:00" },
2772 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles Zeit", "America/Los_Angeles" },
2773 { "de", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Nordamerikanische Westk\\u00fcstenzeit", "America/Los_Angeles" },
2774
2775 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2776 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2777 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2778 { "de", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2779 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2780 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2781 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2782 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2783 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2784 { "de", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2785
2786 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2787 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2788 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2789 { "de", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2790 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2791 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2792 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2793 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "Argentinische Normalzeit", "-3:00" },
2794 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires Zeit", "America/Buenos_Aires" },
2795 { "de", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Argentinische Normalzeit", "America/Buenos_Aires" },
2796
2797 { "de", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2798 { "de", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2799 { "de", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2800 { "de", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "Kubanische Normalzeit", "-5:00" },
2801 { "de", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2802 { "de", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2803 { "de", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2804 { "de", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "Kubanische Sommerzeit", "-4:00" },
2805 { "de", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2806 { "de", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2807 // added to test proper fallback of country name
2808 { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "v", "Kuba Zeit", "America/Havana" },
2809 { "de_CH", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "Kubanische Zeit", "America/Havana" },
2810
2811 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2812 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2813 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2814 { "de", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2815 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2816 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2817 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2818 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2819 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2820 { "de", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2821
2822 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2823 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2824 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2825 { "de", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "Ostaustralische Sommerzeit", "+11:00" },
2826 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2827 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2828 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2829 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "Ostaustralische Normalzeit", "+10:00" },
2830 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney Zeit", "Australia/Sydney" },
2831 { "de", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Ostaustralische Zeit", "Australia/Sydney" },
2832
2833 { "de", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2834 { "de", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2835 { "de", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2836 { "de", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "Mittlere Greenwich-Zeit", "+0:00" },
2837 { "de", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2838 { "de", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2839 { "de", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2840 { "de", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "Britische Sommerzeit", "+1:00" },
2841 { "de", "Europe/London", "2004-07-15T00:00:00Z", "v", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2842 { "de", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "Vereinigtes K\\u00f6nigreich Zeit", "Europe/London" },
2843
2844 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2845 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2846 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2847 { "de", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2848 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2849 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2850 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2851 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2852 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2853 { "de", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2854
2855 // JB#5150
2856 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2857 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2858 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2859 { "de", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2860 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2861 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2862 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2863 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "Indische Zeit", "+5:30" },
2864 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "Indien Zeit", "Asia/Calcutta" },
2865 { "de", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "Indische Zeit", "Asia/Calcutta" },
2866
2867 // ==========
2868
2869 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2870 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2871 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
2872 { "zh", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u6807\\u51c6\\u65f6\\u95f4", "America/Los_Angeles" },
2873 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2874 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2875 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
2876 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u590f\\u4ee4\\u65f6\\u95f4", "America/Los_Angeles" },
2877 // icu zh.txt has exemplar city for this time zone
2878 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4", "America/Los_Angeles" },
2879 { "zh", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u5317\\u7f8e\\u592a\\u5e73\\u6d0b\\u65f6\\u95f4", "America/Los_Angeles" },
2880
2881 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2882 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2883 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2884 { "zh", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2885 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2886 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2887 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2888 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2889 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2890 { "zh", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2891
2892 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2893 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2894 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2895 { "zh", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2896 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2897 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2898 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2899 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "-3:00" },
2900 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u5E03\\u5B9C\\u8BFA\\u65AF\\u827E\\u5229\\u65AF\\u65F6\\u95F4", "America/Buenos_Aires" },
2901 { "zh", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u963f\\u6839\\u5ef7\\u6807\\u51c6\\u65f6\\u95f4", "America/Buenos_Aires" },
2902
2903 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
2904 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
2905 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
2906 { "zh", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u6807\\u51c6\\u65f6\\u95f4", "-5:00" },
2907 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
2908 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
2909 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
2910 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u53e4\\u5df4\\u590f\\u4ee4\\u65f6\\u95f4", "-4:00" },
2911 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2912 { "zh", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u53e4\\u5df4\\u65f6\\u95f4", "America/Havana" },
2913
2914 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2915 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2916 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2917 { "zh", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2918 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2919 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2920 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2921 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2922 // icu zh.txt does not have info for this time zone
2923 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2924 { "zh", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2925
2926 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
2927 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
2928 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
2929 { "zh", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u590f\\u4ee4\\u65f6\\u95f4", "+11:00" },
2930 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
2931 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
2932 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
2933 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u6807\\u51c6\\u65f6\\u95f4", "+10:00" },
2934 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u6089\\u5C3C\\u65F6\\u95F4", "Australia/Sydney" },
2935 { "zh", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u6fb3\\u5927\\u5229\\u4e9a\\u4e1c\\u90e8\\u65f6\\u95f4", "Australia/Sydney" },
2936
2937 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
2938 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2939 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2940 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
2941 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
2942 { "zh", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u683C\\u6797\\u5C3C\\u6CBB\\u6807\\u51C6\\u65F6\\u95F4", "+0:00" },
2943 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
2944 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
2945 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
2946 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u4ee4\\u65f6\\u95f4", "+1:00" },
2947 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2948 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2949 { "zh", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u82f1\\u56fd\\u65f6\\u95f4", "Europe/London" },
2950
2951 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2952 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2953 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2954 { "zh", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2955 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2956 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2957 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2958 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
2959 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
2960 { "zh", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
2961
2962 // JB#5150
2963 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
2964 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2965 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
2966 { "zh", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2967 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
2968 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
2969 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
2970 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u5370\\u5ea6\\u65f6\\u95f4", "+5:30" },
2971 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2972 { "zh", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u5370\\u5ea6\\u65f6\\u95f4", "Asia/Calcutta" },
2973
2974 // ==========
2975
2976 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
2977 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
2978 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
2979 { "hi", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-8:00" },
2980 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
2981 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
2982 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
2983 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "-7:00" },
2984 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u0932\\u0949\\u0938 \\u090f\\u0902\\u091c\\u093f\\u0932\\u094d\\u0938 \\u0938\\u092e\\u092f", "America/Los_Angeles" },
2985 { "hi", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u0909\\u0924\\u094d\\u0924\\u0930\\u0940 \\u0905\\u092e\\u0947\\u0930\\u093f\\u0915\\u0940 \\u092a\\u094d\\u0930\\u0936\\u093e\\u0902\\u0924 \\u0938\\u092e\\u092f", "America/Los_Angeles" },
2986
2987 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2988 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2989 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2990 { "hi", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2991 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
2992 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
2993 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
2994 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
2995 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u092C\\u094D\\u092F\\u0942\\u0928\\u0938 \\u0906\\u092F\\u0930\\u0938 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2996 { "hi", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
2997
2998 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
2999 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3000 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3001 { "hi", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
3002 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3003 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3004 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3005 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "-3:00" },
3006 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u092C\\u094D\\u092F\\u0942\\u0928\\u0938 \\u0906\\u092F\\u0930\\u0938 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
3007 { "hi", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0905\\u0930\\u094D\\u091C\\u0947\\u0902\\u091F\\u0940\\u0928\\u093E \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "America/Buenos_Aires" },
3008
3009 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3010 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3011 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3012 { "hi", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "-5:00" },
3013 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3014 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3015 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3016 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "-4:00" },
3017 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092E\\u092F", "America/Havana" },
3018 { "hi", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u0915\\u094d\\u092f\\u0942\\u092c\\u093e \\u0938\\u092e\\u092f", "America/Havana" },
3019
3020 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3021 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3022 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3023 { "hi", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "+11:00" },
3024 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3025 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3026 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3027 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "+10:00" },
3028 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3029 { "hi", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0911\\u0938\\u094d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e \\u0938\\u092e\\u092f", "Australia/Sydney" },
3030
3031 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3032 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3033 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3034 { "hi", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0921\\u0947\\u0932\\u093e\\u0907\\u091f \\u0938\\u092e\\u092f", "+11:00" },
3035 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3036 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3037 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3038 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u0911\\u0938\\u094d\\u200d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e\\u0908 \\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u092e\\u093e\\u0928\\u0915 \\u0938\\u092e\\u092f", "+10:00" },
3039 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0938\\u093F\\u0921\\u0928\\u0940 \\u0938\\u092E\\u092F", "Australia/Sydney" },
3040 { "hi", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u092a\\u0942\\u0930\\u094d\\u0935\\u0940 \\u0911\\u0938\\u094d\\u091f\\u094d\\u0930\\u0947\\u0932\\u093f\\u092f\\u093e \\u0938\\u092e\\u092f", "Australia/Sydney" },
3041
3042 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3043 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3044 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3045 { "hi", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u0917\\u094d\\u0930\\u0940\\u0928\\u0935\\u093f\\u091a \\u092e\\u0940\\u0928 \\u091f\\u093e\\u0907\\u092e", "+0:00" },
3046 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3047 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3048 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3049 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u092c\\u094d\\u0930\\u093f\\u091f\\u093f\\u0936 \\u0917\\u094d\\u0930\\u0940\\u0937\\u094d\\u092e\\u0915\\u093e\\u0932\\u0940\\u0928 \\u0938\\u092e\\u092f", "+1:00" },
3050 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u092f\\u0942\\u0928\\u093e\\u0907\\u091f\\u0947\\u0921 \\u0915\\u093f\\u0902\\u0917\\u0921\\u092e \\u0938\\u092e\\u092f", "Europe/London" },
3051 { "hi", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u092f\\u0942\\u0928\\u093e\\u0907\\u091f\\u0947\\u0921 \\u0915\\u093f\\u0902\\u0917\\u0921\\u092e \\u0938\\u092e\\u092f", "Europe/London" },
3052
3053 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3054 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3055 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3056 { "hi", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3057 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3058 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3059 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3060 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3061 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3062 { "hi", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3063
3064 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3065 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3066 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "IST", "+5:30" },
3067 { "hi", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3068 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3069 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3070 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "IST", "+05:30" },
3071 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "+5:30" },
3072 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "IST", "Asia/Calcutta" },
3073 { "hi", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u092D\\u093E\\u0930\\u0924\\u0940\\u092F \\u092E\\u093E\\u0928\\u0915 \\u0938\\u092E\\u092F", "Asia/Calcutta" },
3074
3075 // ==========
3076
3077 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3078 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-08:00", "-8:00" },
3079 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-8", "America/Los_Angeles" },
3080 { "bg", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3081 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3082 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-07:00", "-7:00" },
3083 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-7", "America/Los_Angeles" },
3084 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3085 // icu bg.txt has exemplar city for this time zone
3086 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3087 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u0421\\u0435\\u0432\\u0435\\u0440\\u043d\\u043e\\u0430\\u043c\\u0435\\u0440\\u0438\\u043a\\u0430\\u043d\\u0441\\u043a\\u043e \\u0442\\u0438\\u0445\\u043e\\u043e\\u043a\\u0435\\u0430\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Los_Angeles" },
3088 { "bg", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u041B\\u043E\\u0441 \\u0410\\u043D\\u0434\\u0436\\u0435\\u043B\\u0438\\u0441", "America/Los_Angeles" },
3089
3090 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3091 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3092 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3093 { "bg", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3094 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3095 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3096 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3097 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3098 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
3099 { "bg", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Buenos_Aires" },
3100
3101 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3102 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3103 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3104 { "bg", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3105 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3106 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3107 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3108 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-3:00" },
3109 // icu bg.txt does not have info for this time zone
3110 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u0411\\u0443\\u0435\\u043D\\u043E\\u0441 \\u0410\\u0439\\u0440\\u0435\\u0441", "America/Buenos_Aires" },
3111 { "bg", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u0410\\u0440\\u0436\\u0435\\u043D\\u0442\\u0438\\u043D\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "America/Buenos_Aires" },
3112
3113 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3114 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-05:00", "-5:00" },
3115 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-5", "-5:00" },
3116 { "bg", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0441\\u0442\\u0430\\u043d\\u0434\\u0430\\u0440\\u0442\\u043d\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-5:00" },
3117 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3118 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-04:00", "-4:00" },
3119 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-4", "-4:00" },
3120 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "-4:00" },
3121 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u041a\\u0443\\u0431\\u0430", "America/Havana" },
3122 { "bg", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u041a\\u0443\\u0431\\u0438\\u043d\\u0441\\u043a\\u043e \\u0432\\u0440\\u0435\\u043C\\u0435", "America/Havana" },
3123
3124 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3125 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3126 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3127 { "bg", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u043B\\u044F\\u0442\\u043D\\u043E \\u0447\\u0430\\u0441\\u043E\\u0432\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+11:00" },
3128 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3129 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3130 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3131 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+10:00" },
3132 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3133 { "bg", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "Australia/Sydney" },
3134
3135 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3136 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11:00", "+11:00" },
3137 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+11", "+11:00" },
3138 { "bg", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u043B\\u044F\\u0442\\u043D\\u043E \\u0447\\u0430\\u0441\\u043E\\u0432\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+11:00" },
3139 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3140 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10:00", "+10:00" },
3141 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+10", "+10:00" },
3142 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0441\\u0442\\u0430\\u043D\\u0434\\u0430\\u0440\\u0442\\u043D\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "+10:00" },
3143 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u0421\\u0438\\u0434\\u043D\\u0438", "Australia/Sydney" },
3144 { "bg", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u0437\\u0442\\u043E\\u0447\\u043D\\u043E\\u0430\\u0432\\u0441\\u0442\\u0440\\u0430\\u043B\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043C\\u0435", "Australia/Sydney" },
3145
3146 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3147 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3148 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447", "+0:00" },
3149 { "bg", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u0421\\u0440\\u0435\\u0434\\u043d\\u043e \\u0433\\u0440\\u0438\\u043d\\u0443\\u0438\\u0447\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+0:00" },
3150 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3151 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+01:00", "+1:00" },
3152 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+1", "+1:00" },
3153 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u0411\\u0440\\u0438\\u0442\\u0430\\u043d\\u0441\\u043a\\u043e \\u043b\\u044f\\u0442\\u043d\\u043e \\u0447\\u0430\\u0441\\u043e\\u0432\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435", "+1:00" },
3154 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u041E\\u0431\\u0435\\u0434\\u0438\\u043D\\u0435\\u043D\\u043E\\u0442\\u043E \\u043A\\u0440\\u0430\\u043B\\u0441\\u0442\\u0432\\u043E", "Europe/London" },
3155 { "bg", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u041E\\u0431\\u0435\\u0434\\u0438\\u043D\\u0435\\u043D\\u043E\\u0442\\u043E \\u043A\\u0440\\u0430\\u043B\\u0441\\u0442\\u0432\\u043E", "Europe/London" },
3156
3157 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3158 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3159 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3160 { "bg", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3161 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3162 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3163 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3164 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3165 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-3", "-3:00" },
3166 { "bg", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447-03:00", "-3:00" },
3167
3168 // JB#5150
3169 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3170 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3171 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+5:30" },
3172 { "bg", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u0418\\u043D\\u0434\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
3173 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3174 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+05:30", "+5:30" },
3175 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "\\u0413\\u0440\\u0438\\u043D\\u0443\\u0438\\u0447+5:30", "+05:30" },
3176 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u0418\\u043D\\u0434\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "+5:30" },
3177 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u0418\\u043D\\u0434\\u0438\\u044F", "Asia/Calcutta" },
3178 { "bg", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u0418\\u043D\\u0434\\u0438\\u0439\\u0441\\u043A\\u043E \\u0432\\u0440\\u0435\\u043c\\u0435", "Asia/Calcutta" },
3179 // ==========
3180
3181 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3182 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3183 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "America/Los_Angeles" },
3184 { "ja", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u6a19\\u6e96\\u6642", "America/Los_Angeles" },
3185 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-700" },
3186 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3187 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "America/Los_Angeles" },
3188 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "\\u30a2\\u30e1\\u30ea\\u30ab\\u592a\\u5e73\\u6d0b\\u590f\\u6642\\u9593", "America/Los_Angeles" },
3189 // icu ja.txt has exemplar city for this time zone
3190 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3191 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30E1\\u30EA\\u30AB\\u592A\\u5e73\\u6D0B\\u6642\\u9593", "America/Los_Angeles" },
3192 { "ja", "America/Los_Angeles", "2004-07-15T00:00:00Z", "VVVV", "\\u30ED\\u30B5\\u30F3\\u30BC\\u30EB\\u30B9\\u6642\\u9593", "America/Los_Angeles" },
3193
3194 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3195 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3196 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3197 { "ja", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3198 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3199 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3200 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3201 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3202 // icu ja.txt does not have info for this time zone
3203 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3204 { "ja", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3205
3206 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3207 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3208 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3209 { "ja", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3210 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3211 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3212 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3213 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "-3:00" },
3214 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "\\u30D6\\u30A8\\u30CE\\u30B9\\u30A2\\u30A4\\u30EC\\u30B9\\u6642\\u9593", "America/Buenos_Aires" },
3215 { "ja", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "\\u30A2\\u30EB\\u30BC\\u30F3\\u30C1\\u30F3\\u6A19\\u6E96\\u6642", "America/Buenos_Aires" },
3216
3217 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3218 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3219 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3220 { "ja", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u6A19\\u6E96\\u6642", "-5:00" },
3221 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3222 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3223 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3224 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "\\u30AD\\u30E5\\u30FC\\u30D0\\u590F\\u6642\\u9593", "-4:00" },
3225 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3226 { "ja", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u30ad\\u30e5\\u30fc\\u30d0\\u6642\\u9593", "America/Havana" },
3227
3228 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3229 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3230 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3231 { "ja", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3232 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3233 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3234 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3235 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3236 // icu ja.txt does not have info for this time zone
3237 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3238 { "ja", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3239
3240 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3241 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3242 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3243 { "ja", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u590F\\u6642\\u9593", "+11:00" },
3244 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3245 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3246 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3247 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6A19\\u6E96\\u6642", "+10:00" },
3248 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "\\u30B7\\u30C9\\u30CB\\u30FC\\u6642\\u9593", "Australia/Sydney" },
3249 { "ja", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "\\u30AA\\u30FC\\u30B9\\u30C8\\u30E9\\u30EA\\u30A2\\u6771\\u90E8\\u6642\\u9593", "Australia/Sydney" },
3250
3251 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3252 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3253 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3254 { "ja", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "\\u30B0\\u30EA\\u30CB\\u30C3\\u30B8\\u6A19\\u6E96\\u6642", "+0:00" },
3255 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3256 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3257 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3258 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "\\u82f1\\u56fd\\u590f\\u6642\\u9593", "+1:00" },
3259 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3260 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3261 { "ja", "Europe/London", "2004-07-15T00:00:00Z", "VVVV", "\\u30a4\\u30ae\\u30ea\\u30b9\\u6642\\u9593", "Europe/London" },
3262
3263 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3264 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3265 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3266 { "ja", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3267 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3268 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3269 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3270 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3271 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3272 { "ja", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3273
3274 // JB#5150
3275 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3276 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3277 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3278 { "ja", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3279 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3280 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3281 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3282 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "+5:30" },
3283 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u30A4\\u30F3\\u30C9\\u6642\\u9593", "Asia/Calcutta" },
3284 { "ja", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u30A4\\u30F3\\u30C9\\u6A19\\u6E96\\u6642", "Asia/Calcutta" },
3285
3286 // ==========
3287
3288 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "Z", "-0800", "-8:00" },
3289 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-08:00", "-8:00" },
3290 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "z", "GMT-8", "-8:00" },
3291 { "ti", "America/Los_Angeles", "2004-01-15T00:00:00Z", "zzzz", "GMT-08:00", "-8:00" },
3292 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "Z", "-0700", "-7:00" },
3293 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-07:00", "-7:00" },
3294 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "z", "GMT-7", "-7:00" },
3295 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "zzzz", "GMT-07:00", "-7:00" },
3296 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "v", "Los Angeles", "America/Los_Angeles" },
3297 { "ti", "America/Los_Angeles", "2004-07-15T00:00:00Z", "vvvv", "Los Angeles", "America/Los_Angeles" },
3298
3299 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3300 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3301 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3302 { "ti", "America/Argentina/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3303 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3304 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3305 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3306 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3307 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3308 { "ti", "America/Argentina/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3309
3310 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3311 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3312 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3313 { "ti", "America/Buenos_Aires", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3314 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3315 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3316 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3317 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3318 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "v", "Buenos Aires", "America/Buenos_Aires" },
3319 { "ti", "America/Buenos_Aires", "2004-07-15T00:00:00Z", "vvvv", "Buenos Aires", "America/Buenos_Aires" },
3320
3321 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "Z", "-0500", "-5:00" },
3322 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-05:00", "-5:00" },
3323 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "z", "GMT-5", "-5:00" },
3324 { "ti", "America/Havana", "2004-01-15T00:00:00Z", "zzzz", "GMT-05:00", "-5:00" },
3325 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "Z", "-0400", "-4:00" },
3326 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-04:00", "-4:00" },
3327 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "z", "GMT-4", "-4:00" },
3328 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "zzzz", "GMT-04:00", "-4:00" },
3329 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "v", "\\u12A9\\u1263", "America/Havana" },
3330 { "ti", "America/Havana", "2004-07-15T00:00:00Z", "vvvv", "\\u12A9\\u1263", "America/Havana" },
3331
3332 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3333 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3334 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3335 { "ti", "Australia/ACT", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3336 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3337 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3338 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3339 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3340 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3341 { "ti", "Australia/ACT", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3342
3343 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "Z", "+1100", "+11:00" },
3344 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+11:00", "+11:00" },
3345 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "z", "GMT+11", "+11:00" },
3346 { "ti", "Australia/Sydney", "2004-01-15T00:00:00Z", "zzzz", "GMT+11:00", "+11:00" },
3347 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "Z", "+1000", "+10:00" },
3348 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+10:00", "+10:00" },
3349 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "z", "GMT+10", "+10:00" },
3350 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "zzzz", "GMT+10:00", "+10:00" },
3351 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "v", "Sydney", "Australia/Sydney" },
3352 { "ti", "Australia/Sydney", "2004-07-15T00:00:00Z", "vvvv", "Sydney", "Australia/Sydney" },
3353
3354 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "Z", "+0000", "+0:00" },
3355 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "ZZZZ", "GMT", "+0:00" },
3356 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "z", "GMT", "+0:00" },
3357 { "ti", "Europe/London", "2004-01-15T00:00:00Z", "zzzz", "GMT", "+0:00" },
3358 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "Z", "+0100", "+1:00" },
3359 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+01:00", "+1:00" },
3360 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "z", "GMT+1", "+1:00" },
3361 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "zzzz", "GMT+01:00", "+1:00" },
3362 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "v", "\\u12A5\\u1295\\u130D\\u120A\\u12DD", "Europe/London" },
3363 { "ti", "Europe/London", "2004-07-15T00:00:00Z", "vvvv", "\\u12A5\\u1295\\u130D\\u120A\\u12DD", "Europe/London" },
3364
3365 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "Z", "-0300", "-3:00" },
3366 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3367 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3368 { "ti", "Etc/GMT+3", "2004-01-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3369 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "Z", "-0300", "-3:00" },
3370 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "ZZZZ", "GMT-03:00", "-3:00" },
3371 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "z", "GMT-3", "-3:00" },
3372 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "zzzz", "GMT-03:00", "-3:00" },
3373 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "v", "GMT-3", "-3:00" },
3374 { "ti", "Etc/GMT+3", "2004-07-15T00:00:00Z", "vvvv", "GMT-03:00", "-3:00" },
3375
3376 // JB#5150
3377 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "Z", "+0530", "+5:30" },
3378 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3379 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "z", "GMT+5:30", "+5:30" },
3380 { "ti", "Asia/Calcutta", "2004-01-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3381 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "Z", "+0530", "+5:30" },
3382 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "ZZZZ", "GMT+05:30", "+5:30" },
3383 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "z", "GMT+5:30", "+05:30" },
3384 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "zzzz", "GMT+05:30", "+5:30" },
3385 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "v", "\\u1205\\u1295\\u12F2", "Alna/Calcutta" },
3386 { "ti", "Asia/Calcutta", "2004-07-15T00:00:00Z", "vvvv", "\\u1205\\u1295\\u12F2", "Asia/Calcutta" },
3387
3388 // Ticket#8589 Partial location name to use country name if the zone is the golden
3389 // zone for the time zone's country.
3390 { "en_MX", "America/Chicago", "1995-07-15T00:00:00Z", "vvvv", "Central Time (United States)", "America/Chicago"},
3391
3392 // Tests proper handling of time zones that should have empty sets when inherited from the parent.
3393 // For example, en_GB understands CET as Central European Time, but en_HK, which inherits from en_GB
3394 // does not
3395 { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3396 { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3397 { "en_GB", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "CET", "+1:00"},
3398 { "en_GB", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "CEST", "+2:00"},
3399 { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "zzzz", "Central European Standard Time", "+1:00"},
3400 { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "zzzz", "Central European Summer Time", "+2:00"},
3401 { "en_HK", "Europe/Paris", "2004-01-15T00:00:00Z", "z", "GMT+1", "+1:00"},
3402 { "en_HK", "Europe/Paris", "2004-07-15T00:00:00Z", "z", "GMT+2", "+2:00"},
3403
3404 { NULL, NULL, NULL, NULL, NULL, NULL },
3405 };
3406
3407 UErrorCode status = U_ZERO_ERROR;
3408 LocalPointer<Calendar> cal(GregorianCalendar::createInstance(status));
3409 if (failure(status, "GregorianCalendar::createInstance", TRUE)) return;
3410 SimpleDateFormat testfmt(UnicodeString("yyyy-MM-dd'T'HH:mm:ss'Z'"), status);
3411 if (failure(status, "SimpleDateFormat constructor", TRUE)) return;
3412 testfmt.setTimeZone(*TimeZone::getGMT());
3413
3414 for (int i = 0; fallbackTests[i][0]; i++) {
3415 const char **testLine = fallbackTests[i];
3416 UnicodeString info[5];
3417 for ( int j = 0 ; j < 5 ; j++ ) {
3418 info[j] = UnicodeString(testLine[j], -1, US_INV);
3419 }
3420 info[4] = info[4].unescape();
3421 logln("%s;%s;%s;%s", testLine[0], testLine[1], testLine[2], testLine[3]);
3422
3423 TimeZone *tz = TimeZone::createTimeZone(info[1]);
3424
3425 UDate d = testfmt.parse(testLine[2], status);
3426 cal->setTime(d, status);
3427 if (U_FAILURE(status)) {
3428 errln(UnicodeString("Failed to set date: ") + testLine[2]);
3429 }
3430
3431 SimpleDateFormat fmt(info[3], Locale(testLine[0]),status);
3432 ASSERT_OK(status);
3433 cal->adoptTimeZone(tz);
3434 UnicodeString result;
3435 FieldPosition pos(FieldPosition::DONT_CARE);
3436 fmt.format(*cal.getAlias(), result,pos);
3437 if (result != info[4]) {
3438 errln(info[0] + ";" + info[1] + ";" + info[2] + ";" + info[3] + " expected: '" +
3439 info[4] + "' but got: '" + result + "'");
3440 }
3441 }
3442}
3443
3444void DateFormatTest::TestRoundtripWithCalendar(void) {
3445 UErrorCode status = U_ZERO_ERROR;
3446
3447 TimeZone *tz = TimeZone::createTimeZone("Europe/Paris");
3448 TimeZone *gmt = TimeZone::createTimeZone("Etc/GMT");
3449
3450 Calendar *calendars[] = {
3451 Calendar::createInstance(*tz, Locale("und@calendar=gregorian"), status),
3452 Calendar::createInstance(*tz, Locale("und@calendar=buddhist"), status),
3453// Calendar::createInstance(*tz, Locale("und@calendar=hebrew"), status),
3454 Calendar::createInstance(*tz, Locale("und@calendar=islamic"), status),
3455 Calendar::createInstance(*tz, Locale("und@calendar=japanese"), status),
3456 NULL
3457 };
3458 if (U_FAILURE(status)) {
3459 dataerrln("Failed to initialize calendars: %s", u_errorName(status));
3460 for (int i = 0; calendars[i] != NULL; i++) {
3461 delete calendars[i];
3462 }
3463 return;
3464 }
3465
3466 //FIXME The formatters commented out below are currently failing because of
3467 // the calendar calculation problem reported by #6691
3468
3469 // The order of test formatters must match the order of calendars above.
3470 DateFormat *formatters[] = {
3471 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("en_US")), //calendar=gregorian
3472 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("th_TH")), //calendar=buddhist
3473// DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("he_IL@calendar=hebrew")),
3474 DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ar_EG@calendar=islamic")),
3475// DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale("ja_JP@calendar=japanese")),
3476 NULL
3477 };
3478
3479 UDate d = Calendar::getNow();
3480 UnicodeString buf;
3481 FieldPosition fpos;
3482 ParsePosition ppos;
3483
3484 for (int i = 0; formatters[i] != NULL; i++) {
3485 buf.remove();
3486 fpos.setBeginIndex(0);
3487 fpos.setEndIndex(0);
3488 calendars[i]->setTime(d, status);
3489
3490 // Normal case output - the given calendar matches the calendar
3491 // used by the formatter
3492 formatters[i]->format(*calendars[i], buf, fpos);
3493 UnicodeString refStr(buf);
3494
3495 for (int j = 0; calendars[j] != NULL; j++) {
3496 if (j == i) {
3497 continue;
3498 }
3499 buf.remove();
3500 fpos.setBeginIndex(0);
3501 fpos.setEndIndex(0);
3502 calendars[j]->setTime(d, status);
3503
3504 // Even the different calendar type is specified,
3505 // we should get the same result.
3506 formatters[i]->format(*calendars[j], buf, fpos);
3507 if (refStr != buf) {
3508 errln((UnicodeString)"FAIL: Different format result with a different calendar for the same time -"
3509 + "\n Reference calendar type=" + calendars[i]->getType()
3510 + "\n Another calendar type=" + calendars[j]->getType()
3511 + "\n Expected result=" + refStr
3512 + "\n Actual result=" + buf);
3513 }
3514 }
3515
3516 calendars[i]->setTimeZone(*gmt);
3517 calendars[i]->clear();
3518 ppos.setErrorIndex(-1);
3519 ppos.setIndex(0);
3520
3521 // Normal case parse result - the given calendar matches the calendar
3522 // used by the formatter
3523 formatters[i]->parse(refStr, *calendars[i], ppos);
3524
3525 for (int j = 0; calendars[j] != NULL; j++) {
3526 if (j == i) {
3527 continue;
3528 }
3529 calendars[j]->setTimeZone(*gmt);
3530 calendars[j]->clear();
3531 ppos.setErrorIndex(-1);
3532 ppos.setIndex(0);
3533
3534 // Even the different calendar type is specified,
3535 // we should get the same time and time zone.
3536 formatters[i]->parse(refStr, *calendars[j], ppos);
3537 if (calendars[i]->getTime(status) != calendars[j]->getTime(status)
3538 || calendars[i]->getTimeZone() != calendars[j]->getTimeZone()) {
3539 UnicodeString tzid;
3540 errln((UnicodeString)"FAIL: Different parse result with a different calendar for the same string -"
3541 + "\n Reference calendar type=" + calendars[i]->getType()
3542 + "\n Another calendar type=" + calendars[j]->getType()
3543 + "\n Date string=" + refStr
3544 + "\n Expected time=" + calendars[i]->getTime(status)
3545 + "\n Expected time zone=" + calendars[i]->getTimeZone().getID(tzid)
3546 + "\n Actual time=" + calendars[j]->getTime(status)
3547 + "\n Actual time zone=" + calendars[j]->getTimeZone().getID(tzid));
3548 }
3549 }
3550 if (U_FAILURE(status)) {
3551 errln((UnicodeString)"FAIL: " + u_errorName(status));
3552 break;
3553 }
3554 }
3555
3556 delete tz;
3557 delete gmt;
3558 for (int i = 0; calendars[i] != NULL; i++) {
3559 delete calendars[i];
3560 }
3561 for (int i = 0; formatters[i] != NULL; i++) {
3562 delete formatters[i];
3563 }
3564}
3565
3566/*
3567void DateFormatTest::TestRelativeError(void)
3568{
3569 UErrorCode status;
3570 Locale en("en");
3571
3572 DateFormat *en_reltime_reldate = DateFormat::createDateTimeInstance(DateFormat::kFullRelative,DateFormat::kFullRelative,en);
3573 if(en_reltime_reldate == NULL) {
3574 logln("PASS: rel date/rel time failed");
3575 } else {
3576 errln("FAIL: rel date/rel time created, should have failed.");
3577 delete en_reltime_reldate;
3578 }
3579}
3580
3581void DateFormatTest::TestRelativeOther(void)
3582{
3583 logln("Nothing in this test. When we get more data from CLDR, put in some tests of -2, +2, etc. ");
3584}
3585*/
3586
3587void DateFormatTest::Test6338(void)
3588{
3589 UErrorCode status = U_ZERO_ERROR;
3590
3591 SimpleDateFormat fmt1(UnicodeString(u"y-M-d"), Locale("ar"), status);
3592 if (failure(status, "new SimpleDateFormat", TRUE)) return;
3593
3594 UDate dt1 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3595 UnicodeString str1;
3596 str1 = fmt1.format(dt1, str1);
3597 logln(str1);
3598
3599 UDate dt11 = fmt1.parse(str1, status);
3600 failure(status, "fmt->parse");
3601
3602 UnicodeString str11;
3603 str11 = fmt1.format(dt11, str11);
3604 logln(str11);
3605
3606 if (str1 != str11) {
3607 errln((UnicodeString)"FAIL: Different dates str1:" + str1
3608 + " str2:" + str11);
3609 }
3610
3611 /////////////////
3612
3613 status = U_ZERO_ERROR;
3614 SimpleDateFormat fmt2(UnicodeString(u"y M d"), Locale("ar"), status);
3615 failure(status, "new SimpleDateFormat");
3616
3617 UDate dt2 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3618 UnicodeString str2;
3619 str2 = fmt2.format(dt2, str2);
3620 logln(str2);
3621
3622 UDate dt22 = fmt2.parse(str2, status);
3623 failure(status, "fmt->parse");
3624
3625 UnicodeString str22;
3626 str22 = fmt2.format(dt22, str22);
3627 logln(str22);
3628
3629 if (str2 != str22) {
3630 errln((UnicodeString)"FAIL: Different dates str1:" + str2
3631 + " str2:" + str22);
3632 }
3633
3634 /////////////////
3635
3636 status = U_ZERO_ERROR;
3637 SimpleDateFormat fmt3(UnicodeString("y-M-d"), Locale("en-us"), status);
3638 failure(status, "new SimpleDateFormat");
3639
3640 UDate dt3 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3641 UnicodeString str3;
3642 str3 = fmt3.format(dt3, str3);
3643 logln(str3);
3644
3645 UDate dt33 = fmt3.parse(str3, status);
3646 failure(status, "fmt->parse");
3647
3648 UnicodeString str33;
3649 str33 = fmt3.format(dt33, str33);
3650 logln(str33);
3651
3652 if (str3 != str33) {
3653 errln((UnicodeString)"FAIL: Different dates str1:" + str3
3654 + " str2:" + str33);
3655 }
3656
3657 /////////////////
3658
3659 status = U_ZERO_ERROR;
3660 SimpleDateFormat fmt4(UnicodeString("y M d"), Locale("en-us"), status);
3661 failure(status, "new SimpleDateFormat");
3662
3663 UDate dt4 = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3664 UnicodeString str4;
3665 str4 = fmt4.format(dt4, str4);
3666 logln(str4);
3667
3668 UDate dt44 = fmt4.parse(str4, status);
3669 failure(status, "fmt->parse");
3670
3671 UnicodeString str44;
3672 str44 = fmt4.format(dt44, str44);
3673 logln(str44);
3674
3675 if (str4 != str44) {
3676 errln((UnicodeString)"FAIL: Different dates str1:" + str4
3677 + " str2:" + str44);
3678 }
3679
3680}
3681
3682void DateFormatTest::Test6726(void)
3683{
3684 // status
3685// UErrorCode status = U_ZERO_ERROR;
3686
3687 // fmtf, fmtl, fmtm, fmts;
3688 UnicodeString strf, strl, strm, strs;
3689 UDate dt = date(2008-1900, UCAL_JUNE, 10, 12, 00);
3690
3691 Locale loc("ja");
3692 DateFormat* fmtf = DateFormat::createDateTimeInstance(DateFormat::FULL, DateFormat::FULL, loc);
3693 DateFormat* fmtl = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::FULL, loc);
3694 DateFormat* fmtm = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, loc);
3695 DateFormat* fmts = DateFormat::createDateTimeInstance(DateFormat::SHORT, DateFormat::FULL, loc);
3696 if (fmtf == NULL || fmtl == NULL || fmtm == NULL || fmts == NULL) {
3697 dataerrln("Unable to create DateFormat. got NULL.");
3698 /* It may not be true that if one is NULL all is NULL. Just to be safe. */
3699 delete fmtf;
3700 delete fmtl;
3701 delete fmtm;
3702 delete fmts;
3703
3704 return;
3705 }
3706 strf = fmtf->format(dt, strf);
3707 strl = fmtl->format(dt, strl);
3708 strm = fmtm->format(dt, strm);
3709 strs = fmts->format(dt, strs);
3710
3711
3712 logln("strm.charAt(10)=%04X wanted 0x20\n", strm.charAt(10));
3713 if (strm.charAt(10) != UChar(0x0020)) {
3714 errln((UnicodeString)"FAIL: Improper formatted date: " + strm );
3715 }
3716 logln("strs.charAt(10)=%04X wanted 0x20\n", strs.charAt(8));
3717 if (strs.charAt(10) != UChar(0x0020)) {
3718 errln((UnicodeString)"FAIL: Improper formatted date: " + strs);
3719 }
3720
3721 delete fmtf;
3722 delete fmtl;
3723 delete fmtm;
3724 delete fmts;
3725
3726 return;
3727}
3728
3729/**
3730 * Test DateFormat's parsing of default GMT variants. See ticket#6135
3731 */
3732void DateFormatTest::TestGMTParsing() {
3733 const char* DATA[] = {
3734 "HH:mm:ss Z",
3735
3736 // pattern, input, expected output (in quotes)
3737 "HH:mm:ss Z", "10:20:30 GMT+03:00", "10:20:30 +0300",
3738 "HH:mm:ss Z", "10:20:30 UT-02:00", "10:20:30 -0200",
3739 "HH:mm:ss Z", "10:20:30 GMT", "10:20:30 +0000",
3740 "HH:mm:ss vvvv", "10:20:30 UT+10:00", "10:20:30 +1000",
3741 "HH:mm:ss zzzz", "10:20:30 UTC", "10:20:30 +0000", // standalone "UTC"
3742 "ZZZZ HH:mm:ss", "UT 10:20:30", "10:20:30 +0000",
3743 "z HH:mm:ss", "UT+0130 10:20:30", "10:20:30 +0130",
3744 "z HH:mm:ss", "UTC+0130 10:20:30", "10:20:30 +0130",
3745 // Note: GMT-1100 no longer works because of the introduction of the short
3746 // localized GMT support. Previous implementation support this level of
3747 // leniency (no separator char in localized GMT format), but the new
3748 // implementation handles GMT-11 as the legitimate short localized GMT format
3749 // and stop at there. Otherwise, roundtrip would be broken.
3750 //"HH mm Z ss", "10 20 GMT-1100 30", "10:20:30 -1100",
3751 "HH mm Z ss", "10 20 GMT-11 30", "10:20:30 -1100",
3752 "HH:mm:ssZZZZZ", "14:25:45Z", "14:25:45 +0000",
3753 "HH:mm:ssZZZZZ", "15:00:00-08:00", "15:00:00 -0800",
3754 };
3755 const int32_t DATA_len = UPRV_LENGTHOF(DATA);
3756 expectParse(DATA, DATA_len, Locale("en"));
3757}
3758
3759// Test case for localized GMT format parsing
3760// with no delimitters in offset format (Chinese locale)
3761void DateFormatTest::Test6880() {
3762 UErrorCode status = U_ZERO_ERROR;
3763 UDate d1, d2, dp1, dp2, dexp1, dexp2;
3764 UnicodeString s1, s2;
3765
3766 TimeZone *tz = TimeZone::createTimeZone("Asia/Shanghai");
3767 GregorianCalendar gcal(*tz, status);
3768 if (failure(status, "construct GregorianCalendar", TRUE)) return;
3769
3770 gcal.clear();
3771 gcal.set(1900, UCAL_JULY, 1, 12, 00); // offset 8:05:43
3772 d1 = gcal.getTime(status);
3773
3774 gcal.clear();
3775 gcal.set(1950, UCAL_JULY, 1, 12, 00); // offset 8:00
3776 d2 = gcal.getTime(status);
3777
3778 gcal.clear();
3779 gcal.set(1970, UCAL_JANUARY, 1, 12, 00);
3780 dexp2 = gcal.getTime(status);
3781 dexp1 = dexp2 - (5*60 + 43)*1000; // subtract 5m43s
3782
3783 if (U_FAILURE(status)) {
3784 errln("FAIL: Gregorian calendar error");
3785 }
3786
3787 DateFormat *fmt = DateFormat::createTimeInstance(DateFormat::kFull, Locale("zh"));
3788 if (fmt == NULL) {
3789 dataerrln("Unable to create DateFormat. Got NULL.");
3790 return;
3791 }
3792 fmt->adoptTimeZone(tz);
3793
3794 fmt->format(d1, s1);
3795 fmt->format(d2, s2);
3796
3797 dp1 = fmt->parse(s1, status);
3798 dp2 = fmt->parse(s2, status);
3799
3800 if (U_FAILURE(status)) {
3801 errln("FAIL: Parse failure");
3802 }
3803
3804 if (dp1 != dexp1) {
3805 errln("FAIL: Failed to parse " + s1 + " parsed: " + dp1 + " expected: " + dexp1);
3806 }
3807 if (dp2 != dexp2) {
3808 errln("FAIL: Failed to parse " + s2 + " parsed: " + dp2 + " expected: " + dexp2);
3809 }
3810
3811 delete fmt;
3812}
3813
3814typedef struct {
3815 const char * localeStr;
3816 UBool lenient;
3817 UBool expectFail;
3818 UnicodeString datePattern;
3819 UnicodeString dateString;
3820} NumAsStringItem;
3821
3822void DateFormatTest::TestNumberAsStringParsing()
3823{
3824 const NumAsStringItem items[] = {
3825 // loc lenient fail? datePattern dateString
3826 { "", FALSE, TRUE, UnicodeString("y MMMM d HH:mm:ss"), UnicodeString("2009 7 14 08:43:57") },
3827 { "", TRUE, FALSE, UnicodeString("y MMMM d HH:mm:ss"), UnicodeString("2009 7 14 08:43:57") },
3828 { "en", FALSE, FALSE, UnicodeString("MMM d, y"), UnicodeString("Jul 14, 2009") },
3829 { "en", TRUE, FALSE, UnicodeString("MMM d, y"), UnicodeString("Jul 14, 2009") },
3830 { "en", FALSE, TRUE, UnicodeString("MMM d, y"), UnicodeString("7 14, 2009") },
3831 { "en", TRUE, FALSE, UnicodeString("MMM d, y"), UnicodeString("7 14, 2009") },
3832 { "ja", FALSE, FALSE, UnicodeString("yyyy/MM/dd"), UnicodeString("2009/07/14") },
3833 { "ja", TRUE, FALSE, UnicodeString("yyyy/MM/dd"), UnicodeString("2009/07/14") },
3834 //{ "ja", FALSE, FALSE, UnicodeString("yyyy/MMMMM/d"), UnicodeString("2009/7/14") }, // #8860 covers test failure
3835 { "ja", TRUE, FALSE, UnicodeString("yyyy/MMMMM/d"), UnicodeString("2009/7/14") },
3836 { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3837 { "ja", TRUE, FALSE, CharsToUnicodeString("y\\u5E74M\\u6708d\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3838 { "ja", FALSE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") },
3839 { "ja", TRUE, FALSE, CharsToUnicodeString("y\\u5E74MMMd\\u65E5"), CharsToUnicodeString("2009\\u5E747\\u670814\\u65E5") }, // #8820 fixes test failure
3840 { "ko", FALSE, FALSE, UnicodeString("yyyy. M. d."), UnicodeString("2009. 7. 14.") },
3841 { "ko", TRUE, FALSE, UnicodeString("yyyy. M. d."), UnicodeString("2009. 7. 14.") },
3842 { "ko", FALSE, FALSE, UnicodeString("yyyy. MMMMM d."), CharsToUnicodeString("2009. 7\\uC6D4 14.") },
3843 { "ko", TRUE, FALSE, UnicodeString("yyyy. MMMMM d."), CharsToUnicodeString("2009. 7\\uC6D4 14.") }, // #8820 fixes test failure
3844 { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3845 { "ko", TRUE, FALSE, CharsToUnicodeString("y\\uB144 M\\uC6D4 d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3846 { "ko", FALSE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") },
3847 { "ko", TRUE, FALSE, CharsToUnicodeString("y\\uB144 MMM d\\uC77C"), CharsToUnicodeString("2009\\uB144 7\\uC6D4 14\\uC77C") }, // #8820 fixes test failure
3848 { NULL, FALSE, FALSE, UnicodeString(""), UnicodeString("") }
3849 };
3850 const NumAsStringItem * itemPtr;
3851 for (itemPtr = items; itemPtr->localeStr != NULL; itemPtr++ ) {
3852 Locale locale = Locale::createFromName(itemPtr->localeStr);
3853 UErrorCode status = U_ZERO_ERROR;
3854 SimpleDateFormat formatter(itemPtr->datePattern, locale, status);
3855 if (U_FAILURE(status)) {
3856 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3857 return;
3858 }
3859
3860 formatter.setLenient(itemPtr->lenient);
3861 formatter.setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->lenient, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->lenient, status);
3862 UDate date1 = formatter.parse(itemPtr->dateString, status);
3863 if (U_FAILURE(status)) {
3864 if (!itemPtr->expectFail) {
3865 errln("FAIL, err when expected success: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3866 ": using pattern \"" + itemPtr->datePattern + "\", could not parse \"" + itemPtr->dateString + "\"; err: " + u_errorName(status) );
3867 }
3868 } else if (itemPtr->expectFail) {
3869 errln("FAIL, expected err but got none: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3870 ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\"." );
3871 } else if (!itemPtr->lenient) {
3872 UnicodeString formatted;
3873 formatter.format(date1, formatted);
3874 if (formatted != itemPtr->dateString) {
3875 errln("FAIL, mismatch formatting parsed date: Locale \"" + UnicodeString(itemPtr->localeStr) + "\", lenient " + itemPtr->lenient +
3876 ": using pattern \"" + itemPtr->datePattern + "\", did parse \"" + itemPtr->dateString + "\", formatted result \"" + formatted + "\".");
3877 }
3878 }
3879 }
3880}
3881
3882void DateFormatTest::TestISOEra() {
3883
3884 const char* data[] = {
3885 // input, output
3886 "BC 4004-10-23T07:00:00Z", "BC 4004-10-23T07:00:00Z",
3887 "AD 4004-10-23T07:00:00Z", "AD 4004-10-23T07:00:00Z",
3888 "-4004-10-23T07:00:00Z" , "BC 4005-10-23T07:00:00Z",
3889 "4004-10-23T07:00:00Z" , "AD 4004-10-23T07:00:00Z",
3890 };
3891
3892 int32_t numData = 8;
3893
3894 UErrorCode status = U_ZERO_ERROR;
3895
3896 // create formatter
3897 SimpleDateFormat *fmt1 = new SimpleDateFormat(UnicodeString("GGG yyyy-MM-dd'T'HH:mm:ss'Z"), status);
3898 failure(status, "new SimpleDateFormat", TRUE);
3899 if (status == U_MISSING_RESOURCE_ERROR) {
3900 if (fmt1 != NULL) {
3901 delete fmt1;
3902 }
3903 return;
3904 }
3905 for(int i=0; i < numData; i+=2) {
3906 // create input string
3907 UnicodeString in = data[i];
3908
3909 // parse string to date
3910 UDate dt1 = fmt1->parse(in, status);
3911 failure(status, "fmt->parse", TRUE);
3912
3913 // format date back to string
3914 UnicodeString out;
3915 out = fmt1->format(dt1, out);
3916 logln(out);
3917
3918 // check that roundtrip worked as expected
3919 UnicodeString expected = data[i+1];
3920 if (out != expected) {
3921 dataerrln((UnicodeString)"FAIL: " + in + " -> " + out + " expected -> " + expected);
3922 }
3923 }
3924
3925 delete fmt1;
3926}
3927void DateFormatTest::TestFormalChineseDate() {
3928
3929 UErrorCode status = U_ZERO_ERROR;
3930 UnicodeString pattern(u"y\u5e74M\u6708d\u65e5");
3931 UnicodeString numsys_override(u"y=hanidec;M=hans;d=hans");
3932
3933 // create formatter
3934 SimpleDateFormat sdf(pattern, numsys_override, Locale::getChina(),status);
3935 if (failure(status, "new SimpleDateFormat with override", true)) {
3936 return;
3937 }
3938
3939 UDate thedate = date(2009-1900, UCAL_JULY, 28);
3940 FieldPosition pos(FieldPosition::DONT_CARE);
3941 UnicodeString result;
3942 sdf.format(thedate,result,pos);
3943
3944 UnicodeString expected = "\\u4e8c\\u3007\\u3007\\u4e5d\\u5e74\\u4e03\\u6708\\u4e8c\\u5341\\u516b\\u65e5";
3945 expected = expected.unescape();
3946 if (result != expected) {
3947 dataerrln((UnicodeString)"FAIL: -> " + result + " expected -> " + expected);
3948 }
3949
3950 UDate parsedate = sdf.parse(expected,status);
3951 if ( parsedate != thedate ) {
3952 UnicodeString pat1 ("yyyy-MM-dd'T'HH:mm:ss'Z'", -1, US_INV );
3953 SimpleDateFormat usf(pat1, Locale::getEnglish(), status);
3954 UnicodeString parsedres,expres;
3955 usf.format(parsedate,parsedres,pos);
3956 usf.format(thedate,expres,pos);
3957 dataerrln((UnicodeString)"FAIL: parsed -> " + parsedres + " expected -> " + expres);
3958 }
3959}
3960
3961// Test case for #8675
3962// Incorrect parse offset with stand alone GMT string on 2nd or later iteration.
3963void DateFormatTest::TestStandAloneGMTParse() {
3964 UErrorCode status = U_ZERO_ERROR;
3965 SimpleDateFormat sdf("ZZZZ", Locale(""), status);
3966
3967 if (U_SUCCESS(status)) {
3968
3969 UnicodeString inText(u"GMT$$$");
3970 for (int32_t i = 0; i < 10; i++) {
3971 ParsePosition pos(0);
3972 sdf.parse(inText, pos);
3973 if (pos.getIndex() != 3) {
3974 errln((UnicodeString)"FAIL: Incorrect output parse position: actual=" + pos.getIndex() + " expected=3");
3975 }
3976 }
3977
3978 } else {
3979 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
3980 }
3981}
3982
3983void DateFormatTest::TestParsePosition() {
3984 const char* TestData[][4] = {
3985 // {<pattern>, <lead>, <date string>, <trail>}
3986 {"yyyy-MM-dd HH:mm:ssZ", "", "2010-01-10 12:30:00+0500", ""},
3987 {"yyyy-MM-dd HH:mm:ss ZZZZ", "", "2010-01-10 12:30:00 GMT+05:00", ""},
3988 {"Z HH:mm:ss", "", "-0100 13:20:30", ""},
3989 {"y-M-d Z", "", "2011-8-25 -0400", " Foo"},
3990 {"y/M/d H:mm:ss z", "", "2011/7/1 12:34:00 PDT", ""},
3991 {"y/M/d H:mm:ss z", "+123", "2011/7/1 12:34:00 PDT", " PST"},
3992 {"vvvv a h:mm:ss", "", "Pacific Time AM 10:21:45", ""},
3993 {"HH:mm v M/d", "111", "14:15 PT 8/10", " 12345"},
3994 {"'time zone:' VVVV 'date:' yyyy-MM-dd", "xxxx", "time zone: Los Angeles Time date: 2010-02-25", "xxxx"},
3995 {"yG", "", "2012AD", ""},
3996 {"yG", "", "2012", "x"},
3997 {0, 0, 0, 0},
3998 };
3999
4000 for (int32_t i = 0; TestData[i][0]; i++) {
4001 UErrorCode status = U_ZERO_ERROR;
4002 SimpleDateFormat sdf(UnicodeString(TestData[i][0]), status);
4003 if (failure(status, "new SimpleDateFormat", TRUE)) return;
4004
4005 int32_t startPos, resPos;
4006
4007 // lead text
4008 UnicodeString input(TestData[i][1]);
4009 startPos = input.length();
4010
4011 // date string
4012 input += TestData[i][2];
4013 resPos = input.length();
4014
4015 // trail text
4016 input += TestData[i][3];
4017
4018 ParsePosition pos(startPos);
4019 //UDate d = sdf->parse(input, pos);
4020 (void)sdf.parse(input, pos);
4021
4022 if (pos.getIndex() != resPos) {
4023 errln(UnicodeString("FAIL: Parsing [") + input + "] with pattern [" + TestData[i][0] + "] returns position - "
4024 + pos.getIndex() + ", expected - " + resPos);
4025 }
4026 }
4027}
4028
4029
4030typedef struct {
4031 int32_t era;
4032 int32_t year;
4033 int32_t month; // 1-based
4034 int32_t isLeapMonth;
4035 int32_t day;
4036} ChineseCalTestDate;
4037
4038#define NUM_TEST_DATES 3
4039
4040typedef struct {
4041 const char * locale;
4042 int32_t style; // <0 => custom
4043 UnicodeString dateString[NUM_TEST_DATES];
4044} MonthPatternItem;
4045
4046void DateFormatTest::TestMonthPatterns()
4047{
4048 const ChineseCalTestDate dates[NUM_TEST_DATES] = {
4049 // era yr mo lp da
4050 { 78, 29, 4, 0, 2 }, // (in chinese era 78) gregorian 2012-4-22
4051 { 78, 29, 4, 1, 2 }, // (in chinese era 78) gregorian 2012-5-22
4052 { 78, 29, 5, 0, 2 }, // (in chinese era 78) gregorian 2012-6-20
4053 };
4054
4055 const MonthPatternItem items[] = {
4056 // locale date style; expected formats for the 3 dates above
4057 { "root@calendar=chinese", DateFormat::kLong, { UnicodeString("2012(ren-chen) M04 2"), UnicodeString("2012(ren-chen) M04bis 2"), UnicodeString("2012(ren-chen) M05 2") } },
4058 { "root@calendar=chinese", DateFormat::kShort, { UnicodeString("2012-04-02"), UnicodeString("2012-04bis-02"), UnicodeString("2012-05-02") } },
4059 { "root@calendar=chinese", -1, { UnicodeString("29-4-2"), UnicodeString("29-4bis-2"), UnicodeString("29-5-2") } },
4060 { "root@calendar=chinese", -2, { UnicodeString("78x29-4-2"), UnicodeString("78x29-4bis-2"), UnicodeString("78x29-5-2") } },
4061 { "root@calendar=chinese", -3, { UnicodeString("ren-chen-4-2"), UnicodeString("ren-chen-4bis-2"), UnicodeString("ren-chen-5-2") } },
4062 { "root@calendar=chinese", -4, { UnicodeString("ren-chen M04 2"), UnicodeString("ren-chen M04bis 2"), UnicodeString("ren-chen M05 2") } },
4063 { "en@calendar=gregorian", -3, { UnicodeString("2012-4-22"), UnicodeString("2012-5-22"), UnicodeString("2012-6-20") } },
4064 { "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)") } },
4065 { "en@calendar=chinese", DateFormat::kShort, { UnicodeString("4/2/2012"), UnicodeString("4bis/2/2012"), UnicodeString("5/2/2012") } },
4066 { "zh@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4067 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u95F0\\u56DB\\u6708\\u521D\\u4E8C"),
4068 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4069 { "zh@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("2012-4-2"),
4070 CharsToUnicodeString("2012-\\u95F04-2"),
4071 CharsToUnicodeString("2012-5-2") } },
4072 { "zh@calendar=chinese", -3, { CharsToUnicodeString("\\u58EC\\u8FB0-4-2"),
4073 CharsToUnicodeString("\\u58EC\\u8FB0-\\u95F04-2"),
4074 CharsToUnicodeString("\\u58EC\\u8FB0-5-2") } },
4075 { "zh@calendar=chinese", -4, { CharsToUnicodeString("\\u58EC\\u8FB0 \\u56DB\\u6708 2"),
4076 CharsToUnicodeString("\\u58EC\\u8FB0 \\u95F0\\u56DB\\u6708 2"),
4077 CharsToUnicodeString("\\u58EC\\u8FB0 \\u4E94\\u6708 2") } },
4078 { "zh_Hant@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u56DB\\u6708\\u521D\\u4E8C"),
4079 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u958F\\u56DB\\u6708\\u521D\\u4E8C"),
4080 CharsToUnicodeString("2012\\u58EC\\u8FB0\\u5E74\\u4E94\\u6708\\u521D\\u4E8C") } },
4081 { "zh_Hant@calendar=chinese", DateFormat::kShort, { CharsToUnicodeString("2012/4/2"),
4082 CharsToUnicodeString("2012/\\u958F4/2"),
4083 CharsToUnicodeString("2012/5/2") } },
4084 { "fr@calendar=chinese", DateFormat::kLong, { CharsToUnicodeString("2 s\\u00ECyu\\u00E8 ren-chen"),
4085 CharsToUnicodeString("2 s\\u00ECyu\\u00E8bis ren-chen"),
4086 CharsToUnicodeString("2 w\\u01D4yu\\u00E8 ren-chen") } },
4087 { "fr@calendar=chinese", DateFormat::kShort, { UnicodeString("2/4/29"), UnicodeString("2/4bis/29"), UnicodeString("2/5/29") } },
4088 { "en@calendar=dangi", DateFormat::kLong, { UnicodeString("Third Monthbis 2, 2012(ren-chen)"), UnicodeString("Fourth Month 2, 2012(ren-chen)"), UnicodeString("Fifth Month 1, 2012(ren-chen)") } },
4089 { "en@calendar=dangi", DateFormat::kShort, { UnicodeString("3bis/2/2012"), UnicodeString("4/2/2012"), UnicodeString("5/1/2012") } },
4090 { "en@calendar=dangi", -2, { UnicodeString("78x29-3bis-2"), UnicodeString("78x29-4-2"), UnicodeString("78x29-5-1") } },
4091 { "ko@calendar=dangi", DateFormat::kLong, { CharsToUnicodeString("\\uC784\\uC9C4\\uB144 \\uC7243\\uC6D4 2\\uC77C"),
4092 CharsToUnicodeString("\\uC784\\uC9C4\\uB144 4\\uC6D4 2\\uC77C"),
4093 CharsToUnicodeString("\\uC784\\uC9C4\\uB144 5\\uC6D4 1\\uC77C") } },
4094 { "ko@calendar=dangi", DateFormat::kShort, { CharsToUnicodeString("29. \\uC7243. 2."),
4095 CharsToUnicodeString("29. 4. 2."),
4096 CharsToUnicodeString("29. 5. 1.") } },
4097 // terminator
4098 { NULL, 0, { UnicodeString(""), UnicodeString(""), UnicodeString("") } }
4099 };
4100
4101 //. style: -1 -2 -3 -4
4102 const UnicodeString customPatterns[] = { "y-Ml-d", "G'x'y-Ml-d", "U-M-d", "U MMM d" }; // like old root pattern, using 'l'
4103
4104 UErrorCode status = U_ZERO_ERROR;
4105 Locale rootChineseCalLocale = Locale::createFromName("root@calendar=chinese");
4106 Calendar * rootChineseCalendar = Calendar::createInstance(rootChineseCalLocale, status);
4107 if (U_SUCCESS(status)) {
4108 const MonthPatternItem * itemPtr;
4109 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4110 Locale locale = Locale::createFromName(itemPtr->locale);
4111 DateFormat * dmft = (itemPtr->style >= 0)?
4112 DateFormat::createDateInstance((DateFormat::EStyle)itemPtr->style, locale):
4113 new SimpleDateFormat(customPatterns[-itemPtr->style - 1], locale, status);
4114 if ( dmft != NULL ) {
4115 if (U_SUCCESS(status)) {
4116 const ChineseCalTestDate * datePtr = dates;
4117 int32_t idate;
4118 for (idate = 0; idate < NUM_TEST_DATES; idate++, datePtr++) {
4119 rootChineseCalendar->clear();
4120 rootChineseCalendar->set(UCAL_ERA, datePtr->era);
4121 rootChineseCalendar->set(datePtr->year, datePtr->month-1, datePtr->day);
4122 rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, datePtr->isLeapMonth);
4123 UnicodeString result;
4124 FieldPosition fpos(FieldPosition::DONT_CARE);
4125 dmft->format(*rootChineseCalendar, result, fpos);
4126 if ( result.compare(itemPtr->dateString[idate]) != 0 ) {
4127 errln( UnicodeString("FAIL: Chinese calendar format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4128 ", expected \"" + itemPtr->dateString[idate] + "\", got \"" + result + "\"");
4129 } else {
4130 // formatted OK, try parse
4131 ParsePosition ppos(0);
4132 // ensure we are really parsing the fields we should be
4133 rootChineseCalendar->set(UCAL_YEAR, 1);
4134 rootChineseCalendar->set(UCAL_MONTH, 0);
4135 rootChineseCalendar->set(UCAL_IS_LEAP_MONTH, 0);
4136 rootChineseCalendar->set(UCAL_DATE, 1);
4137 //
4138 dmft->parse(result, *rootChineseCalendar, ppos);
4139 int32_t year = rootChineseCalendar->get(UCAL_YEAR, status);
4140 int32_t month = rootChineseCalendar->get(UCAL_MONTH, status) + 1;
4141 int32_t isLeapMonth = rootChineseCalendar->get(UCAL_IS_LEAP_MONTH, status);
4142 int32_t day = rootChineseCalendar->get(UCAL_DATE, status);
4143 if ( ppos.getIndex() < result.length() || year != datePtr->year || month != datePtr->month || isLeapMonth != datePtr->isLeapMonth || day != datePtr->day ) {
4144 errln( UnicodeString("FAIL: Chinese calendar parse for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4145 ", string \"" + result + "\", expected " + datePtr->year +"-"+datePtr->month+"("+datePtr->isLeapMonth+")-"+datePtr->day + ", got pos " +
4146 ppos.getIndex() + " " + year +"-"+month+"("+isLeapMonth+")-"+day);
4147 }
4148 }
4149 }
4150 } else {
4151 dataerrln("Error creating SimpleDateFormat for Chinese calendar- %s", u_errorName(status));
4152 }
4153 delete dmft;
4154 } else {
4155 dataerrln("FAIL: Unable to create DateFormat for Chinese calendar- %s", u_errorName(status));
4156 }
4157 }
4158 delete rootChineseCalendar;
4159 } else {
4160 errln(UnicodeString("FAIL: Unable to create Calendar for root@calendar=chinese"));
4161 }
4162}
4163
4164typedef struct {
4165 const char * locale;
4166 UnicodeString pattern;
4167 UDisplayContext capitalizationContext;
4168 UnicodeString expectedFormat;
4169} TestContextItem;
4170
4171void DateFormatTest::TestContext()
4172{
4173 const UDate july022008 = 1215000001979.0;
4174 const TestContextItem items[] = {
4175 //locale pattern capitalizationContext expected formatted date
4176 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_NONE, UnicodeString("juillet 2008") },
4177#if !UCONFIG_NO_BREAK_ITERATION
4178 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, UnicodeString("juillet 2008") },
4179 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, UnicodeString("Juillet 2008") },
4180 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, UnicodeString("juillet 2008") },
4181 { "fr", UnicodeString("MMMM y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE, UnicodeString("Juillet 2008") },
4182#endif
4183 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_NONE, CharsToUnicodeString("\\u010Dervenec 2008") },
4184#if !UCONFIG_NO_BREAK_ITERATION
4185 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, CharsToUnicodeString("\\u010Dervenec 2008") },
4186 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, CharsToUnicodeString("\\u010Cervenec 2008") },
4187 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, CharsToUnicodeString("\\u010Cervenec 2008") },
4188 { "cs", UnicodeString("LLLL y"), UDISPCTX_CAPITALIZATION_FOR_STANDALONE, CharsToUnicodeString("\\u010Dervenec 2008") },
4189#endif
4190 // terminator
4191 { NULL, UnicodeString(""), (UDisplayContext)0, UnicodeString("") }
4192 };
4193 UErrorCode status = U_ZERO_ERROR;
4194 Calendar* cal = Calendar::createInstance(status);
4195 if (U_FAILURE(status)) {
4196 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4197 } else {
4198 cal->setTime(july022008, status);
4199 const TestContextItem * itemPtr;
4200 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4201 Locale locale = Locale::createFromName(itemPtr->locale);
4202 status = U_ZERO_ERROR;
4203 SimpleDateFormat * sdmft = new SimpleDateFormat(itemPtr->pattern, locale, status);
4204 if (U_FAILURE(status)) {
4205 dataerrln(UnicodeString("FAIL: Unable to create SimpleDateFormat for specified pattern with locale ") + UnicodeString(itemPtr->locale));
4206 } else {
4207 sdmft->setContext(itemPtr->capitalizationContext, status);
4208 UnicodeString result;
4209 FieldPosition pos(FieldPosition::DONT_CARE);
4210 sdmft->format(*cal, result, pos);
4211 if (result.compare(itemPtr->expectedFormat) != 0) {
4212 errln(UnicodeString("FAIL: format for locale ") + UnicodeString(itemPtr->locale) +
4213 ", status " + (int)status +
4214 ", capitalizationContext " + (int)itemPtr->capitalizationContext +
4215 ", expected " + itemPtr->expectedFormat + ", got " + result);
4216 }
4217 }
4218 if (sdmft) {
4219 delete sdmft;
4220 }
4221 }
4222 }
4223 if (cal) {
4224 delete cal;
4225 }
4226}
4227
4228// test item for a particular locale + calendar and date format
4229typedef struct {
4230 int32_t era;
4231 int32_t year;
4232 int32_t month;
4233 int32_t day;
4234 int32_t hour;
4235 int32_t minute;
4236 UnicodeString formattedDate;
4237} CalAndFmtTestItem;
4238
4239// test item giving locale + calendar, date format, and CalAndFmtTestItems
4240typedef struct {
4241 const char * locale; // with calendar
4242 DateFormat::EStyle style;
4243 UnicodeString pattern; // ignored unless style == DateFormat::kNone
4244 const CalAndFmtTestItem *caftItems;
4245} TestNonGregoItem;
4246
4247void DateFormatTest::TestNonGregoFmtParse()
4248{
4249 // test items for he@calendar=hebrew, long date format
4250 const CalAndFmtTestItem cafti_he_hebrew_long[] = {
4251 { 0, 4999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05D3\\u05F3\\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4252 { 0, 5100, 0, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05E7\\u05F3") },
4253 { 0, 5774, 5, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05D0\\u05D3\\u05E8 \\u05D0\\u05F3 \\u05EA\\u05E9\\u05E2\\u05F4\\u05D3") },
4254 { 0, 5999, 12, 29, 12, 0, CharsToUnicodeString("\\u05DB\\u05F4\\u05D8 \\u05D1\\u05D0\\u05DC\\u05D5\\u05DC \\u05EA\\u05EA\\u05E7\\u05E6\\u05F4\\u05D8") },
4255 { 0, 6100, 0, 1, 12, 0, CharsToUnicodeString("\\u05D0\\u05F3 \\u05D1\\u05EA\\u05E9\\u05E8\\u05D9 \\u05D5\\u05F3\\u05E7\\u05F3") },
4256 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4257 };
4258 const CalAndFmtTestItem cafti_zh_chinese_custU[] = {
4259 { 78, 31, 0, 1, 12, 0, CharsToUnicodeString("2014\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4260 { 77, 31, 0, 1, 12, 0, CharsToUnicodeString("1954\\u7532\\u5348\\u5E74\\u6B63\\u67081") },
4261 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4262 };
4263 const CalAndFmtTestItem cafti_zh_chinese_custNoU[] = {
4264 { 78, 31, 0, 1, 12, 0, CharsToUnicodeString("2014\\u5E74\\u6B63\\u67081") },
4265 { 77, 31, 0, 1, 12, 0, CharsToUnicodeString("1954\\u5E74\\u6B63\\u67081") },
4266 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4267 };
4268 const CalAndFmtTestItem cafti_ja_japanese_custGy[] = {
4269 {235, 26, 2, 5, 12, 0, CharsToUnicodeString("2014(\\u5E73\\u621026)\\u5E743\\u67085\\u65E5") },
4270 {234, 60, 2, 5, 12, 0, CharsToUnicodeString("1985(\\u662D\\u548C60)\\u5E743\\u67085\\u65E5") },
4271 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4272 };
4273 const CalAndFmtTestItem cafti_ja_japanese_custNoGy[] = {
4274 {235, 26, 2, 5, 12, 0, CharsToUnicodeString("2014\\u5E743\\u67085\\u65E5") },
4275 {234, 60, 2, 5, 12, 0, CharsToUnicodeString("1985\\u5E743\\u67085\\u65E5") },
4276 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4277 };
4278 const CalAndFmtTestItem cafti_en_islamic_cust[] = {
4279 { 0, 1384, 0, 1, 12, 0, UnicodeString("1 Muh. 1384 AH, 1964") },
4280 { 0, 1436, 0, 1, 12, 0, UnicodeString("1 Muh. 1436 AH, 2014") },
4281 { 0, 1487, 0, 1, 12, 0, UnicodeString("1 Muh. 1487 AH, 2064") },
4282 { 0, 0, 0, 0, 0, 0, UnicodeString("") } // terminator
4283 };
4284 // overal test items
4285 const TestNonGregoItem items[] = {
4286 { "he@calendar=hebrew", DateFormat::kLong, UnicodeString(""), cafti_he_hebrew_long },
4287 { "zh@calendar=chinese", DateFormat::kNone, CharsToUnicodeString("rU\\u5E74MMMd"), cafti_zh_chinese_custU },
4288 { "zh@calendar=chinese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74MMMd"), cafti_zh_chinese_custNoU },
4289 { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r(Gy)\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custGy },
4290 { "ja@calendar=japanese", DateFormat::kNone, CharsToUnicodeString("r\\u5E74M\\u6708d\\u65E5"), cafti_ja_japanese_custNoGy },
4291 { "en@calendar=islamic", DateFormat::kNone, UnicodeString("d MMM y G, r"), cafti_en_islamic_cust },
4292 { NULL, DateFormat::kNone, UnicodeString(""), NULL } // terminator
4293 };
4294 const TestNonGregoItem * itemPtr;
4295 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++) {
4296 Locale locale = Locale::createFromName(itemPtr->locale);
4297 LocalPointer<DateFormat> dfmt;
4298 UErrorCode status = U_ZERO_ERROR;
4299 if (itemPtr->style != DateFormat::kNone) {
4300 dfmt.adoptInstead(DateFormat::createDateInstance(itemPtr->style, locale));
4301 } else {
4302 dfmt.adoptInstead(new SimpleDateFormat(itemPtr->pattern, locale, status));
4303 }
4304 if (U_FAILURE(status)) {
4305 dataerrln("new SimpleDateFormat fails for locale %s", itemPtr->locale);
4306 } else if (!dfmt.isValid()) {
4307 dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->locale);
4308 } else {
4309 LocalPointer<Calendar>cal((dfmt->getCalendar())->clone());
4310 if (!cal.isValid()) {
4311 dataerrln("(DateFormat::getCalendar)->clone() fails for locale %s", itemPtr->locale);
4312 } else {
4313 const CalAndFmtTestItem * caftItemPtr;
4314 for (caftItemPtr = itemPtr->caftItems; caftItemPtr->year != 0; caftItemPtr++) {
4315 cal->clear();
4316 cal->set(UCAL_ERA, caftItemPtr->era);
4317 cal->set(UCAL_YEAR, caftItemPtr->year);
4318 cal->set(UCAL_MONTH, caftItemPtr->month);
4319 cal->set(UCAL_DATE, caftItemPtr->day);
4320 cal->set(UCAL_HOUR_OF_DAY, caftItemPtr->hour);
4321 cal->set(UCAL_MINUTE, caftItemPtr->minute);
4322 UnicodeString result;
4323 FieldPosition fpos(FieldPosition::DONT_CARE);
4324 dfmt->format(*cal, result, fpos);
4325 if ( result.compare(caftItemPtr->formattedDate) != 0 ) {
4326 errln( UnicodeString("FAIL: date format for locale ") + UnicodeString(itemPtr->locale) + ", style " + itemPtr->style +
4327 ", expected \"" + caftItemPtr->formattedDate + "\", got \"" + result + "\"");
4328 } else {
4329 // formatted OK, try parse
4330 ParsePosition ppos(0);
4331 dfmt->parse(result, *cal, ppos);
4332 status = U_ZERO_ERROR;
4333 int32_t era = cal->get(UCAL_ERA, status);
4334 int32_t year = cal->get(UCAL_YEAR, status);
4335 int32_t month = cal->get(UCAL_MONTH, status);
4336 int32_t day = cal->get(UCAL_DATE, status);
4337 if ( U_FAILURE(status) || ppos.getIndex() < result.length() || era != caftItemPtr->era ||
4338 year != caftItemPtr->year || month != caftItemPtr->month || day != caftItemPtr->day ) {
4339 errln( UnicodeString("FAIL: date parse for locale ") + UnicodeString(itemPtr->locale) +
4340 ", style " + itemPtr->style + ", string \"" + result + "\", expected " +
4341 caftItemPtr->era +":"+caftItemPtr->year +"-"+caftItemPtr->month+"-"+caftItemPtr->day + ", got pos " +
4342 ppos.getIndex() + " " + year +"-"+month+"-"+day + " status " + UnicodeString(u_errorName(status)) );
4343 }
4344 }
4345 }
4346 }
4347 }
4348 }
4349}
4350
4351typedef struct {
4352 const char* localeID;
4353 DateFormat::EStyle style;
4354 UnicodeString expectPattern;
4355 UnicodeString expectFormat;
4356} TestFmtWithNumSysItem;
4357enum { kBBufMax = 128 };
4358void DateFormatTest::TestFormatsWithNumberSystems()
4359{
4360 LocalPointer<TimeZone> zone(TimeZone::createTimeZone(UnicodeString("UTC")));
4361 const UDate date = 1451556000000.0; // for UTC: grego 31-Dec-2015 10 AM, hebrew 19 tevet 5776, chinese yi-wei 11mo 21day
4362 const TestFmtWithNumSysItem items[] = {
4363 { "haw@calendar=gregorian", DateFormat::kShort, UnicodeString("d/M/yy"), UnicodeString("31/xii/15") },
4364 { "he@calendar=hebrew", DateFormat::kLong, CharsToUnicodeString("d \\u05D1MMMM y"), CharsToUnicodeString("\\u05D9\\u05F4\\u05D8 \\u05D1\\u05D8\\u05D1\\u05EA \\u05EA\\u05E9\\u05E2\\u05F4\\u05D5") }, // "י״ט בטבת תשע״ו"
4365 { "zh@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u51AC\\u6708\\u5EFF\\u4E00") }, // "2015乙未年冬月廿一"
4366 { "zh_Hant@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("rU\\u5E74MMMd"), CharsToUnicodeString("2015\\u4E59\\u672A\\u5E74\\u51AC\\u6708\\u5EFF\\u4E00") }, // "2015乙未年冬月廿一"
4367 { "ja@calendar=chinese", DateFormat::kLong, CharsToUnicodeString("U\\u5E74MMMd\\u65E5"), CharsToUnicodeString("\\u4E59\\u672A\\u5E74\\u5341\\u4E00\\u6708\\u4E8C\\u5341\\u4E00\\u65E5") }, // "乙未年十一月二十一日"
4368 { NULL, DateFormat::kNone, UnicodeString(""), UnicodeString("") },
4369 };
4370 const TestFmtWithNumSysItem * itemPtr;
4371 for (itemPtr = items; itemPtr->localeID != NULL; itemPtr++) {
4372 char bExpected[kBBufMax];
4373 char bResult[kBBufMax];
4374 UErrorCode status = U_ZERO_ERROR;
4375 Locale locale = Locale::createFromName(itemPtr->localeID);
4376 LocalPointer<Calendar> cal(Calendar::createInstance(zone.orphan(), locale, status));
4377 if (U_FAILURE(status)) {
4378 dataerrln("Calendar::createInstance fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4379 continue;
4380 }
4381 cal->setTime(date, status);
4382 if (U_FAILURE(status)) {
4383 dataerrln("Calendar::setTime fails for locale %s, date %.1f, status %s", itemPtr->localeID, date, u_errorName(status));
4384 continue;
4385 }
4386 LocalPointer<SimpleDateFormat> sdfmt(static_cast<SimpleDateFormat *>(DateFormat::createDateInstance(itemPtr->style, locale)));
4387 if (sdfmt.isNull()) {
4388 dataerrln("DateFormat::createDateInstance fails for locale %s", itemPtr->localeID);
4389 continue;
4390 }
4391 UnicodeString getFormat;
4392 sdfmt->format(*(cal.getAlias()), getFormat, NULL, status);
4393 if (U_FAILURE(status)) {
4394 errln("DateFormat::format fails for locale %s, status %s", itemPtr->localeID, u_errorName(status));
4395 continue;
4396 }
4397 if (getFormat.compare(itemPtr->expectFormat) != 0) {
4398 itemPtr->expectFormat.extract(0, itemPtr->expectFormat.length(), bExpected, kBBufMax);
4399 getFormat.extract(0, getFormat.length(), bResult, kBBufMax);
4400 errln("DateFormat::format for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4401 }
4402 UnicodeString getPattern;
4403 sdfmt->toPattern(getPattern);
4404 if (getPattern.compare(itemPtr->expectPattern) != 0) {
4405 itemPtr->expectPattern.extract(0, itemPtr->expectPattern.length(), bExpected, kBBufMax);
4406 getPattern.extract(0, getPattern.length(), bResult, kBBufMax);
4407 errln("DateFormat::toPattern() for locale %s, expected \"%s\", got \"%s\"", itemPtr->localeID, bExpected, bResult);
4408 }
4409 }
4410}
4411
4412static const UDate TEST_DATE = 1326585600000.; // 2012-jan-15
4413
4414void DateFormatTest::TestDotAndAtLeniency() {
4415 // Test for date/time parsing regression with CLDR 22.1/ICU 50 pattern strings.
4416 // For details see http://bugs.icu-project.org/trac/ticket/9789
4417 static const char *locales[] = { "en", "fr" };
4418 for (int32_t i = 0; i < UPRV_LENGTHOF(locales); ++i) {
4419 Locale locale(locales[i]);
4420
4421 for (DateFormat::EStyle dateStyle = DateFormat::FULL; dateStyle <= DateFormat::SHORT;
4422 dateStyle = static_cast<DateFormat::EStyle>(dateStyle + 1)) {
4423 LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance(dateStyle, locale));
4424
4425 for (DateFormat::EStyle timeStyle = DateFormat::FULL; timeStyle <= DateFormat::SHORT;
4426 timeStyle = static_cast<DateFormat::EStyle>(timeStyle + 1)) {
4427 LocalPointer<DateFormat> format(DateFormat::createDateTimeInstance(dateStyle, timeStyle, locale));
4428 LocalPointer<DateFormat> timeFormat(DateFormat::createTimeInstance(timeStyle, locale));
4429 UnicodeString formattedString;
4430 if (format.isNull()) {
4431 dataerrln("Unable to create DateFormat");
4432 continue;
4433 }
4434 format->format(TEST_DATE, formattedString);
4435
4436 if (!showParse(*format, formattedString)) {
4437 errln(UnicodeString(" with date-time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4438 }
4439
4440 UnicodeString ds, ts;
4441 formattedString = dateFormat->format(TEST_DATE, ds) + " " + timeFormat->format(TEST_DATE, ts);
4442 if (!showParse(*format, formattedString)) {
4443 errln(UnicodeString(" with date sp sp time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4444 }
4445 if (formattedString.indexOf("n ") >= 0) { // will add "." after the end of text ending in 'n', like Jan.
4446 UnicodeString plusDot(formattedString);
4447 plusDot.findAndReplace("n ", "n. ").append(".");
4448 if (!showParse(*format, plusDot)) {
4449 errln(UnicodeString(" with date plus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4450 }
4451 }
4452 if (formattedString.indexOf(". ") >= 0) { // will subtract "." at the end of strings.
4453 UnicodeString minusDot(formattedString);
4454 minusDot.findAndReplace(". ", " ");
4455 if (!showParse(*format, minusDot)) {
4456 errln(UnicodeString(" with date minus-dot time: dateStyle=") + dateStyle + " timeStyle=" + timeStyle);
4457 }
4458 }
4459 }
4460 }
4461 }
4462}
4463
4464UBool DateFormatTest::showParse(DateFormat &format, const UnicodeString &formattedString) {
4465 ParsePosition parsePosition;
4466 UDate parsed = format.parse(formattedString, parsePosition);
4467 UBool ok = TEST_DATE == parsed && parsePosition.getIndex() == formattedString.length();
4468 UnicodeString pattern;
4469 static_cast<SimpleDateFormat &>(format).toPattern(pattern);
4470 if (ok) {
4471 logln(pattern + " parsed: " + formattedString);
4472 } else {
4473 errln(pattern + " fails to parse: " + formattedString);
4474 }
4475 return ok;
4476}
4477
4478
4479typedef struct {
4480 const char * locale;
4481 UBool leniency;
4482 UnicodeString parseString;
4483 UnicodeString pattern;
4484 UnicodeString expectedResult; // empty string indicates expected error
4485} TestDateFormatLeniencyItem;
4486
4487void DateFormatTest::TestDateFormatLeniency() {
4488 // For details see http://bugs.icu-project.org/trac/ticket/10261
4489
4490 const UDate july022008 = 1215000001979.0;
4491 const TestDateFormatLeniencyItem items[] = {
4492 //locale leniency parse String pattern expected result
4493 { "en", true, UnicodeString("2008-07 02"), UnicodeString("yyyy-LLLL dd"), UnicodeString("2008-July 02") },
4494 { "en", false, UnicodeString("2008-07 02"), UnicodeString("yyyy-LLLL dd"), UnicodeString("") },
4495 { "en", true, UnicodeString("2008-Jan 02"), UnicodeString("yyyy-LLL. dd"), UnicodeString("2008-Jan. 02") },
4496 { "en", false, UnicodeString("2008-Jan 02"), UnicodeString("yyyy-LLL. dd"), UnicodeString("") },
4497 { "en", true, UnicodeString("2008-Jan--02"), UnicodeString("yyyy-MMM' -- 'dd"), UnicodeString("2008-Jan -- 02") },
4498 { "en", false, UnicodeString("2008-Jan--02"), UnicodeString("yyyy-MMM' -- 'dd"), UnicodeString("") },
4499 // terminator
4500 { NULL, true, UnicodeString(""), UnicodeString(""), UnicodeString("") }
4501 };
4502 UErrorCode status = U_ZERO_ERROR;
4503 LocalPointer<Calendar> cal(Calendar::createInstance(status));
4504 if (U_FAILURE(status)) {
4505 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4506 return;
4507 }
4508 cal->setTime(july022008, status);
4509 const TestDateFormatLeniencyItem * itemPtr;
4510 LocalPointer<SimpleDateFormat> sdmft;
4511 for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
4512
4513 Locale locale = Locale::createFromName(itemPtr->locale);
4514 status = U_ZERO_ERROR;
4515 ParsePosition pos(0);
4516 sdmft.adoptInsteadAndCheckErrorCode(new SimpleDateFormat(itemPtr->pattern, locale, status), status);
4517 if (U_FAILURE(status)) {
4518 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4519 continue;
4520 }
4521 sdmft->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, itemPtr->leniency, status).
4522 setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, itemPtr->leniency, status).
4523 setBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, itemPtr->leniency, status);
4524 UDate d = sdmft->parse(itemPtr->parseString, pos);
4525
4526 if(itemPtr->expectedResult.length() == 0) {
4527 if(pos.getErrorIndex() != -1) {
4528 continue;
4529 } else {
4530 errln("error: unexpected parse success - " + itemPtr->parseString +
4531 " - pattern " + itemPtr->pattern +
4532 " - error index " + pos.getErrorIndex() +
4533 " - leniency " + itemPtr->leniency);
4534 continue;
4535 }
4536 }
4537 if(pos.getErrorIndex() != -1) {
4538 errln("error: parse error for string - " + itemPtr->parseString +
4539 " - pattern " + itemPtr->pattern +
4540 " - idx " + pos.getIndex() +
4541 " - error index "+pos.getErrorIndex() +
4542 " - leniency " + itemPtr->leniency);
4543 continue;
4544 }
4545
4546 UnicodeString formatResult("");
4547 sdmft->format(d, formatResult);
4548 if(formatResult.compare(itemPtr->expectedResult) != 0) {
4549 errln("error: unexpected format result. pattern["+itemPtr->pattern+"] expected[" + itemPtr->expectedResult + "] but result was[" + formatResult + "]");
4550 continue;
4551 } else {
4552 logln("formatted results match! - " + formatResult);
4553 }
4554
4555 }
4556}
4557
4558
4559typedef struct {
4560 UBool leniency;
4561 UnicodeString parseString;
4562 UnicodeString pattern;
4563 UnicodeString expectedResult; // empty string indicates expected error
4564} TestMultiPatternMatchItem;
4565
4566void DateFormatTest::TestParseMultiPatternMatch() {
4567 // For details see http://bugs.icu-project.org/trac/ticket/10336
4568 const TestMultiPatternMatchItem items[] = {
4569 // leniency parse String pattern expected result
4570 {true, UnicodeString("2013-Sep 13"), UnicodeString("yyyy-MMM dd"), UnicodeString("2013-Sep 13")},
4571 {true, UnicodeString("2013-September 14"), UnicodeString("yyyy-MMM dd"), UnicodeString("2013-Sep 14")},
4572 {false, UnicodeString("2013-September 15"), UnicodeString("yyyy-MMM dd"), UnicodeString("")},
4573 {false, UnicodeString("2013-September 16"), UnicodeString("yyyy-MMMM dd"), UnicodeString("2013-September 16")},
4574 {true, UnicodeString("2013-Sep 17"), UnicodeString("yyyy-LLL dd"), UnicodeString("2013-Sep 17")},
4575 {true, UnicodeString("2013-September 18"), UnicodeString("yyyy-LLL dd"), UnicodeString("2013-Sep 18")},
4576 {false, UnicodeString("2013-September 19"), UnicodeString("yyyy-LLL dd"), UnicodeString("")},
4577 {false, UnicodeString("2013-September 20"), UnicodeString("yyyy-LLLL dd"), UnicodeString("2013-September 20")},
4578 {true, UnicodeString("2013 Sat Sep 21"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("2013 Sat Sep 21")},
4579 {true, UnicodeString("2013 Sunday Sep 22"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("2013 Sun Sep 22")},
4580 {false, UnicodeString("2013 Monday Sep 23"), UnicodeString("yyyy EEE MMM dd"), UnicodeString("")},
4581 {false, UnicodeString("2013 Tuesday Sep 24"), UnicodeString("yyyy EEEE MMM dd"), UnicodeString("2013 Tuesday Sep 24")},
4582 {true, UnicodeString("2013 Wed Sep 25"), UnicodeString("yyyy eee MMM dd"), UnicodeString("2013 Wed Sep 25")},
4583 {true, UnicodeString("2013 Thu Sep 26"), UnicodeString("yyyy eee MMM dd"), UnicodeString("2013 Thu Sep 26")},
4584 {false, UnicodeString("2013 Friday Sep 27"), UnicodeString("yyyy eee MMM dd"), UnicodeString("")},
4585 {false, UnicodeString("2013 Saturday Sep 28"), UnicodeString("yyyy eeee MMM dd"), UnicodeString("2013 Saturday Sep 28")},
4586 {true, UnicodeString("2013 Sun Sep 29"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("2013 Sun Sep 29")},
4587 {true, UnicodeString("2013 Monday Sep 30"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("2013 Mon Sep 30")},
4588 {false, UnicodeString("2013 Sunday Oct 13"), UnicodeString("yyyy ccc MMM dd"), UnicodeString("")},
4589 {false, UnicodeString("2013 Monday Oct 14"), UnicodeString("yyyy cccc MMM dd"), UnicodeString("2013 Monday Oct 14")},
4590 {true, UnicodeString("2013 Oct 15 Q4"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 15 Q4")},
4591 {true, UnicodeString("2013 Oct 16 4th quarter"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 16 Q4")},
4592 {false, UnicodeString("2013 Oct 17 4th quarter"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("")},
4593 {false, UnicodeString("2013 Oct 18 Q4"), UnicodeString("yyyy MMM dd QQQ"), UnicodeString("2013 Oct 18 Q4")},
4594 {true, UnicodeString("2013 Oct 19 Q4"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 19 4th quarter")},
4595 {true, UnicodeString("2013 Oct 20 4th quarter"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 20 4th quarter")},
4596 {false, UnicodeString("2013 Oct 21 Q4"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("")},
4597 {false, UnicodeString("2013 Oct 22 4th quarter"), UnicodeString("yyyy MMM dd qqqq"), UnicodeString("2013 Oct 22 4th quarter")},
4598 {false, UnicodeString("--end--"), UnicodeString(""), UnicodeString("")},
4599 };
4600
4601 UErrorCode status = U_ZERO_ERROR;
4602 LocalPointer<Calendar> cal(Calendar::createInstance(status));
4603 if (U_FAILURE(status)) {
4604 dataerrln(UnicodeString("FAIL: Unable to create Calendar for default timezone and locale."));
4605 return;
4606 }
4607 const TestMultiPatternMatchItem * itemPtr;
4608 DateFormat* sdmft = DateFormat::createDateInstance();
4609 if (sdmft == NULL) {
4610 dataerrln(UnicodeString("FAIL: Unable to create DateFormat"));
4611 return;
4612 }
4613 for (itemPtr = items; itemPtr->parseString != "--end--"; itemPtr++ ) {
4614 status = U_ZERO_ERROR;
4615 ParsePosition pos(0);
4616 ((SimpleDateFormat*) sdmft)->applyPattern(itemPtr->pattern);
4617 if (U_FAILURE(status)) {
4618 dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
4619 continue;
4620 }
4621 sdmft->setBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, itemPtr->leniency, status);
4622 UDate d = sdmft->parse(itemPtr->parseString, pos);
4623
4624 if(itemPtr->expectedResult.length() == 0) {
4625 if(pos.getErrorIndex() != -1) {
4626 continue;
4627 } else {
4628 errln("error: unexpected parse success - " + itemPtr->parseString +
4629 " - error index " + pos.getErrorIndex() +
4630 " - leniency " + itemPtr->leniency);
4631 continue;
4632 }
4633 }
4634 if(pos.getErrorIndex() != -1) {
4635 errln("error: parse error for string - " +itemPtr->parseString + " -- idx["+pos.getIndex()+"] errIdx["+pos.getErrorIndex()+"]");
4636 continue;
4637 }
4638
4639 UnicodeString formatResult("");
4640 sdmft->format(d, formatResult);
4641 if(formatResult.compare(itemPtr->expectedResult) != 0) {
4642 errln("error: unexpected format result. expected[" + itemPtr->expectedResult + "] but result was[" + formatResult + "]");
4643 } else {
4644 logln("formatted results match! - " + formatResult);
4645 }
4646 }
4647 delete sdmft;
4648}
4649
4650void DateFormatTest::TestParseLeniencyAPIs() {
4651 UErrorCode status = U_ZERO_ERROR;
4652 LocalPointer<DateFormat> dateFormat(DateFormat::createDateInstance());
4653 DateFormat *fmt = dateFormat.getAlias();
4654 if (fmt == NULL) {
4655 dataerrln("Failed calling dateFormat.getAlias()");
4656 return;
4657 }
4658
4659 assertTrue("isLenient default", fmt->isLenient());
4660 assertTrue("isCalendarLenient default", fmt->isCalendarLenient());
4661 assertTrue("ALLOW_WHITESPACE default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4662 assertTrue("ALLOW_NUMERIC default", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4663 assertTrue("PARTIAL_MATCH default", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4664 assertTrue("MULTIPLE_PATTERNS default", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4665
4666 // Set calendar to strict
4667 fmt->setCalendarLenient(FALSE);
4668
4669 assertFalse("isLeninent after setCalendarLenient(FALSE)", fmt->isLenient());
4670 assertFalse("isCalendarLenient after setCalendarLenient(FALSE)", fmt->isCalendarLenient());
4671 assertTrue("ALLOW_WHITESPACE after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4672 assertTrue("ALLOW_NUMERIC after setCalendarLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4673
4674 // Set to strict
4675 fmt->setLenient(FALSE);
4676
4677 assertFalse("isLeninent after setLenient(FALSE)", fmt->isLenient());
4678 assertFalse("isCalendarLenient after setLenient(FALSE)", fmt->isCalendarLenient());
4679 assertFalse("ALLOW_WHITESPACE after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4680 assertFalse("ALLOW_NUMERIC after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4681 // These two boolean attributes are NOT affected according to the API specification
4682 assertTrue("PARTIAL_MATCH after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_PARTIAL_LITERAL_MATCH, status));
4683 assertTrue("MULTIPLE_PATTERNS after setLenient(FALSE)", fmt->getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status));
4684
4685 // Allow white space leniency
4686 fmt->setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, TRUE, status);
4687
4688 assertFalse("isLeninent after ALLOW_WHITESPACE/TRUE", fmt->isLenient());
4689 assertFalse("isCalendarLenient after ALLOW_WHITESPACE/TRUE", fmt->isCalendarLenient());
4690 assertTrue("ALLOW_WHITESPACE after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4691 assertFalse("ALLOW_NUMERIC after ALLOW_WHITESPACE/TRUE", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4692
4693 // Set to lenient
4694 fmt->setLenient(TRUE);
4695
4696 assertTrue("isLenient after setLenient(TRUE)", fmt->isLenient());
4697 assertTrue("isCalendarLenient after setLenient(TRUE)", fmt->isCalendarLenient());
4698 assertTrue("ALLOW_WHITESPACE after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status));
4699 assertTrue("ALLOW_NUMERIC after setLenient(TRUE)", fmt->getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status));
4700}
4701
4702void DateFormatTest::TestNumberFormatOverride() {
4703 UErrorCode status = U_ZERO_ERROR;
4704 UnicodeString fields = (UnicodeString) "M";
4705
4706 LocalPointer<SimpleDateFormat> fmt;
4707 fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4708 if (!assertSuccess("SimpleDateFormat with pattern MM d", status)) {
4709 return;
4710 }
4711
4712
4713 for(int i=0; i<3; i++){
4714 NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4715 assertSuccess("NumberFormat en_US", status);
4716 fmt->adoptNumberFormat(fields, check_nf, status);
4717 assertSuccess("adoptNumberFormat check_nf", status);
4718
4719 const NumberFormat* get_nf = fmt->getNumberFormatForField((UChar)0x004D /*'M'*/);
4720 if (get_nf != check_nf) errln("FAIL: getter and setter do not work");
4721 }
4722 NumberFormat* check_nf = NumberFormat::createInstance(Locale("en_US"), status);
4723 assertSuccess("NumberFormat en_US", status);
4724 fmt->adoptNumberFormat(check_nf); // make sure using the same NF will not crash
4725
4726 const char * DATA [][2] = {
4727 { "", "\\u521D\\u516D \\u5341\\u4E94"},
4728 { "M", "\\u521D\\u516D 15"},
4729 { "Mo", "\\u521D\\u516D 15"},
4730 { "Md", "\\u521D\\u516D \\u5341\\u4E94"},
4731 { "MdMMd", "\\u521D\\u516D \\u5341\\u4E94"},
4732 { "mixed", "\\u521D\\u516D \\u5341\\u4E94"}
4733 };
4734
4735 UDate test_date = date(97, 6 - 1, 15);
4736
4737 for(int i=0; i < UPRV_LENGTHOF(DATA); i++){
4738 fields = DATA[i][0];
4739
4740 LocalPointer<SimpleDateFormat> fmt;
4741 fmt.adoptInsteadAndCheckErrorCode(new SimpleDateFormat((UnicodeString)"MM d", status), status);
4742 assertSuccess("SimpleDateFormat with pattern MM d", status);
4743 NumberFormat* overrideNF = NumberFormat::createInstance(Locale::createFromName("zh@numbers=hanidays"),status);
4744 assertSuccess("NumberFormat zh@numbers=hanidays", status);
4745 if (U_FAILURE(status)) {
4746 status = U_ZERO_ERROR;
4747 continue;
4748 }
4749
4750 if (fields == (UnicodeString) "") { // use the one w/o fields
4751 fmt->adoptNumberFormat(overrideNF);
4752 } else if (fields == (UnicodeString) "mixed") { // set 1 field at first but then full override, both(M & d) should be override
4753 NumberFormat* singleOverrideNF = NumberFormat::createInstance(Locale::createFromName("en@numbers=hebr"),status);
4754 assertSuccess("NumberFormat en@numbers=hebr", status);
4755
4756 fields = (UnicodeString) "M";
4757 fmt->adoptNumberFormat(fields, singleOverrideNF, status);
4758 assertSuccess("adoptNumberFormat singleOverrideNF", status);
4759
4760 fmt->adoptNumberFormat(overrideNF);
4761 } else if (fields == (UnicodeString) "Mo"){ // o is invlid field
4762 fmt->adoptNumberFormat(fields, overrideNF, status);
4763 if(status == U_INVALID_FORMAT_ERROR) {
4764 status = U_ZERO_ERROR;
4765 continue;
4766 }
4767 } else {
4768 fmt->adoptNumberFormat(fields, overrideNF, status);
4769 assertSuccess("adoptNumberFormat overrideNF", status);
4770 }
4771
4772 UnicodeString result;
4773 FieldPosition pos(FieldPosition::DONT_CARE);
4774 fmt->format(test_date,result, pos);
4775
4776 UnicodeString expected = ((UnicodeString)DATA[i][1]).unescape();
4777
4778 if (result != expected)
4779 errln("FAIL: Expected " + expected + " get: " + result);
4780 }
4781}
4782
4783void DateFormatTest::TestCreateInstanceForSkeleton() {
4784 UErrorCode status = U_ZERO_ERROR;
4785 LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4786 "yMMMMd", "en", status));
4787 if (!assertSuccess("Create with pattern yMMMMd", status)) {
4788 return;
4789 }
4790 UnicodeString result;
4791 FieldPosition pos(FieldPosition::DONT_CARE);
4792 fmt->format(date(98, 5-1, 25), result, pos);
4793 assertEquals("format yMMMMd", "May 25, 1998", result);
4794 fmt.adoptInstead(DateFormat::createInstanceForSkeleton(
4795 "yMd", "en", status));
4796 if (!assertSuccess("Create with pattern yMd", status)) {
4797 return;
4798 }
4799 result.remove();
4800 fmt->format(date(98, 5-1, 25), result, pos);
4801 assertEquals("format yMd", "5/25/1998", result);
4802}
4803
4804void DateFormatTest::TestCreateInstanceForSkeletonDefault() {
4805 UErrorCode status = U_ZERO_ERROR;
4806 Locale savedLocale;
4807 Locale::setDefault(Locale::getUS(), status);
4808 LocalPointer<DateFormat> fmt(DateFormat::createInstanceForSkeleton(
4809 "yMMMd", status));
4810 Locale::setDefault(savedLocale, status);
4811 if (!assertSuccess("Create with pattern yMMMd", status)) {
4812 return;
4813 }
4814 UnicodeString result;
4815 FieldPosition pos(FieldPosition::DONT_CARE);
4816 fmt->format(date(98, 5-1, 25), result, pos);
4817 assertEquals("format yMMMd", "May 25, 1998", result);
4818}
4819
4820void DateFormatTest::TestCreateInstanceForSkeletonWithCalendar() {
4821 UErrorCode status = U_ZERO_ERROR;
4822 LocalPointer<DateFormat> fmt(
4823 DateFormat::createInstanceForSkeleton(
4824 Calendar::createInstance(
4825 TimeZone::createTimeZone("GMT-3:00"),
4826 status),
4827 "yMdHm", "en", status));
4828 if (!assertSuccess("Create with pattern yMMMMd", status)) {
4829 return;
4830 }
4831 UnicodeString result;
4832 FieldPosition pos(FieldPosition::DONT_CARE);
4833
4834 LocalPointer<Calendar> cal(Calendar::createInstance(
4835 TimeZone::createTimeZone("GMT-7:00"),
4836 status));
4837 if (!assertSuccess("Creating GMT-7 time zone failed", status)) {
4838 return;
4839 }
4840 cal->clear();
4841 cal->set(1998, 5-1, 25, 0, 0, 0);
4842
4843 // date format time zone should be 4 hours ahead.
4844 fmt->format(cal->getTime(status), result, pos);
4845 assertEquals("format yMdHm", "5/25/1998, 04:00", result);
4846 assertSuccess("", status);
4847}
4848
4849void DateFormatTest::TestDFSCreateForLocaleNonGregorianLocale() {
4850 UErrorCode status = U_ZERO_ERROR;
4851 Locale fa("fa");
4852 LocalPointer<DateFormatSymbols> sym(
4853 DateFormatSymbols::createForLocale(fa, status));
4854 if (!assertSuccess("", status)) {
4855 return;
4856 }
4857
4858 // Farsi should default to the persian calendar, not gregorian
4859 int32_t count;
4860 const UnicodeString *months = sym->getShortMonths(count);
4861
4862 // First persian month.
4863 UnicodeString expected("\\u0641\\u0631\\u0648\\u0631\\u062f\\u06cc\\u0646");
4864 assertEquals("", expected.unescape(), months[0]);
4865}
4866
4867void DateFormatTest::TestDFSCreateForLocaleWithCalendarInLocale() {
4868 UErrorCode status = U_ZERO_ERROR;
4869 Locale en_heb("en@calendar=hebrew");
4870 LocalPointer<DateFormatSymbols> sym(
4871 DateFormatSymbols::createForLocale(en_heb, status));
4872 if (!assertSuccess("", status)) {
4873 return;
4874 }
4875
4876 // We should get the months of the hebrew calendar, not the gregorian
4877 // calendar.
4878 int32_t count;
4879 const UnicodeString *months = sym->getShortMonths(count);
4880
4881 // First hebrew month.
4882 UnicodeString expected("Tishri");
4883 assertEquals("", expected, months[0]);
4884}
4885
4886void DateFormatTest::TestChangeCalendar() {
4887 UErrorCode status = U_ZERO_ERROR;
4888 Locale en("en");
4889 Locale en_heb("en@calendar=hebrew");
4890 LocalPointer<DateFormat> fmt(
4891 DateFormat::createInstanceForSkeleton("yMMMd", en, status));
4892 if (!assertSuccess("", status)) {
4893 return;
4894 }
4895 fmt->adoptCalendar(Calendar::createInstance(en_heb, status));
4896 if (!assertSuccess("", status)) {
4897 return;
4898 }
4899 UnicodeString result;
4900 FieldPosition pos(FieldPosition::DONT_CARE);
4901 fmt->format(date(98, 5-1, 25), result, pos);
4902 assertEquals("format yMMMd", "Iyar 29, 5758", result);
4903}
4904
4905void DateFormatTest::TestPatternFromSkeleton() {
4906 static const struct {
4907 const Locale& locale;
4908 const char* const skeleton;
4909 const char* const pattern;
4910 } TESTDATA[] = {
4911 // Ticket #11985
4912 {Locale::getEnglish(), "jjmm", "h:mm a"},
4913 {Locale::getEnglish(), "JJmm", "hh:mm"},
4914 {Locale::getGerman(), "jjmm", "HH:mm"},
4915 {Locale::getGerman(), "JJmm", "HH:mm"}
4916 };
4917
4918 for (size_t i = 0; i < UPRV_LENGTHOF(TESTDATA); i++) {
4919 UErrorCode status = U_ZERO_ERROR;
4920 LocalPointer<DateFormat> fmt(
4921 DateFormat::createInstanceForSkeleton(
4922 TESTDATA[i].skeleton, TESTDATA[i].locale, status));
4923 if (!assertSuccess("createInstanceForSkeleton", status)) {
4924 return;
4925 }
4926 UnicodeString pattern;
4927 static_cast<const SimpleDateFormat*>(fmt.getAlias())->toPattern(pattern);
4928 assertEquals("Format pattern", TESTDATA[i].pattern, pattern);
4929 }
4930}
4931
4932void DateFormatTest::TestAmPmMidnightNoon() {
4933 // Some times on 2015-11-13 (UTC+0).
4934 UDate k000000 = 1447372800000.0;
4935 UDate k000030 = 1447372830000.0;
4936 UDate k003000 = 1447374600000.0;
4937 UDate k060000 = 1447394400000.0;
4938 UDate k120000 = 1447416000000.0;
4939 UDate k180000 = 1447437600000.0;
4940
4941 UErrorCode errorCode = U_ZERO_ERROR;
4942 SimpleDateFormat sdf(UnicodeString(), errorCode);
4943 if (U_FAILURE(errorCode)) {
4944 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
4945 return;
4946 }
4947 const TimeZone *tz = TimeZone::getGMT();
4948 sdf.setTimeZone(*tz);
4949 UnicodeString out;
4950
4951 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
4952 // For ICU 57 output of "midnight" is temporarily suppressed.
4953
4954 // Short.
4955 sdf.applyPattern(UnicodeString("hh:mm:ss bbb"));
4956
4957 // assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4958 assertEquals("hh:mm:ss bbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4959 assertEquals("hh:mm:ss bbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
4960 assertEquals("hh:mm:ss bbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
4961 assertEquals("hh:mm:ss bbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
4962 assertEquals("hh:mm:ss bbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
4963 assertEquals("hh:mm:ss bbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
4964
4965 sdf.applyPattern(UnicodeString("hh:mm bbb"));
4966
4967 // assertEquals("hh:mm bbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
4968 assertEquals("hh:mm bbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
4969 // assertEquals("hh:mm bbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
4970 assertEquals("hh:mm bbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
4971 assertEquals("hh:mm bbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
4972
4973 sdf.applyPattern(UnicodeString("hh bbb"));
4974
4975 // assertEquals("hh bbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
4976 assertEquals("hh bbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
4977 // assertEquals("hh bbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
4978 assertEquals("hh bbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
4979 // assertEquals("hh bbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
4980 assertEquals("hh bbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
4981
4982 // Wide.
4983 sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
4984
4985 // assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
4986 assertEquals("hh:mm:ss bbbb | 00:00:00", "12:00:00 AM", sdf.format(k000000, out.remove()));
4987 assertEquals("hh:mm:ss bbbb | 00:00:30", "12:00:30 AM", sdf.format(k000030, out.remove()));
4988 assertEquals("hh:mm:ss bbbb | 00:30:00", "12:30:00 AM", sdf.format(k003000, out.remove()));
4989 assertEquals("hh:mm:ss bbbb | 06:00:00", "06:00:00 AM", sdf.format(k060000, out.remove()));
4990 assertEquals("hh:mm:ss bbbb | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
4991 assertEquals("hh:mm:ss bbbb | 18:00:00", "06:00:00 PM", sdf.format(k180000, out.remove()));
4992
4993 sdf.applyPattern(UnicodeString("hh:mm bbbb"));
4994
4995 // assertEquals("hh:mm bbbb | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
4996 assertEquals("hh:mm bbbb | 00:00:00", "12:00 AM", sdf.format(k000000, out.remove()));
4997 // assertEquals("hh:mm bbbb | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
4998 assertEquals("hh:mm bbbb | 00:00:30", "12:00 AM", sdf.format(k000030, out.remove()));
4999 assertEquals("hh:mm bbbb | 00:30:00", "12:30 AM", sdf.format(k003000, out.remove()));
5000
5001 sdf.applyPattern(UnicodeString("hh bbbb"));
5002
5003 // assertEquals("hh bbbb | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5004 assertEquals("hh bbbb | 00:00:00", "12 AM", sdf.format(k000000, out.remove()));
5005 // assertEquals("hh bbbb | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5006 assertEquals("hh bbbb | 00:00:30", "12 AM", sdf.format(k000030, out.remove()));
5007 // assertEquals("hh bbbb | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5008 assertEquals("hh bbbb | 00:30:00", "12 AM", sdf.format(k003000, out.remove()));
5009
5010 // Narrow.
5011 sdf.applyPattern(UnicodeString("hh:mm:ss bbbbb"));
5012
5013 // assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5014 assertEquals("hh:mm:ss bbbbb | 00:00:00", "12:00:00 a", sdf.format(k000000, out.remove()));
5015 assertEquals("hh:mm:ss bbbbb | 00:00:30", "12:00:30 a", sdf.format(k000030, out.remove()));
5016 assertEquals("hh:mm:ss bbbbb | 00:30:00", "12:30:00 a", sdf.format(k003000, out.remove()));
5017 assertEquals("hh:mm:ss bbbbb | 06:00:00", "06:00:00 a", sdf.format(k060000, out.remove()));
5018 assertEquals("hh:mm:ss bbbbb | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5019 assertEquals("hh:mm:ss bbbbb | 18:00:00", "06:00:00 p", sdf.format(k180000, out.remove()));
5020
5021 sdf.applyPattern(UnicodeString("hh:mm bbbbb"));
5022
5023 // assertEquals("hh:mm bbbbb | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5024 assertEquals("hh:mm bbbbb | 00:00:00", "12:00 a", sdf.format(k000000, out.remove()));
5025 // assertEquals("hh:mm bbbbb | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5026 assertEquals("hh:mm bbbbb | 00:00:30", "12:00 a", sdf.format(k000030, out.remove()));
5027 assertEquals("hh:mm bbbbb | 00:30:00", "12:30 a", sdf.format(k003000, out.remove()));
5028
5029 sdf.applyPattern(UnicodeString("hh bbbbb"));
5030
5031 // assertEquals("hh bbbbb | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5032 assertEquals("hh bbbbb | 00:00:00", "12 a", sdf.format(k000000, out.remove()));
5033 // assertEquals("hh bbbbb | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5034 assertEquals("hh bbbbb | 00:00:30", "12 a", sdf.format(k000030, out.remove()));
5035 // assertEquals("hh bbbbb | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5036 assertEquals("hh bbbbb | 00:30:00", "12 a", sdf.format(k003000, out.remove()));
5037}
5038
5039void DateFormatTest::TestFlexibleDayPeriod() {
5040 // Some times on 2015-11-13 (UTC+0).
5041 UDate k000000 = 1447372800000.0;
5042 UDate k000030 = 1447372830000.0;
5043 UDate k003000 = 1447374600000.0;
5044 UDate k060000 = 1447394400000.0;
5045 UDate k120000 = 1447416000000.0;
5046 UDate k180000 = 1447437600000.0;
5047
5048 UErrorCode errorCode = U_ZERO_ERROR;
5049 SimpleDateFormat sdf(UnicodeString(), errorCode);
5050 if (U_FAILURE(errorCode)) {
5051 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5052 return;
5053 }
5054 const TimeZone *tz = TimeZone::getGMT();
5055 sdf.setTimeZone(*tz);
5056 UnicodeString out;
5057
5058 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5059 // For ICU 57 output of "midnight" is temporarily suppressed.
5060
5061 // Short.
5062 sdf.applyPattern(UnicodeString("hh:mm:ss BBB"));
5063
5064 // assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5065 assertEquals("hh:mm:ss BBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5066 assertEquals("hh:mm:ss BBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5067 assertEquals("hh:mm:ss BBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5068 assertEquals("hh:mm:ss BBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5069 assertEquals("hh:mm:ss BBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5070 assertEquals("hh:mm:ss BBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5071
5072 sdf.applyPattern(UnicodeString("hh:mm BBB"));
5073
5074 // assertEquals("hh:mm BBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5075 assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5076 // assertEquals("hh:mm BBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5077 assertEquals("hh:mm BBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5078 assertEquals("hh:mm BBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5079
5080 sdf.applyPattern(UnicodeString("hh BBB"));
5081
5082 // assertEquals("hh BBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5083 assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5084 // assertEquals("hh BBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5085 assertEquals("hh BBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5086 // assertEquals("hh BBB | 00:30:00", "12 midnight", sdf.format(k003000, out.remove()));
5087 assertEquals("hh BBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5088
5089 // Wide.
5090 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5091
5092 // assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 midnight", sdf.format(k000000, out.remove()));
5093 assertEquals("hh:mm:ss BBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5094 assertEquals("hh:mm:ss BBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5095 assertEquals("hh:mm:ss BBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5096 assertEquals("hh:mm:ss BBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5097 assertEquals("hh:mm:ss BBBB | 12:00:00", "12:00:00 noon", sdf.format(k120000, out.remove()));
5098 assertEquals("hh:mm:ss BBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5099
5100 sdf.applyPattern(UnicodeString("hh:mm BBBB"));
5101
5102 // assertEquals("hh:mm BBBB | 00:00:00", "12:00 midnight", sdf.format(k000000, out.remove()));
5103 assertEquals("hh:mm BBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5104 // assertEquals("hh:mm BBBB | 00:00:30", "12:00 midnight", sdf.format(k000030, out.remove()));
5105 assertEquals("hh:mm BBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5106 assertEquals("hh:mm BBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5107
5108 sdf.applyPattern(UnicodeString("hh BBBB"));
5109
5110 // assertEquals("hh BBBB | 00:00:00", "12 midnight", sdf.format(k000000, out.remove()));
5111 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5112 // assertEquals("hh BBBB | 00:00:30", "12 midnight", sdf.format(k000030, out.remove()));
5113 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5114 // assertEquals("hh BBBB | 00:80:00", "12 midnight", sdf.format(k003000, out.remove()));
5115 assertEquals("hh BBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5116
5117 // Narrow.
5118 sdf.applyPattern(UnicodeString("hh:mm:ss BBBBB"));
5119
5120 // assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 mi", sdf.format(k000000, out.remove()));
5121 assertEquals("hh:mm:ss BBBBB | 00:00:00", "12:00:00 at night", sdf.format(k000000, out.remove()));
5122 assertEquals("hh:mm:ss BBBBB | 00:00:30", "12:00:30 at night", sdf.format(k000030, out.remove()));
5123 assertEquals("hh:mm:ss BBBBB | 00:30:00", "12:30:00 at night", sdf.format(k003000, out.remove()));
5124 assertEquals("hh:mm:ss BBBBB | 06:00:00", "06:00:00 in the morning", sdf.format(k060000, out.remove()));
5125 assertEquals("hh:mm:ss BBBBB | 12:00:00", "12:00:00 n", sdf.format(k120000, out.remove()));
5126 assertEquals("hh:mm:ss BBBBB | 18:00:00", "06:00:00 in the evening", sdf.format(k180000, out.remove()));
5127
5128 sdf.applyPattern(UnicodeString("hh:mm BBBBB"));
5129
5130 // assertEquals("hh:mm BBBBB | 00:00:00", "12:00 mi", sdf.format(k000000, out.remove()));
5131 assertEquals("hh:mm BBBBB | 00:00:00", "12:00 at night", sdf.format(k000000, out.remove()));
5132 // assertEquals("hh:mm BBBBB | 00:00:30", "12:00 mi", sdf.format(k000030, out.remove()));
5133 assertEquals("hh:mm BBBBB | 00:00:30", "12:00 at night", sdf.format(k000030, out.remove()));
5134 assertEquals("hh:mm BBBBB | 00:30:00", "12:30 at night", sdf.format(k003000, out.remove()));
5135
5136 sdf.applyPattern(UnicodeString("hh BBBBB"));
5137
5138 // assertEquals("hh BBBBB | 00:00:00", "12 mi", sdf.format(k000000, out.remove()));
5139 assertEquals("hh BBBBB | 00:00:00", "12 at night", sdf.format(k000000, out.remove()));
5140 // assertEquals("hh BBBBB | 00:00:30", "12 mi", sdf.format(k000030, out.remove()));
5141 assertEquals("hh BBBBB | 00:00:30", "12 at night", sdf.format(k000030, out.remove()));
5142 // assertEquals("hh BBBBB | 00:30:00", "12 mi", sdf.format(k003000, out.remove()));
5143 assertEquals("hh BBBBB | 00:30:00", "12 at night", sdf.format(k003000, out.remove()));
5144}
5145
5146void DateFormatTest::TestDayPeriodWithLocales() {
5147 // Some times on 2015-11-13 (UTC+0).
5148 UDate k000000 = 1447372800000.0;
5149 UDate k010000 = 1447376400000.0;
5150 UDate k120000 = 1447416000000.0;
5151 UDate k220000 = 1447452000000.0;
5152
5153 UErrorCode errorCode = U_ZERO_ERROR;
5154 const TimeZone *tz = TimeZone::getGMT();
5155 UnicodeString out;
5156
5157 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5158 // For ICU 57 output of "midnight" and its localized equivalentns is temporarily suppressed.
5159
5160 // Locale de has a word for midnight, but not noon.
5161 SimpleDateFormat sdf(UnicodeString(), Locale::getGermany(), errorCode);
5162 if (U_FAILURE(errorCode)) {
5163 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5164 return;
5165 }
5166 sdf.setTimeZone(*tz);
5167
5168 sdf.applyPattern(UnicodeString("hh:mm:ss bbbb"));
5169
5170 // assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 Mitternacht",
5171 // sdf.format(k000000, out.remove()));
5172 assertEquals("hh:mm:ss bbbb | 00:00:00 | de", "12:00:00 AM",
5173 sdf.format(k000000, out.remove()));
5174 assertEquals("hh:mm:ss bbbb | 12:00:00 | de", "12:00:00 PM",
5175 sdf.format(k120000, out.remove()));
5176
5177 // Locale ee has a rule that wraps around midnight (21h - 4h).
5178 sdf = SimpleDateFormat(UnicodeString(), Locale("ee"), errorCode);
5179 sdf.setTimeZone(*tz);
5180
5181 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5182
5183 assertEquals("hh:mm:ss BBBB | 22:00:00 | ee", UnicodeString("10:00:00 z\\u00E3").unescape(),
5184 sdf.format(k220000, out.remove()));
5185 assertEquals("hh:mm:ss BBBB | 00:00:00 | ee", UnicodeString("12:00:00 z\\u00E3").unescape(),
5186 sdf.format(k000000, out.remove()));
5187 assertEquals("hh:mm:ss BBBB | 01:00:00 | ee", UnicodeString("01:00:00 z\\u00E3").unescape(),
5188 sdf.format(k010000, out.remove()));
5189
5190 // Locale root has rules for AM/PM only.
5191 sdf = SimpleDateFormat(UnicodeString(), Locale("root"), errorCode);
5192 sdf.setTimeZone(*tz);
5193
5194 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5195
5196 assertEquals("hh:mm:ss BBBB | 00:00:00 | root", "12:00:00 AM",
5197 sdf.format(k000000, out.remove()));
5198 assertEquals("hh:mm:ss BBBB | 12:00:00 | root", "12:00:00 PM",
5199 sdf.format(k120000, out.remove()));
5200
5201 // Empty string should behave exactly as root.
5202 sdf = SimpleDateFormat(UnicodeString(), Locale(""), errorCode);
5203 sdf.setTimeZone(*tz);
5204
5205 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5206
5207 assertEquals("hh:mm:ss BBBB | 00:00:00 | \"\" (root)", "12:00:00 AM",
5208 sdf.format(k000000, out.remove()));
5209 assertEquals("hh:mm:ss BBBB | 12:00:00 | \"\" (root)", "12:00:00 PM",
5210 sdf.format(k120000, out.remove()));
5211
5212 // Locale en_US should fall back to en.
5213 sdf = SimpleDateFormat(UnicodeString(), Locale("en_US"), errorCode);
5214 sdf.setTimeZone(*tz);
5215
5216 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5217
5218 // assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 midnight",
5219 // sdf.format(k000000, out.remove()));
5220 assertEquals("hh:mm:ss BBBB | 00:00:00 | en_US", "12:00:00 at night",
5221 sdf.format(k000000, out.remove()));
5222 assertEquals("hh:mm:ss BBBB | 01:00:00 | en_US", "01:00:00 at night",
5223 sdf.format(k010000, out.remove()));
5224 assertEquals("hh:mm:ss BBBB | 12:00:00 | en_US", "12:00:00 noon",
5225 sdf.format(k120000, out.remove()));
5226
5227 // Locale es_CO should not fall back to es and should have a
5228 // different string for 1 in the morning.
5229 // (es_CO: "de la manana" (first n has a tilde) vs. es: "de la madrugada")
5230 sdf = SimpleDateFormat(UnicodeString(), Locale("es_CO"), errorCode);
5231 sdf.setTimeZone(*tz);
5232
5233 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5234 assertEquals("hh:mm:ss BBBB | 01:00:00 | es_CO", u"01:00:00 de la mañana",
5235 sdf.format(k010000, out.remove()));
5236
5237 sdf = SimpleDateFormat(UnicodeString(), Locale("es"), errorCode);
5238 sdf.setTimeZone(*tz);
5239
5240 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5241 assertEquals("hh:mm:ss BBBB | 01:00:00 | es", "01:00:00 de la madrugada",
5242 sdf.format(k010000, out.remove()));
5243
5244 // #13215: for locales with keywords, check hang in DayPeriodRules""getInstance(const Locale, ...),
5245 // which is called in SimpleDateFormat::format for patterns that include 'B'.
5246 sdf = SimpleDateFormat(UnicodeString(), Locale("en@calendar=buddhist"), errorCode);
5247 sdf.setTimeZone(*tz);
5248
5249 sdf.applyPattern(UnicodeString("hh:mm:ss BBBB"));
5250 assertEquals("hh:mm:ss BBBB | 01:00:00 | en@calendar=buddhist", "01:00:00 at night",
5251 sdf.format(k010000, out.remove()));
5252}
5253
5254void DateFormatTest::TestMinuteSecondFieldsInOddPlaces() {
5255 // Some times on 2015-11-13 (UTC+0).
5256 UDate k000000 = 1447372800000.0;
5257 UDate k000030 = 1447372830000.0;
5258 UDate k003000 = 1447374600000.0;
5259 UDate k060030 = 1447394430000.0;
5260 UDate k063000 = 1447396200000.0;
5261
5262 UErrorCode errorCode = U_ZERO_ERROR;
5263 const TimeZone *tz = TimeZone::getGMT();
5264 UnicodeString out;
5265
5266 // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
5267 // For ICU 57 output of "midnight" is temporarily suppressed.
5268
5269 // Seconds field is not present.
5270
5271 // Apply pattern through constructor to make sure parsePattern() is called during initialization.
5272 SimpleDateFormat sdf(UnicodeString("hh:mm 'ss' bbbb"), errorCode);
5273 if (U_FAILURE(errorCode)) {
5274 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5275 return;
5276 }
5277 sdf.setTimeZone(*tz);
5278
5279 // assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss midnight",
5280 // sdf.format(k000030, out.remove()));
5281 assertEquals("hh:mm 'ss' bbbb | 00:00:30", "12:00 ss AM",
5282 sdf.format(k000030, out.remove()));
5283 assertEquals("hh:mm 'ss' bbbb | 06:00:30", "06:00 ss AM",
5284 sdf.format(k060030, out.remove()));
5285
5286 sdf.applyPattern(UnicodeString("hh:mm 'ss' BBBB"));
5287
5288 // assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss midnight",
5289 // sdf.format(k000030, out.remove()));
5290 assertEquals("hh:mm 'ss' BBBB | 00:00:30", "12:00 ss at night",
5291 sdf.format(k000030, out.remove()));
5292 assertEquals("hh:mm 'ss' BBBB | 06:00:30", "06:00 ss in the morning",
5293 sdf.format(k060030, out.remove()));
5294
5295 // Minutes field is not present.
5296 sdf.applyPattern(UnicodeString("hh 'mm ss' bbbb"));
5297
5298 // assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss midnight",
5299 // sdf.format(k003000, out.remove()));
5300 assertEquals("hh 'mm ss' bbbb | 00:30:00", "12 mm ss AM",
5301 sdf.format(k003000, out.remove()));
5302 assertEquals("hh 'mm ss' bbbb | 06:30:00", "06 mm ss AM",
5303 sdf.format(k063000, out.remove()));
5304
5305 sdf.applyPattern(UnicodeString("hh 'mm ss' BBBB"));
5306
5307 // assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss midnight",
5308 // sdf.format(k003000, out.remove()));
5309 assertEquals("hh 'mm ss' BBBB | 00:30:00", "12 mm ss at night",
5310 sdf.format(k003000, out.remove()));
5311 assertEquals("hh 'mm ss' BBBB | 06:30:00", "06 mm ss in the morning",
5312 sdf.format(k063000, out.remove()));
5313
5314 // Minutes and seconds fields appear after day periods.
5315 sdf.applyPattern(UnicodeString("bbbb hh:mm:ss"));
5316
5317 // assertEquals("bbbb hh:mm:ss | 00:00:00", "midnight 12:00:00",
5318 // sdf.format(k000000, out.remove()));
5319 assertEquals("bbbb hh:mm:ss | 00:00:00", "AM 12:00:00",
5320 sdf.format(k000000, out.remove()));
5321 assertEquals("bbbb hh:mm:ss | 00:00:30", "AM 12:00:30",
5322 sdf.format(k000030, out.remove()));
5323 assertEquals("bbbb hh:mm:ss | 00:30:00", "AM 12:30:00",
5324 sdf.format(k003000, out.remove()));
5325
5326 sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5327
5328 // assertEquals("BBBB hh:mm:ss | 00:00:00", "midnight 12:00:00",
5329 // sdf.format(k000000, out.remove()));
5330 assertEquals("BBBB hh:mm:ss | 00:00:00", "at night 12:00:00",
5331 sdf.format(k000000, out.remove()));
5332 assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5333 sdf.format(k000030, out.remove()));
5334 assertEquals("BBBB hh:mm:ss | 00:30:00", "at night 12:30:00",
5335 sdf.format(k003000, out.remove()));
5336
5337 // Confirm applyPattern() reparses the pattern string.
5338 sdf.applyPattern(UnicodeString("BBBB hh"));
5339 // assertEquals("BBBB hh | 00:00:30", "midnight 12",
5340 // sdf.format(k000030, out.remove()));
5341 assertEquals("BBBB hh | 00:00:30", "at night 12",
5342 sdf.format(k000030, out.remove()));
5343
5344 sdf.applyPattern(UnicodeString("BBBB hh:mm:'ss'"));
5345 // assertEquals("BBBB hh:mm:'ss' | 00:00:30", "midnight 12:00:ss",
5346 // sdf.format(k000030, out.remove()));
5347 assertEquals("BBBB hh | 00:00:30", "at night 12:00:ss",
5348 sdf.format(k000030, out.remove()));
5349
5350 sdf.applyPattern(UnicodeString("BBBB hh:mm:ss"));
5351 assertEquals("BBBB hh:mm:ss | 00:00:30", "at night 12:00:30",
5352 sdf.format(k000030, out.remove()));
5353}
5354
5355void DateFormatTest::TestDayPeriodParsing() {
5356 // Some times on 2015-11-13 (UTC+0).
5357 UDate k000000 = 1447372800000.0;
5358 UDate k003700 = 1447375020000.0;
5359 UDate k010000 = 1447376400000.0;
5360 UDate k013000 = 1447378200000.0;
5361 UDate k030000 = 1447383600000.0;
5362 UDate k090000 = 1447405200000.0;
5363 UDate k120000 = 1447416000000.0;
5364 UDate k130000 = 1447419600000.0;
5365 UDate k133700 = 1447421820000.0;
5366 UDate k150000 = 1447426800000.0;
5367 UDate k190000 = 1447441200000.0;
5368 UDate k193000 = 1447443000000.0;
5369 UDate k200000 = 1447444800000.0;
5370 UDate k210000 = 1447448400000.0;
5371
5372 UErrorCode errorCode = U_ZERO_ERROR;
5373 SimpleDateFormat sdf(UnicodeString(), errorCode);
5374 if (U_FAILURE(errorCode)) {
5375 dataerrln("Error creating SimpleDateFormat - %s", u_errorName(errorCode));
5376 return;
5377 }
5378 const TimeZone *tz = TimeZone::getGMT();
5379 sdf.setTimeZone(*tz);
5380 UnicodeString out;
5381
5382 // 'B' -- flexible day periods
5383 // A day period on its own parses to the center of that period.
5384 sdf.applyPattern(UnicodeString("yyyy-MM-dd B"));
5385 assertEquals("yyyy-MM-dd B | 2015-11-13 midnight",
5386 k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5387 assertEquals("yyyy-MM-dd B | 2015-11-13 noon",
5388 k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5389 assertEquals("yyyy-MM-dd B | 2015-11-13 in the afternoon",
5390 k150000, sdf.parse(UnicodeString("2015-11-13 in the afternoon"), errorCode));
5391 assertEquals("yyyy-MM-dd B | 2015-11-13 in the evening",
5392 k193000, sdf.parse(UnicodeString("2015-11-13 in the evening"), errorCode));
5393 assertEquals("yyyy-MM-dd B | 2015-11-13 at night",
5394 k013000, sdf.parse(UnicodeString("2015-11-13 at night"), errorCode));
5395
5396 // If time and day period are consistent with each other then time is parsed accordingly.
5397 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5398 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 midnight",
5399 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5400 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 12:00 noon",
5401 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5402 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 at night",
5403 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5404 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 01:00 in the afternoon",
5405 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5406 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 in the morning",
5407 k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5408 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 09:00 at night",
5409 k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5410
5411 // If the hour is 13 thru 23 then day period has no effect on time (since time is assumed
5412 // to be in 24-hour format).
5413 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5414 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 midnight",
5415 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5416 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 noon",
5417 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5418 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5419 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5420 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the afternoon",
5421 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the afternoon"), errorCode));
5422 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 in the morning",
5423 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 in the morning"), errorCode));
5424 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 13:37 at night",
5425 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 at night"), errorCode));
5426
5427 // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5428 // This unfortunately means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5429 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5430 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 midnight",
5431 k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5432 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 00:00 noon",
5433 k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5434
5435 // But when parsed with 'H', 0 indicates a 24-hour time, therefore we disregard the day period.
5436 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5437 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 midnight",
5438 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5439 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 noon",
5440 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5441 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5442 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5443 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the afternoon",
5444 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the afternoon"), errorCode));
5445 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 in the morning",
5446 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 in the morning"), errorCode));
5447 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 00:37 at night",
5448 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 at night"), errorCode));
5449
5450 // Even when parsed with 'H', hours 1 thru 12 are considered 12-hour time and takes
5451 // day period into account in parsing.
5452 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm B"));
5453 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 midnight",
5454 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5455 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 12:00 noon",
5456 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5457 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 at night",
5458 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 at night"), errorCode));
5459 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 01:00 in the afternoon",
5460 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 in the afternoon"), errorCode));
5461 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 in the morning",
5462 k090000, sdf.parse(UnicodeString("2015-11-13 09:00 in the morning"), errorCode));
5463 assertEquals("yyyy-MM-dd HH:mm B | 2015-11-13 09:00 at night",
5464 k210000, sdf.parse(UnicodeString("2015-11-13 09:00 at night"), errorCode));
5465
5466 // If a 12-hour time and the day period don't agree with each other, time is parsed as close
5467 // to the given day period as possible.
5468 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm B"));
5469
5470 // AFTERNOON1 is [12, 18), but "7 in the afternoon" parses to 19:00.
5471 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 07:00 in the afternoon",
5472 k190000, sdf.parse(UnicodeString("2015-11-13 07:00 in the afternoon"), errorCode));
5473 // NIGHT1 is [21, 6), but "8 at night" parses to 20:00.
5474 assertEquals("yyyy-MM-dd hh:mm B | 2015-11-13 08:00 at night",
5475 k200000, sdf.parse(UnicodeString("2015-11-13 08:00 at night"), errorCode));
5476
5477 // 'b' -- fixed day periods (AM, PM, midnight, noon)
5478 // On their own, "midnight" parses to 00:00 and "noon" parses to 12:00.
5479 // AM and PM are handled by the 'a' parser (which doesn't handle this case well).
5480 sdf.applyPattern(UnicodeString("yyyy-MM-dd b"));
5481 assertEquals("yyyy-MM-dd b | 2015-11-13 midnight",
5482 k000000, sdf.parse(UnicodeString("2015-11-13 midnight"), errorCode));
5483 assertEquals("yyyy-MM-dd b | 2015-11-13 noon",
5484 k120000, sdf.parse(UnicodeString("2015-11-13 noon"), errorCode));
5485
5486 // For 12-hour times, AM and PM should be parsed as if with pattern character 'a'.
5487 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5488 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 AM",
5489 k010000, sdf.parse(UnicodeString("2015-11-13 01:00 AM"), errorCode));
5490 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 01:00 PM",
5491 k130000, sdf.parse(UnicodeString("2015-11-13 01:00 PM"), errorCode));
5492
5493 // 12 midnight parses to 00:00, and 12 noon parses to 12:00.
5494 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 midnight",
5495 k000000, sdf.parse(UnicodeString("2015-11-13 12:00 midnight"), errorCode));
5496 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 12:00 noon",
5497 k120000, sdf.parse(UnicodeString("2015-11-13 12:00 noon"), errorCode));
5498
5499 // Hours 13-23 indicate 24-hour time so we disregard "midnight" or "noon".
5500 // Again, AM and PM are handled by the 'a' parser which doesn't handle this case well.
5501 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5502 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 midnight",
5503 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 midnight"), errorCode));
5504 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 13:37 noon",
5505 k133700, sdf.parse(UnicodeString("2015-11-13 13:37 noon"), errorCode));
5506
5507 // Hour 0 is synonymous with hour 12 when parsed with 'h'.
5508 // Again, this means we have to tolerate "0 noon" as it's synonymous with "12 noon".
5509 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5510 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 midnight",
5511 k000000, sdf.parse(UnicodeString("2015-11-13 00:00 midnight"), errorCode));
5512 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 00:00 noon",
5513 k120000, sdf.parse(UnicodeString("2015-11-13 00:00 noon"), errorCode));
5514
5515 // With 'H' though 0 indicates a 24-hour time, therefore we disregard the day period.
5516 sdf.applyPattern(UnicodeString("yyyy-MM-dd HH:mm b"));
5517 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 midnight",
5518 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 midnight"), errorCode));
5519 assertEquals("yyyy-MM-dd HH:mm b | 2015-11-13 00:37 noon",
5520 k003700, sdf.parse(UnicodeString("2015-11-13 00:37 noon"), errorCode));
5521
5522 // If "midnight" or "noon" is parsed with a 12-hour time other than 12:00, choose
5523 // the version that's closer to the period given.
5524 sdf.applyPattern(UnicodeString("yyyy-MM-dd hh:mm b"));
5525 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 midnight",
5526 k030000, sdf.parse(UnicodeString("2015-11-13 03:00 midnight"), errorCode));
5527 assertEquals("yyyy-MM-dd hh:mm b | 2015-11-13 03:00 noon",
5528 k150000, sdf.parse(UnicodeString("2015-11-13 03:00 noon"), errorCode));
5529}
5530
5531void DateFormatTest::TestParseRegression13744() {
5532 LocalPointer<DateFormat> dfmt(DateFormat::createDateTimeInstance(
5533 DateFormat::SHORT, DateFormat::SHORT, Locale("en", "US")));
5534 if (dfmt.isNull()) {
5535 dataerrln("DateFormat::createDateTimeInstance() failed");
5536 return;
5537 }
5538 ParsePosition pos(0);
5539 UnicodeString inDate("4/27/18");
5540 dfmt->parse(inDate, pos);
5541 assertEquals("Error index", inDate.length(), pos.getErrorIndex());
5542}
5543
5544void DateFormatTest::TestAdoptCalendarLeak() {
5545 UErrorCode status = U_ZERO_ERROR;
5546 // This test relies on the locale fullName exceeding ULOC_FULLNAME_CAPACITY
5547 // in order for setKeywordValue to fail.
5548 SimpleDateFormat sdf(
5549 "d.M.y",
5550 Locale("de__POSIX@colstrength=primary;currency=eur;em=default;"
5551 "hours=h23;lb=strict;lw=normal;measure=metric;numbers=latn;"
5552 "rg=atzzzz;sd=atat1;ss=none;timezone=Europe/Vienna"),
5553 status);
5554 ASSERT_OK(status);
5555 sdf.adoptCalendar(Calendar::createInstance(status));
5556}
5557
5558#endif /* #if !UCONFIG_NO_FORMATTING */
5559
5560//eof