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