]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /******************************************************************** |
2 | * COPYRIGHT: | |
374ca955 | 3 | * Copyright (c) 1997-2004, International Business Machines Corporation and |
b75a7d8f A |
4 | * 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/timezone.h" | |
13 | #include "unicode/gregocal.h" | |
14 | #include "unicode/smpdtfmt.h" | |
15 | #include "unicode/datefmt.h" | |
16 | #include "unicode/simpletz.h" | |
17 | #include "unicode/strenum.h" | |
374ca955 | 18 | #include "unicode/dtfmtsym.h" |
b75a7d8f | 19 | #include "cmemory.h" |
374ca955 A |
20 | #include "cstring.h" |
21 | #include "caltest.h" // for fieldName | |
b75a7d8f A |
22 | // ***************************************************************************** |
23 | // class DateFormatTest | |
24 | // ***************************************************************************** | |
25 | ||
26 | void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) | |
27 | { | |
28 | // if (exec) logln((UnicodeString)"TestSuite DateFormatTest"); | |
29 | switch (index) { | |
30 | TESTCASE(0,TestEquals); | |
31 | TESTCASE(1,TestTwoDigitYearDSTParse); | |
32 | TESTCASE(2,TestFieldPosition); | |
33 | TESTCASE(3,TestPartialParse994); | |
34 | TESTCASE(4,TestRunTogetherPattern985); | |
35 | TESTCASE(5,TestRunTogetherPattern917); | |
36 | TESTCASE(6,TestCzechMonths459); | |
37 | TESTCASE(7,TestLetterDPattern212); | |
38 | TESTCASE(8,TestDayOfYearPattern195); | |
39 | TESTCASE(9,TestQuotePattern161); | |
40 | TESTCASE(10,TestBadInput135); | |
41 | TESTCASE(11,TestBadInput135a); | |
42 | TESTCASE(12,TestTwoDigitYear); | |
43 | TESTCASE(13,TestDateFormatZone061); | |
44 | TESTCASE(14,TestDateFormatZone146); | |
45 | TESTCASE(15,TestLocaleDateFormat); | |
46 | TESTCASE(16,TestWallyWedel); | |
47 | TESTCASE(17,TestDateFormatCalendar); | |
48 | TESTCASE(18,TestSpaceParsing); | |
49 | TESTCASE(19,TestExactCountFormat); | |
50 | TESTCASE(20,TestWhiteSpaceParsing); | |
374ca955 A |
51 | TESTCASE(21,TestInvalidPattern); |
52 | TESTCASE(22,TestGeneral); | |
53 | TESTCASE(23,TestGreekMay); | |
b75a7d8f A |
54 | default: name = ""; break; |
55 | } | |
56 | } | |
57 | ||
58 | // Test written by Wally Wedel and emailed to me. | |
59 | void DateFormatTest::TestWallyWedel() | |
60 | { | |
61 | UErrorCode status = U_ZERO_ERROR; | |
62 | /* | |
63 | * Instantiate a TimeZone so we can get the ids. | |
64 | */ | |
65 | TimeZone *tz = new SimpleTimeZone(7,""); | |
66 | /* | |
67 | * Computational variables. | |
68 | */ | |
69 | int32_t offset, hours, minutes; | |
70 | /* | |
71 | * Instantiate a SimpleDateFormat set up to produce a full time | |
72 | zone name. | |
73 | */ | |
74 | SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)"zzzz", status); | |
75 | /* | |
76 | * A String array for the time zone ids. | |
77 | */ | |
78 | int32_t ids_length; | |
79 | StringEnumeration* ids = TimeZone::createEnumeration(); | |
80 | ids_length = ids->count(status); | |
81 | /* | |
82 | * How many ids do we have? | |
83 | */ | |
84 | logln("Time Zone IDs size: %d", ids_length); | |
85 | /* | |
86 | * Column headings (sort of) | |
87 | */ | |
88 | logln("Ordinal ID offset(h:m) name"); | |
89 | /* | |
90 | * Loop through the tzs. | |
91 | */ | |
92 | UDate today = Calendar::getNow(); | |
93 | Calendar *cal = Calendar::createInstance(status); | |
94 | for (int32_t i = 0; i < ids_length; i++) { | |
95 | // logln(i + " " + ids[i]); | |
96 | const UnicodeString* id = ids->snext(status); | |
97 | TimeZone *ttz = TimeZone::createTimeZone(*id); | |
98 | // offset = ttz.getRawOffset(); | |
99 | cal->setTimeZone(*ttz); | |
100 | cal->setTime(today, status); | |
101 | offset = cal->get(UCAL_ZONE_OFFSET, status) + cal->get(UCAL_DST_OFFSET, status); | |
102 | // logln(i + " " + ids[i] + " offset " + offset); | |
103 | const char* sign = "+"; | |
104 | if (offset < 0) { | |
105 | sign = "-"; | |
106 | offset = -offset; | |
107 | } | |
108 | hours = offset/3600000; | |
109 | minutes = (offset%3600000)/60000; | |
110 | UnicodeString dstOffset = (UnicodeString)"" + sign + (hours < 10 ? "0" : "") + | |
111 | (int32_t)hours + ":" + (minutes < 10 ? "0" : "") + (int32_t)minutes; | |
112 | /* | |
113 | * Instantiate a date so we can display the time zone name. | |
114 | */ | |
115 | sdf->setTimeZone(*ttz); | |
116 | /* | |
117 | * Format the output. | |
118 | */ | |
119 | UnicodeString fmtOffset; | |
120 | FieldPosition pos(0); | |
121 | sdf->format(today,fmtOffset, pos); | |
122 | // UnicodeString fmtOffset = tzS.toString(); | |
123 | UnicodeString *fmtDstOffset = 0; | |
124 | if (fmtOffset.startsWith("GMT")) | |
125 | { | |
126 | //fmtDstOffset = fmtOffset->substring(3); | |
127 | fmtDstOffset = new UnicodeString(); | |
128 | fmtOffset.extract(3, fmtOffset.length(), *fmtDstOffset); | |
129 | } | |
130 | /* | |
131 | * Show our result. | |
132 | */ | |
133 | UBool ok = fmtDstOffset == 0 || *fmtDstOffset == dstOffset; | |
134 | if (ok) | |
135 | { | |
136 | logln(UnicodeString() + i + " " + *id + " " + dstOffset + | |
137 | " " + fmtOffset + | |
138 | (fmtDstOffset != 0 ? " ok" : " ?")); | |
139 | } | |
140 | else | |
141 | { | |
142 | errln(UnicodeString() + i + " " + *id + " " + dstOffset + | |
143 | " " + fmtOffset + " *** FAIL ***"); | |
144 | } | |
145 | delete ttz; | |
146 | delete fmtDstOffset; | |
147 | } | |
148 | delete cal; | |
149 | // delete ids; // TODO: BAD API | |
150 | delete ids; | |
151 | delete sdf; | |
152 | delete tz; | |
153 | } | |
154 | ||
155 | // ------------------------------------- | |
156 | ||
157 | /** | |
158 | * Test operator== | |
159 | */ | |
160 | void | |
161 | DateFormatTest::TestEquals() | |
162 | { | |
163 | DateFormat* fmtA = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL); | |
164 | DateFormat* fmtB = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL); | |
165 | if (!(*fmtA == *fmtB)) errln((UnicodeString)"FAIL"); | |
166 | delete fmtA; | |
167 | delete fmtB; | |
168 | } | |
169 | ||
170 | // ------------------------------------- | |
171 | ||
172 | /** | |
173 | * Test the parsing of 2-digit years. | |
174 | */ | |
175 | void | |
176 | DateFormatTest::TestTwoDigitYearDSTParse(void) | |
177 | { | |
178 | UErrorCode status = U_ZERO_ERROR; | |
179 | SimpleDateFormat* fullFmt = new SimpleDateFormat((UnicodeString)"EEE MMM dd HH:mm:ss.SSS zzz yyyy G", status); | |
180 | SimpleDateFormat *fmt = new SimpleDateFormat((UnicodeString)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status); | |
181 | //DateFormat* fmt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, Locale::ENGLISH); | |
182 | UnicodeString* s = new UnicodeString("03-Apr-04 2:20:47 o'clock AM PST", ""); | |
183 | int32_t hour = 2; | |
184 | ||
185 | UnicodeString str; | |
186 | UDate d = fmt->parse(*s, status); | |
187 | logln(*s + " P> " + ((DateFormat*)fullFmt)->format(d, str)); | |
188 | int32_t y, m, day, hr, min, sec; | |
189 | dateToFields(d, y, m, day, hr, min, sec); | |
190 | if (hr != hour) | |
191 | errln((UnicodeString)"FAIL: Should parse to hour " + hour); | |
192 | ||
193 | if (U_FAILURE(status)) | |
194 | errln((UnicodeString)"FAIL: " + (int32_t)status); | |
195 | ||
196 | delete s; | |
197 | delete fmt; | |
198 | delete fullFmt; | |
199 | } | |
200 | ||
201 | // ------------------------------------- | |
202 | ||
203 | UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); } | |
204 | ||
205 | UnicodeString& | |
206 | DateFormatTest::escape(UnicodeString& s) | |
207 | { | |
208 | UnicodeString buf; | |
209 | for (int32_t i=0; i<s.length(); ++i) | |
210 | { | |
211 | UChar c = s[(int32_t)i]; | |
212 | if (c <= (UChar)0x7F) buf += c; | |
213 | else { | |
214 | buf += (UChar)0x5c; buf += (UChar)0x55; | |
215 | buf += toHexString((c & 0xF000) >> 12); | |
216 | buf += toHexString((c & 0x0F00) >> 8); | |
217 | buf += toHexString((c & 0x00F0) >> 4); | |
218 | buf += toHexString(c & 0x000F); | |
219 | } | |
220 | } | |
221 | return (s = buf); | |
222 | } | |
223 | ||
b75a7d8f A |
224 | // ------------------------------------- |
225 | ||
374ca955 A |
226 | /** |
227 | * This MUST be kept in sync with DateFormatSymbols.gPatternChars. | |
228 | */ | |
229 | static const char* PATTERN_CHARS = "GyMdkHmsSEDFwWahKzYeugAZ"; | |
230 | ||
231 | /** | |
232 | * A list of the names of all the fields in DateFormat. | |
233 | * This MUST be kept in sync with DateFormat. | |
234 | */ | |
235 | static const char* DATEFORMAT_FIELD_NAMES[] = { | |
236 | "ERA_FIELD", | |
237 | "YEAR_FIELD", | |
238 | "MONTH_FIELD", | |
239 | "DATE_FIELD", | |
240 | "HOUR_OF_DAY1_FIELD", | |
241 | "HOUR_OF_DAY0_FIELD", | |
242 | "MINUTE_FIELD", | |
243 | "SECOND_FIELD", | |
244 | "MILLISECOND_FIELD", | |
245 | "DAY_OF_WEEK_FIELD", | |
246 | "DAY_OF_YEAR_FIELD", | |
247 | "DAY_OF_WEEK_IN_MONTH_FIELD", | |
248 | "WEEK_OF_YEAR_FIELD", | |
249 | "WEEK_OF_MONTH_FIELD", | |
250 | "AM_PM_FIELD", | |
251 | "HOUR1_FIELD", | |
252 | "HOUR0_FIELD", | |
253 | "TIMEZONE_FIELD", | |
254 | "YEAR_WOY_FIELD", | |
255 | "DOW_LOCAL_FIELD", | |
256 | "EXTENDED_YEAR_FIELD", | |
257 | "JULIAN_DAY_FIELD", | |
258 | "MILLISECONDS_IN_DAY_FIELD", | |
259 | "TIMEZONE_RFC_FIELD" | |
b75a7d8f A |
260 | }; |
261 | ||
374ca955 A |
262 | static const int32_t DATEFORMAT_FIELD_NAMES_LENGTH = |
263 | sizeof(DATEFORMAT_FIELD_NAMES) / sizeof(DATEFORMAT_FIELD_NAMES[0]); | |
264 | ||
b75a7d8f A |
265 | /** |
266 | * Verify that returned field position indices are correct. | |
267 | */ | |
374ca955 A |
268 | void DateFormatTest::TestFieldPosition() { |
269 | UErrorCode ec = U_ZERO_ERROR; | |
270 | int32_t i, j, exp; | |
271 | UnicodeString buf; | |
272 | ||
273 | // Verify data | |
274 | DateFormatSymbols rootSyms(Locale(""), ec); | |
275 | assertSuccess("DateFormatSymbols", ec); | |
276 | assertEquals("patternChars", PATTERN_CHARS, rootSyms.getLocalPatternChars(buf)); | |
277 | assertEquals("patternChars", PATTERN_CHARS, DateFormatSymbols::getPatternUChars()); | |
278 | assertTrue("DATEFORMAT_FIELD_NAMES", DATEFORMAT_FIELD_NAMES_LENGTH == UDAT_FIELD_COUNT); | |
279 | assertTrue("Data", UDAT_FIELD_COUNT == uprv_strlen(PATTERN_CHARS)); | |
280 | ||
281 | // Create test formatters | |
282 | const int32_t COUNT = 4; | |
283 | DateFormat* dateFormats[COUNT]; | |
284 | dateFormats[0] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getUS()); | |
285 | dateFormats[1] = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, Locale::getFrance()); | |
286 | // Make the pattern "G y M d..." | |
287 | buf.remove().append(PATTERN_CHARS); | |
288 | for (j=buf.length()-1; j>=0; --j) buf.insert(j, (UChar)32/*' '*/); | |
289 | dateFormats[2] = new SimpleDateFormat(buf, Locale::getUS(), ec); | |
290 | // Make the pattern "GGGG yyyy MMMM dddd..." | |
291 | for (j=buf.length()-1; j>=0; j-=2) { | |
292 | for (i=0; i<3; ++i) { | |
293 | buf.insert(j, buf.charAt(j)); | |
294 | } | |
295 | } | |
296 | dateFormats[3] = new SimpleDateFormat(buf, Locale::getUS(), ec); | |
297 | ||
298 | UDate aug13 = 871508052513.0; | |
299 | ||
300 | // Expected output field values for above DateFormats on aug13 | |
301 | // Fields are given in order of DateFormat field number | |
302 | const char* EXPECTED[] = { | |
303 | "", "1997", "August", "13", "", "", "34", "12", "", | |
304 | "Wednesday", "", "", "", "", "PM", "2", "", "PDT", "", "", "", "", "", "", | |
305 | ||
306 | "", "1997", "ao\\u00FBt", "13", "", "14", "34", "", "", | |
307 | "mercredi", "", "", "", "", "", "", "", "HAP (\\u00C9UA)", "", "", "", "", "", "", | |
308 | ||
309 | "AD", "1997", "8", "13", "14", "14", "34", "12", "5", | |
310 | "Wed", "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4", "1997", "2450674", "52452513", "-0700", | |
b75a7d8f | 311 | |
374ca955 A |
312 | "AD", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130", |
313 | "Wednesday", "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "0004", "1997", "2450674", "52452513", "-0700", | |
b75a7d8f A |
314 | }; |
315 | ||
374ca955 | 316 | const int32_t EXPECTED_LENGTH = sizeof(EXPECTED)/sizeof(EXPECTED[0]); |
b75a7d8f | 317 | |
374ca955 A |
318 | assertTrue("data size", EXPECTED_LENGTH == COUNT * UDAT_FIELD_COUNT); |
319 | ||
320 | TimeZone* PT = TimeZone::createTimeZone("America/Los_Angeles"); | |
321 | for (j = 0, exp = 0; j < COUNT; ++j) { | |
322 | // String str; | |
b75a7d8f | 323 | DateFormat* df = dateFormats[j]; |
374ca955 A |
324 | df->setTimeZone(*PT); |
325 | if (df->getDynamicClassID() == SimpleDateFormat::getStaticClassID()) { | |
326 | logln(" Pattern = " + ((SimpleDateFormat*) df)->toPattern(buf.remove())); | |
327 | } else { | |
328 | logln(" Pattern = ? (not a SimpleDateFormat)"); | |
329 | } | |
330 | logln((UnicodeString)" Result = " + df->format(aug13, buf.remove())); | |
331 | ||
332 | for (i = 0; i < UDAT_FIELD_COUNT; ++i, ++exp) { | |
333 | FieldPosition pos(i); | |
334 | df->format(aug13, buf.remove(), pos); | |
b75a7d8f | 335 | UnicodeString field; |
374ca955 A |
336 | buf.extractBetween(pos.getBeginIndex(), pos.getEndIndex(), field); |
337 | assertEquals((UnicodeString)"field #" + i + " " + DATEFORMAT_FIELD_NAMES[i], | |
338 | ctou(EXPECTED[exp]), field); | |
b75a7d8f A |
339 | } |
340 | } | |
374ca955 A |
341 | |
342 | for (i=0; i<COUNT; ++i) { | |
343 | delete dateFormats[i]; | |
344 | } | |
345 | delete PT; | |
b75a7d8f | 346 | } |
374ca955 | 347 | |
b75a7d8f | 348 | // ------------------------------------- |
374ca955 A |
349 | |
350 | /** | |
351 | * General parse/format tests. Add test cases as needed. | |
352 | */ | |
353 | void DateFormatTest::TestGeneral() { | |
354 | const char* DATA[] = { | |
355 | "yyyy MM dd HH:mm:ss.SSS", | |
356 | ||
357 | // Milliseconds are left-justified, since they format as fractions of a second | |
358 | "y/M/d H:mm:ss.S", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.6", "2004 03 10 16:36:31.600", | |
359 | "y/M/d H:mm:ss.SS", "fp", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.57", "2004 03 10 16:36:31.570", | |
360 | "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567", | |
361 | "y/M/d H:mm:ss.SSSS", "pf", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.568", "2004/3/10 16:36:31.5680", | |
362 | }; | |
363 | expect(DATA, sizeof(DATA)/sizeof(DATA[0]), Locale("en", "", "")); | |
b75a7d8f A |
364 | } |
365 | ||
366 | // ------------------------------------- | |
367 | ||
368 | /** | |
369 | * Verify that strings which contain incomplete specifications are parsed | |
370 | * correctly. In some instances, this means not being parsed at all, and | |
371 | * returning an appropriate error. | |
372 | */ | |
373 | void | |
374 | DateFormatTest::TestPartialParse994() | |
375 | { | |
376 | UErrorCode status = U_ZERO_ERROR; | |
377 | SimpleDateFormat* f = new SimpleDateFormat(status); | |
378 | UDate null = 0; | |
379 | tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", date(97, 1 - 1, 17, 10, 11, 42)); | |
380 | tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null); | |
381 | tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null); | |
382 | tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null); | |
383 | tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null); | |
384 | if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status); | |
385 | delete f; | |
386 | } | |
387 | ||
388 | // ------------------------------------- | |
389 | ||
390 | void | |
391 | DateFormatTest::tryPat994(SimpleDateFormat* format, const char* pat, const char* str, UDate expected) | |
392 | { | |
393 | UErrorCode status = U_ZERO_ERROR; | |
394 | UDate null = 0; | |
395 | logln(UnicodeString("Pattern \"") + pat + "\" String \"" + str + "\""); | |
396 | //try { | |
397 | format->applyPattern(pat); | |
398 | UDate date = format->parse(str, status); | |
399 | if (U_FAILURE(status) || date == null) | |
400 | { | |
401 | logln((UnicodeString)"ParseException: " + (int32_t)status); | |
402 | if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected)); | |
403 | } | |
404 | else | |
405 | { | |
406 | UnicodeString f; | |
407 | ((DateFormat*)format)->format(date, f); | |
408 | logln(UnicodeString(" parse(") + str + ") -> " + dateToString(date)); | |
409 | logln((UnicodeString)" format -> " + f); | |
410 | if (expected == null || | |
411 | !(date == expected)) errln((UnicodeString)"FAIL: Expected null");//" + expected); | |
412 | if (!(f == str)) errln(UnicodeString("FAIL: Expected ") + str); | |
413 | } | |
414 | //} | |
415 | //catch(ParseException e) { | |
416 | // logln((UnicodeString)"ParseException: " + e.getMessage()); | |
417 | // if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected)); | |
418 | //} | |
419 | //catch(Exception e) { | |
420 | // errln((UnicodeString)"*** Exception:"); | |
421 | // e.printStackTrace(); | |
422 | //} | |
423 | } | |
424 | ||
425 | // ------------------------------------- | |
426 | ||
427 | /** | |
428 | * Verify the behavior of patterns in which digits for different fields run together | |
429 | * without intervening separators. | |
430 | */ | |
431 | void | |
432 | DateFormatTest::TestRunTogetherPattern985() | |
433 | { | |
434 | UErrorCode status = U_ZERO_ERROR; | |
435 | UnicodeString format("yyyyMMddHHmmssSSS"); | |
436 | UnicodeString now, then; | |
437 | //UBool flag; | |
438 | SimpleDateFormat *formatter = new SimpleDateFormat(format, status); | |
439 | UDate date1 = Calendar::getNow(); | |
440 | ((DateFormat*)formatter)->format(date1, now); | |
441 | logln(now); | |
442 | ParsePosition pos(0); | |
443 | UDate date2 = formatter->parse(now, pos); | |
444 | if (date2 == 0) then = "Parse stopped at " + pos.getIndex(); | |
445 | else ((DateFormat*)formatter)->format(date2, then); | |
446 | logln(then); | |
447 | if (!(date2 == date1)) errln((UnicodeString)"FAIL"); | |
448 | delete formatter; | |
449 | if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status); | |
450 | } | |
451 | ||
452 | // ------------------------------------- | |
453 | ||
454 | /** | |
455 | * Verify the behavior of patterns in which digits for different fields run together | |
456 | * without intervening separators. | |
457 | */ | |
458 | void | |
459 | DateFormatTest::TestRunTogetherPattern917() | |
460 | { | |
461 | UErrorCode status = U_ZERO_ERROR; | |
462 | SimpleDateFormat* fmt; | |
463 | UnicodeString myDate; | |
464 | fmt = new SimpleDateFormat((UnicodeString)"yyyy/MM/dd", status); | |
465 | myDate = "1997/02/03"; | |
466 | testIt917(fmt, myDate, date(97, 2 - 1, 3)); | |
467 | delete fmt; | |
468 | fmt = new SimpleDateFormat((UnicodeString)"yyyyMMdd", status); | |
469 | myDate = "19970304"; | |
470 | testIt917(fmt, myDate, date(97, 3 - 1, 4)); | |
471 | delete fmt; | |
472 | if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status); | |
473 | } | |
474 | ||
475 | // ------------------------------------- | |
476 | ||
477 | void | |
478 | DateFormatTest::testIt917(SimpleDateFormat* fmt, UnicodeString& str, UDate expected) | |
479 | { | |
480 | UErrorCode status = U_ZERO_ERROR; | |
481 | UnicodeString pattern; | |
482 | logln((UnicodeString)"pattern=" + fmt->toPattern(pattern) + " string=" + str); | |
483 | Formattable o; | |
484 | //try { | |
485 | ((Format*)fmt)->parseObject(str, o, status); | |
486 | //} | |
487 | if (U_FAILURE(status)) return; | |
488 | //catch(ParseException e) { | |
489 | // e.printStackTrace(); | |
490 | // return; | |
491 | //} | |
492 | logln((UnicodeString)"Parsed object: " + dateToString(o.getDate())); | |
493 | if (!(o.getDate() == expected)) errln((UnicodeString)"FAIL: Expected " + dateToString(expected)); | |
494 | UnicodeString formatted; ((Format*)fmt)->format(o, formatted, status); | |
495 | logln((UnicodeString)"Formatted string: " + formatted); | |
496 | if (!(formatted == str)) errln((UnicodeString)"FAIL: Expected " + str); | |
497 | if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status); | |
498 | } | |
499 | ||
500 | // ------------------------------------- | |
501 | ||
502 | /** | |
503 | * Verify the handling of Czech June and July, which have the unique attribute that | |
504 | * one is a proper prefix substring of the other. | |
505 | */ | |
506 | void | |
507 | DateFormatTest::TestCzechMonths459() | |
508 | { | |
509 | UErrorCode status = U_ZERO_ERROR; | |
510 | DateFormat* fmt = DateFormat::createDateInstance(DateFormat::FULL, Locale("cs", "", "")); | |
511 | UnicodeString pattern; | |
512 | logln((UnicodeString)"Pattern " + ((SimpleDateFormat*) fmt)->toPattern(pattern)); | |
513 | UDate june = date(97, UCAL_JUNE, 15); | |
514 | UDate july = date(97, UCAL_JULY, 15); | |
515 | UnicodeString juneStr; fmt->format(june, juneStr); | |
516 | UnicodeString julyStr; fmt->format(july, julyStr); | |
517 | //try { | |
518 | logln((UnicodeString)"format(June 15 1997) = " + juneStr); | |
519 | UDate d = fmt->parse(juneStr, status); | |
520 | UnicodeString s; fmt->format(d, s); | |
521 | int32_t month,yr,day,hr,min,sec; dateToFields(d,yr,month,day,hr,min,sec); | |
522 | logln((UnicodeString)" -> parse -> " + s + " (month = " + month + ")"); | |
523 | if (month != UCAL_JUNE) errln((UnicodeString)"FAIL: Month should be June"); | |
524 | logln((UnicodeString)"format(July 15 1997) = " + julyStr); | |
525 | d = fmt->parse(julyStr, status); | |
526 | fmt->format(d, s); | |
527 | dateToFields(d,yr,month,day,hr,min,sec); | |
528 | logln((UnicodeString)" -> parse -> " + s + " (month = " + month + ")"); | |
529 | if (month != UCAL_JULY) errln((UnicodeString)"FAIL: Month should be July"); | |
530 | //} | |
531 | //catch(ParseException e) { | |
532 | if (U_FAILURE(status)) | |
533 | errln((UnicodeString)"Exception: " + (int32_t)status); | |
534 | //} | |
535 | delete fmt; | |
536 | } | |
537 | ||
538 | // ------------------------------------- | |
539 | ||
540 | /** | |
541 | * Test the handling of 'D' in patterns. | |
542 | */ | |
543 | void | |
544 | DateFormatTest::TestLetterDPattern212() | |
545 | { | |
546 | UErrorCode status = U_ZERO_ERROR; | |
547 | UnicodeString dateString("1995-040.05:01:29"); | |
548 | UnicodeString bigD("yyyy-DDD.hh:mm:ss"); | |
549 | UnicodeString littleD("yyyy-ddd.hh:mm:ss"); | |
550 | UDate expLittleD = date(95, 0, 1, 5, 1, 29); | |
551 | UDate expBigD = expLittleD + 39 * 24 * 3600000.0; | |
552 | expLittleD = expBigD; // Expect the same, with default lenient parsing | |
553 | logln((UnicodeString)"dateString= " + dateString); | |
554 | SimpleDateFormat *formatter = new SimpleDateFormat(bigD, status); | |
555 | ParsePosition pos(0); | |
556 | UDate myDate = formatter->parse(dateString, pos); | |
557 | logln((UnicodeString)"Using " + bigD + " -> " + myDate); | |
558 | if (myDate != expBigD) errln((UnicodeString)"FAIL: Expected " + dateToString(expBigD)); | |
559 | delete formatter; | |
560 | formatter = new SimpleDateFormat(littleD, status); | |
561 | pos = ParsePosition(0); | |
562 | myDate = formatter->parse(dateString, pos); | |
563 | logln((UnicodeString)"Using " + littleD + " -> " + dateToString(myDate)); | |
564 | if (myDate != expLittleD) errln((UnicodeString)"FAIL: Expected " + dateToString(expLittleD)); | |
565 | delete formatter; | |
566 | if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status); | |
567 | } | |
568 | ||
569 | // ------------------------------------- | |
570 | ||
571 | /** | |
572 | * Test the day of year pattern. | |
573 | */ | |
574 | void | |
575 | DateFormatTest::TestDayOfYearPattern195() | |
576 | { | |
577 | UErrorCode status = U_ZERO_ERROR; | |
578 | UDate today = Calendar::getNow(); | |
579 | int32_t year,month,day,hour,min,sec; dateToFields(today,year,month,day,hour,min,sec); | |
580 | UDate expected = date(year, month, day); | |
581 | logln((UnicodeString)"Test Date: " + dateToString(today)); | |
582 | SimpleDateFormat* sdf = (SimpleDateFormat*)DateFormat::createDateInstance(); | |
583 | tryPattern(*sdf, today, 0, expected); | |
584 | tryPattern(*sdf, today, "G yyyy DDD", expected); | |
585 | delete sdf; | |
586 | if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status); | |
587 | } | |
588 | ||
589 | // ------------------------------------- | |
590 | ||
591 | void | |
592 | DateFormatTest::tryPattern(SimpleDateFormat& sdf, UDate d, const char* pattern, UDate expected) | |
593 | { | |
594 | UErrorCode status = U_ZERO_ERROR; | |
595 | if (pattern != 0) sdf.applyPattern(pattern); | |
596 | UnicodeString thePat; | |
597 | logln((UnicodeString)"pattern: " + sdf.toPattern(thePat)); | |
598 | UnicodeString formatResult; (*(DateFormat*)&sdf).format(d, formatResult); | |
599 | logln((UnicodeString)" format -> " + formatResult); | |
600 | // try { | |
601 | UDate d2 = sdf.parse(formatResult, status); | |
602 | logln((UnicodeString)" parse(" + formatResult + ") -> " + dateToString(d2)); | |
603 | if (d2 != expected) errln((UnicodeString)"FAIL: Expected " + dateToString(expected)); | |
604 | UnicodeString format2; (*(DateFormat*)&sdf).format(d2, format2); | |
605 | logln((UnicodeString)" format -> " + format2); | |
606 | if (!(formatResult == format2)) errln((UnicodeString)"FAIL: Round trip drift"); | |
607 | //} | |
608 | //catch(Exception e) { | |
609 | if (U_FAILURE(status)) | |
610 | errln((UnicodeString)"Error: " + (int32_t)status); | |
611 | //} | |
612 | } | |
613 | ||
614 | // ------------------------------------- | |
615 | ||
616 | /** | |
617 | * Test the handling of single quotes in patterns. | |
618 | */ | |
619 | void | |
620 | DateFormatTest::TestQuotePattern161() | |
621 | { | |
622 | UErrorCode status = U_ZERO_ERROR; | |
623 | SimpleDateFormat* formatter = new SimpleDateFormat((UnicodeString)"MM/dd/yyyy 'at' hh:mm:ss a zzz", status); | |
624 | UDate currentTime_1 = date(97, UCAL_AUGUST, 13, 10, 42, 28); | |
625 | UnicodeString dateString; ((DateFormat*)formatter)->format(currentTime_1, dateString); | |
626 | UnicodeString exp("08/13/1997 at 10:42:28 AM "); | |
627 | logln((UnicodeString)"format(" + dateToString(currentTime_1) + ") = " + dateString); | |
628 | if (0 != dateString.compareBetween(0, exp.length(), exp, 0, exp.length())) errln((UnicodeString)"FAIL: Expected " + exp); | |
629 | delete formatter; | |
630 | if (U_FAILURE(status)) errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status); | |
631 | } | |
632 | ||
633 | // ------------------------------------- | |
634 | ||
635 | /** | |
636 | * Verify the correct behavior when handling invalid input strings. | |
637 | */ | |
638 | void | |
639 | DateFormatTest::TestBadInput135() | |
640 | { | |
641 | UErrorCode status = U_ZERO_ERROR; | |
642 | DateFormat::EStyle looks[] = { | |
643 | DateFormat::SHORT, DateFormat::MEDIUM, DateFormat::LONG, DateFormat::FULL | |
644 | }; | |
645 | int32_t looks_length = (int32_t)(sizeof(looks) / sizeof(looks[0])); | |
646 | const char* strings[] = { | |
647 | "Mar 15", "Mar 15 1997", "asdf", "3/1/97 1:23:", "3/1/00 1:23:45 AM" | |
648 | }; | |
649 | int32_t strings_length = (int32_t)(sizeof(strings) / sizeof(strings[0])); | |
650 | DateFormat *full = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::LONG); | |
651 | UnicodeString expected("March 1, 2000 1:23:45 AM "); | |
652 | for (int32_t i = 0; i < strings_length;++i) { | |
653 | const char* text = strings[i]; | |
654 | for (int32_t j = 0; j < looks_length;++j) { | |
655 | DateFormat::EStyle dateLook = looks[j]; | |
656 | for (int32_t k = 0; k < looks_length;++k) { | |
657 | DateFormat::EStyle timeLook = looks[k]; | |
658 | DateFormat *df = DateFormat::createDateTimeInstance(dateLook, timeLook); | |
659 | UnicodeString prefix = UnicodeString(text) + ", " + dateLook + "/" + timeLook + ": "; | |
660 | //try { | |
661 | UDate when = df->parse(text, status); | |
662 | if (when == 0 && U_SUCCESS(status)) { | |
663 | errln(prefix + "SHOULD NOT HAPPEN: parse returned 0."); | |
664 | continue; | |
665 | } | |
666 | if (U_SUCCESS(status)) | |
667 | { | |
668 | UnicodeString format; | |
669 | full->format(when, format); | |
670 | logln(prefix + "OK: " + format); | |
671 | if (0!=format.compareBetween(0, expected.length(), expected, 0, expected.length())) | |
672 | errln((UnicodeString)"FAIL: Expected " + expected + " got " + format); | |
673 | } | |
674 | //} | |
675 | //catch(ParseException e) { | |
676 | else | |
677 | status = U_ZERO_ERROR; | |
678 | //} | |
679 | //catch(StringIndexOutOfBoundsException e) { | |
680 | // errln(prefix + "SHOULD NOT HAPPEN: " + (int)status); | |
681 | //} | |
682 | delete df; | |
683 | } | |
684 | } | |
685 | } | |
686 | delete full; | |
687 | if (U_FAILURE(status)) | |
688 | errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status); | |
689 | } | |
690 | ||
691 | const char* DateFormatTest::parseFormats[] = { | |
692 | "MMMM d, yyyy", | |
693 | "MMMM d yyyy", | |
694 | "M/d/yy", | |
695 | "d MMMM, yyyy", | |
696 | "d MMMM yyyy", | |
697 | "d MMMM", | |
698 | "MMMM d", | |
699 | "yyyy", | |
700 | "h:mm a MMMM d, yyyy" | |
701 | }; | |
702 | ||
703 | const char* DateFormatTest::inputStrings[] = { | |
704 | "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
705 | "April 1, 1997", "April 1, 1997", 0, 0, 0, 0, 0, "April 1", 0, 0, | |
706 | "Jan 1, 1970", "January 1, 1970", 0, 0, 0, 0, 0, "January 1", 0, 0, | |
707 | "Jan 1 2037", 0, "January 1 2037", 0, 0, 0, 0, "January 1", 0, 0, | |
708 | "1/1/70", 0, 0, "1/1/70", 0, 0, 0, 0, "0001", 0, | |
709 | "5 May 1997", 0, 0, 0, 0, "5 May 1997", "5 May", 0, "0005", 0, | |
710 | "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0, | |
711 | "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0, | |
712 | "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0, | |
713 | "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0, | |
714 | "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997", | |
715 | }; | |
716 | ||
717 | // ------------------------------------- | |
718 | ||
719 | /** | |
720 | * Verify the correct behavior when parsing an array of inputs against an | |
721 | * array of patterns, with known results. The results are encoded after | |
722 | * the input strings in each row. | |
723 | */ | |
724 | void | |
725 | DateFormatTest::TestBadInput135a() | |
726 | { | |
727 | UErrorCode status = U_ZERO_ERROR; | |
728 | SimpleDateFormat* dateParse = new SimpleDateFormat(status); | |
729 | if(U_FAILURE(status)) { | |
730 | errln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status)); | |
731 | delete dateParse; | |
732 | return; | |
733 | } | |
734 | const char* s; | |
735 | UDate date; | |
736 | const uint32_t PF_LENGTH = (int32_t)(sizeof(parseFormats)/sizeof(parseFormats[0])); | |
737 | const uint32_t INPUT_LENGTH = (int32_t)(sizeof(inputStrings)/sizeof(inputStrings[0])); | |
738 | ||
739 | dateParse->applyPattern("d MMMM, yyyy"); | |
740 | dateParse->adoptTimeZone(TimeZone::createDefault()); | |
741 | s = "not parseable"; | |
742 | UnicodeString thePat; | |
743 | logln(UnicodeString("Trying to parse \"") + s + "\" with " + dateParse->toPattern(thePat)); | |
744 | //try { | |
745 | date = dateParse->parse(s, status); | |
746 | if (U_SUCCESS(status)) | |
747 | errln((UnicodeString)"FAIL: Expected exception during parse"); | |
748 | //} | |
749 | //catch(Exception ex) { | |
750 | else | |
751 | logln((UnicodeString)"Exception during parse: " + (int32_t)status); | |
752 | status = U_ZERO_ERROR; | |
753 | //} | |
754 | for (uint32_t i = 0; i < INPUT_LENGTH; i += (PF_LENGTH + 1)) { | |
755 | ParsePosition parsePosition(0); | |
756 | UnicodeString s( inputStrings[i]); | |
757 | for (uint32_t index = 0; index < PF_LENGTH;++index) { | |
758 | const char* expected = inputStrings[i + 1 + index]; | |
759 | dateParse->applyPattern(parseFormats[index]); | |
760 | dateParse->adoptTimeZone(TimeZone::createDefault()); | |
761 | //try { | |
762 | parsePosition.setIndex(0); | |
763 | date = dateParse->parse(s, parsePosition); | |
764 | if (parsePosition.getIndex() != 0) { | |
765 | UnicodeString s1, s2; | |
766 | s.extract(0, parsePosition.getIndex(), s1); | |
767 | s.extract(parsePosition.getIndex(), s.length(), s2); | |
768 | if (date == 0) { | |
769 | errln((UnicodeString)"ERROR: null result fmt=\"" + | |
770 | parseFormats[index] + | |
771 | "\" pos=" + parsePosition.getIndex() + " " + | |
772 | s1 + "|" + s2); | |
773 | } | |
774 | else { | |
775 | UnicodeString result; | |
776 | ((DateFormat*)dateParse)->format(date, result); | |
777 | logln((UnicodeString)"Parsed \"" + s + "\" using \"" + dateParse->toPattern(thePat) + "\" to: " + result); | |
778 | if (expected == 0) | |
779 | errln((UnicodeString)"FAIL: Expected parse failure"); | |
780 | else if (!(result == expected)) | |
781 | errln(UnicodeString("FAIL: Expected ") + expected); | |
782 | } | |
783 | } | |
784 | else if (expected != 0) { | |
785 | errln(UnicodeString("FAIL: Expected ") + expected + " from \"" + | |
786 | s + "\" with \"" + dateParse->toPattern(thePat) + "\""); | |
787 | } | |
788 | //} | |
789 | //catch(Exception ex) { | |
790 | if (U_FAILURE(status)) | |
791 | errln((UnicodeString)"An exception was thrown during parse: " + (int32_t)status); | |
792 | //} | |
793 | } | |
794 | } | |
795 | delete dateParse; | |
796 | if (U_FAILURE(status)) | |
797 | errln((UnicodeString)"FAIL: UErrorCode received during test: " + (int32_t)status); | |
798 | } | |
799 | ||
800 | // ------------------------------------- | |
801 | ||
802 | /** | |
803 | * Test the parsing of two-digit years. | |
804 | */ | |
805 | void | |
806 | DateFormatTest::TestTwoDigitYear() | |
807 | { | |
808 | UErrorCode ec = U_ZERO_ERROR; | |
809 | SimpleDateFormat fmt("dd/MM/yy", Locale::getUK(), ec); | |
810 | if (U_FAILURE(ec)) { | |
811 | errln("FAIL: SimpleDateFormat constructor"); | |
812 | return; | |
813 | } | |
814 | parse2DigitYear(fmt, "5/6/17", date(117, UCAL_JUNE, 5)); | |
815 | parse2DigitYear(fmt, "4/6/34", date(34, UCAL_JUNE, 4)); | |
816 | } | |
817 | ||
818 | // ------------------------------------- | |
819 | ||
820 | void | |
821 | DateFormatTest::parse2DigitYear(DateFormat& fmt, const char* str, UDate expected) | |
822 | { | |
823 | UErrorCode status = U_ZERO_ERROR; | |
824 | //try { | |
825 | UDate d = fmt.parse(str, status); | |
826 | UnicodeString thePat; | |
827 | logln(UnicodeString("Parsing \"") + str + "\" with " + ((SimpleDateFormat*)&fmt)->toPattern(thePat) + | |
828 | " => " + dateToString(d)); | |
829 | if (d != expected) errln((UnicodeString)"FAIL: Expected " + expected); | |
830 | //} | |
831 | //catch(ParseException e) { | |
832 | if (U_FAILURE(status)) | |
833 | errln((UnicodeString)"FAIL: Got exception"); | |
834 | //} | |
835 | } | |
836 | ||
837 | // ------------------------------------- | |
838 | ||
839 | /** | |
840 | * Test the formatting of time zones. | |
841 | */ | |
842 | void | |
843 | DateFormatTest::TestDateFormatZone061() | |
844 | { | |
845 | UErrorCode status = U_ZERO_ERROR; | |
846 | UDate date; | |
847 | DateFormat *formatter; | |
848 | date= 859248000000.0; | |
849 | logln((UnicodeString)"Date 1997/3/25 00:00 GMT: " + date); | |
850 | formatter = new SimpleDateFormat((UnicodeString)"dd-MMM-yyyyy HH:mm", Locale::getUK(), status); | |
851 | if(U_FAILURE(status)) { | |
852 | errln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status)); | |
853 | delete formatter; | |
854 | return; | |
855 | } | |
856 | formatter->adoptTimeZone(TimeZone::createTimeZone("GMT")); | |
857 | UnicodeString temp; formatter->format(date, temp); | |
858 | logln((UnicodeString)"Formatted in GMT to: " + temp); | |
859 | //try { | |
860 | UDate tempDate = formatter->parse(temp, status); | |
861 | logln((UnicodeString)"Parsed to: " + dateToString(tempDate)); | |
862 | if (tempDate != date) errln((UnicodeString)"FAIL: Expected " + dateToString(date)); | |
863 | //} | |
864 | //catch(Throwable t) { | |
865 | if (U_FAILURE(status)) | |
866 | errln((UnicodeString)"Date Formatter throws: " + (int32_t)status); | |
867 | //} | |
868 | delete formatter; | |
869 | } | |
870 | ||
871 | // ------------------------------------- | |
872 | ||
873 | /** | |
874 | * Test the formatting of time zones. | |
875 | */ | |
876 | void | |
877 | DateFormatTest::TestDateFormatZone146() | |
878 | { | |
879 | TimeZone *saveDefault = TimeZone::createDefault(); | |
880 | ||
881 | //try { | |
882 | TimeZone *thedefault = TimeZone::createTimeZone("GMT"); | |
883 | TimeZone::setDefault(*thedefault); | |
884 | // java.util.Locale.setDefault(new java.util.Locale("ar", "", "")); | |
885 | ||
886 | // check to be sure... its GMT all right | |
887 | TimeZone *testdefault = TimeZone::createDefault(); | |
888 | UnicodeString testtimezone; | |
889 | testdefault->getID(testtimezone); | |
890 | if (testtimezone == "GMT") | |
891 | logln("Test timezone = " + testtimezone); | |
892 | else | |
893 | errln("Test timezone should be GMT, not " + testtimezone); | |
894 | ||
895 | UErrorCode status = U_ZERO_ERROR; | |
896 | // now try to use the default GMT time zone | |
897 | GregorianCalendar *greenwichcalendar = | |
898 | new GregorianCalendar(1997, 3, 4, 23, 0, status); | |
899 | failure(status, "new GregorianCalendar"); | |
900 | //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault()); | |
901 | //greenwichcalendar.set(1997, 3, 4, 23, 0); | |
902 | // try anything to set hour to 23:00 !!! | |
903 | greenwichcalendar->set(UCAL_HOUR_OF_DAY, 23); | |
904 | // get time | |
905 | UDate greenwichdate = greenwichcalendar->getTime(status); | |
906 | // format every way | |
907 | UnicodeString DATA [] = { | |
908 | UnicodeString("simple format: "), UnicodeString("04/04/97 23:00 GMT"), | |
909 | UnicodeString("MM/dd/yy HH:mm z"), | |
910 | UnicodeString("full format: "), UnicodeString("Friday, April 4, 1997 11:00:00 o'clock PM GMT"), | |
911 | UnicodeString("EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z"), | |
912 | UnicodeString("long format: "), UnicodeString("April 4, 1997 11:00:00 PM GMT"), | |
913 | UnicodeString("MMMM d, yyyy h:mm:ss a z"), | |
914 | UnicodeString("default format: "), UnicodeString("04-Apr-97 11:00:00 PM"), | |
915 | UnicodeString("dd-MMM-yy h:mm:ss a"), | |
916 | UnicodeString("short format: "), UnicodeString("4/4/97 11:00 PM"), | |
917 | UnicodeString("M/d/yy h:mm a") | |
918 | }; | |
919 | int32_t DATA_length = (int32_t)(sizeof(DATA) / sizeof(DATA[0])); | |
920 | ||
921 | for (int32_t i=0; i<DATA_length; i+=3) { | |
922 | DateFormat *fmt = new SimpleDateFormat(DATA[i+2], Locale::getEnglish(), status); | |
923 | if(failure(status, "new SimpleDateFormat")) break; | |
924 | fmt->setCalendar(*greenwichcalendar); | |
925 | UnicodeString result; | |
926 | result = fmt->format(greenwichdate, result); | |
927 | logln(DATA[i] + result); | |
928 | if (result != DATA[i+1]) | |
929 | errln("FAIL: Expected " + DATA[i+1] + ", got " + result); | |
930 | delete fmt; | |
931 | } | |
932 | //} | |
933 | //finally { | |
934 | TimeZone::adoptDefault(saveDefault); | |
935 | //} | |
936 | delete testdefault; | |
937 | delete greenwichcalendar; | |
938 | delete thedefault; | |
939 | ||
940 | ||
941 | } | |
942 | ||
943 | // ------------------------------------- | |
944 | ||
945 | /** | |
946 | * Test the formatting of dates in different locales. | |
947 | */ | |
948 | void | |
949 | DateFormatTest::TestLocaleDateFormat() // Bug 495 | |
950 | { | |
951 | UDate testDate = date(97, UCAL_SEPTEMBER, 15); | |
952 | DateFormat *dfFrench = DateFormat::createDateTimeInstance(DateFormat::FULL, | |
953 | DateFormat::FULL, Locale::getFrench()); | |
954 | DateFormat *dfUS = DateFormat::createDateTimeInstance(DateFormat::FULL, | |
955 | DateFormat::FULL, Locale::getUS()); | |
374ca955 A |
956 | UnicodeString expectedFRENCH ( "lundi 15 septembre 1997 00 h 00 HAP (\\u00C9UA)" ); |
957 | expectedFRENCH = expectedFRENCH.unescape(); | |
b75a7d8f A |
958 | //UnicodeString expectedUS ( "Monday, September 15, 1997 12:00:00 o'clock AM PDT" ); |
959 | UnicodeString expectedUS ( "Monday, September 15, 1997 12:00:00 AM PDT" ); | |
960 | logln((UnicodeString)"Date set to : " + dateToString(testDate)); | |
961 | UnicodeString out; | |
962 | dfFrench->format(testDate, out); | |
963 | logln((UnicodeString)"Date Formated with French Locale " + out); | |
964 | if (!(out == expectedFRENCH)) | |
965 | errln((UnicodeString)"FAIL: Expected " + expectedFRENCH); | |
966 | out.truncate(0); | |
967 | dfUS->format(testDate, out); | |
968 | logln((UnicodeString)"Date Formated with US Locale " + out); | |
969 | if (!(out == expectedUS)) | |
970 | errln((UnicodeString)"FAIL: Expected " + expectedUS); | |
971 | delete dfUS; | |
972 | delete dfFrench; | |
973 | } | |
974 | ||
975 | /** | |
976 | * Test DateFormat(Calendar) API | |
977 | */ | |
978 | void DateFormatTest::TestDateFormatCalendar() { | |
979 | DateFormat *date=0, *time=0, *full=0; | |
980 | Calendar *cal=0; | |
981 | UnicodeString str; | |
982 | ParsePosition pos; | |
983 | UDate when; | |
984 | UErrorCode ec = U_ZERO_ERROR; | |
985 | ||
986 | /* Create a formatter for date fields. */ | |
987 | date = DateFormat::createDateInstance(DateFormat::kShort, Locale::getUS()); | |
988 | if (date == NULL) { | |
989 | errln("FAIL: createDateInstance failed"); | |
990 | goto FAIL; | |
991 | } | |
992 | ||
993 | /* Create a formatter for time fields. */ | |
994 | time = DateFormat::createTimeInstance(DateFormat::kShort, Locale::getUS()); | |
995 | if (time == NULL) { | |
996 | errln("FAIL: createTimeInstance failed"); | |
997 | goto FAIL; | |
998 | } | |
999 | ||
1000 | /* Create a full format for output */ | |
1001 | full = DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, | |
1002 | Locale::getUS()); | |
1003 | if (full == NULL) { | |
1004 | errln("FAIL: createInstance failed"); | |
1005 | goto FAIL; | |
1006 | } | |
1007 | ||
1008 | /* Create a calendar */ | |
1009 | cal = Calendar::createInstance(Locale::getUS(), ec); | |
1010 | if (cal == NULL || U_FAILURE(ec)) { | |
1011 | errln((UnicodeString)"FAIL: Calendar::createInstance failed with " + | |
1012 | u_errorName(ec)); | |
1013 | goto FAIL; | |
1014 | } | |
1015 | ||
1016 | /* Parse the date */ | |
1017 | cal->clear(); | |
1018 | str = UnicodeString("4/5/2001", ""); | |
1019 | pos.setIndex(0); | |
1020 | date->parse(str, *cal, pos); | |
1021 | if (pos.getIndex() != str.length()) { | |
1022 | errln((UnicodeString)"FAIL: DateFormat::parse(4/5/2001) failed at " + | |
1023 | pos.getIndex()); | |
1024 | goto FAIL; | |
1025 | } | |
1026 | ||
1027 | /* Parse the time */ | |
1028 | str = UnicodeString("5:45 PM", ""); | |
1029 | pos.setIndex(0); | |
1030 | time->parse(str, *cal, pos); | |
1031 | if (pos.getIndex() != str.length()) { | |
1032 | errln((UnicodeString)"FAIL: DateFormat::parse(17:45) failed at " + | |
1033 | pos.getIndex()); | |
1034 | goto FAIL; | |
1035 | } | |
1036 | ||
1037 | /* Check result */ | |
1038 | when = cal->getTime(ec); | |
1039 | if (U_FAILURE(ec)) { | |
1040 | errln((UnicodeString)"FAIL: cal->getTime() failed with " + u_errorName(ec)); | |
1041 | goto FAIL; | |
1042 | } | |
1043 | str.truncate(0); | |
1044 | full->format(when, str); | |
1045 | // Thursday, April 5, 2001 5:45:00 PM PDT 986517900000 | |
1046 | if (when == 986517900000.0) { | |
1047 | logln("Ok: Parsed result: " + str); | |
1048 | } else { | |
1049 | errln("FAIL: Parsed result: " + str + ", exp 4/5/2001 5:45 PM"); | |
1050 | } | |
1051 | ||
1052 | FAIL: | |
1053 | delete date; | |
1054 | delete time; | |
1055 | delete full; | |
1056 | delete cal; | |
1057 | } | |
1058 | ||
1059 | /** | |
1060 | * Test DateFormat's parsing of space characters. See jitterbug 1916. | |
1061 | */ | |
1062 | void DateFormatTest::TestSpaceParsing() { | |
1063 | const char* DATA[] = { | |
1064 | "yyyy MM dd HH:mm:ss", | |
1065 | ||
1066 | // pattern, input, expected parse or NULL if expect parse failure | |
1067 | "MMMM d yy", " 04 05 06", NULL, // MMMM wants Apr/April | |
1068 | NULL, "04 05 06", NULL, | |
1069 | "MM d yy", " 04 05 06", "2006 04 05 00:00:00", | |
1070 | NULL, "04 05 06", "2006 04 05 00:00:00", | |
1071 | "MMMM d yy", " Apr 05 06", "2006 04 05 00:00:00", | |
1072 | NULL, "Apr 05 06", "2006 04 05 00:00:00", | |
1073 | }; | |
1074 | const int32_t DATA_len = sizeof(DATA)/sizeof(DATA[0]); | |
1075 | ||
1076 | expectParse(DATA, DATA_len, Locale("en")); | |
1077 | } | |
1078 | ||
1079 | /** | |
1080 | * Test handling of "HHmmss" pattern. | |
1081 | */ | |
1082 | void DateFormatTest::TestExactCountFormat() { | |
1083 | const char* DATA[] = { | |
1084 | "yyyy MM dd HH:mm:ss", | |
1085 | ||
1086 | // pattern, input, expected parse or NULL if expect parse failure | |
1087 | "HHmmss", "123456", "1970 01 01 12:34:56", | |
1088 | NULL, "12345", "1970 01 01 01:23:45", | |
1089 | NULL, "1234", NULL, | |
1090 | NULL, "00-05", NULL, | |
1091 | NULL, "12-34", NULL, | |
1092 | NULL, "00+05", NULL, | |
1093 | "ahhmm", "PM730", "1970 01 01 19:30:00", | |
1094 | }; | |
1095 | const int32_t DATA_len = sizeof(DATA)/sizeof(DATA[0]); | |
1096 | ||
1097 | expectParse(DATA, DATA_len, Locale("en")); | |
1098 | } | |
1099 | ||
1100 | /** | |
1101 | * Test handling of white space. | |
1102 | */ | |
1103 | void DateFormatTest::TestWhiteSpaceParsing() { | |
1104 | const char* DATA[] = { | |
1105 | "yyyy MM dd", | |
1106 | ||
1107 | // pattern, input, expected parse or null if expect parse failure | |
1108 | ||
1109 | // Pattern space run should parse input text space run | |
1110 | "MM d yy", " 04 01 03", "2003 04 01", | |
1111 | NULL, " 04 01 03 ", "2003 04 01", | |
1112 | }; | |
1113 | const int32_t DATA_len = sizeof(DATA)/sizeof(DATA[0]); | |
1114 | ||
1115 | expectParse(DATA, DATA_len, Locale("en")); | |
1116 | } | |
1117 | ||
374ca955 A |
1118 | |
1119 | void DateFormatTest::TestInvalidPattern() { | |
1120 | UErrorCode ec = U_ZERO_ERROR; | |
1121 | SimpleDateFormat f(UnicodeString("Yesterday"), ec); | |
1122 | UnicodeString out; | |
1123 | FieldPosition pos; | |
1124 | f.format((UDate)0, out, pos); | |
1125 | logln(out); | |
1126 | // The bug is that the call to format() will crash. By not | |
1127 | // crashing, the test passes. | |
1128 | } | |
1129 | ||
1130 | void DateFormatTest::TestGreekMay() { | |
1131 | UErrorCode ec = U_ZERO_ERROR; | |
1132 | UDate date = -9896080848000.0; | |
1133 | SimpleDateFormat fmt("EEEE, dd MMMM yyyy h:mm:ss a", Locale("el", "", ""), ec); | |
1134 | if (!assertSuccess("SimpleDateFormat::ct", ec)) return; | |
1135 | UnicodeString str; | |
1136 | fmt.format(date, str); | |
1137 | ParsePosition pos(0); | |
1138 | UDate d2 = fmt.parse(str, pos); | |
1139 | if (date != d2) { | |
1140 | errln("FAIL: unable to parse strings where case-folding changes length"); | |
1141 | } | |
1142 | } | |
1143 | ||
b75a7d8f A |
1144 | /** |
1145 | * Test parsing. Input is an array that starts with the following | |
1146 | * header: | |
1147 | * | |
1148 | * [0] = pattern string to parse [i+2] with | |
1149 | * | |
1150 | * followed by test cases, each of which is 3 array elements: | |
1151 | * | |
1152 | * [i] = pattern, or NULL to reuse prior pattern | |
1153 | * [i+1] = input string | |
1154 | * [i+2] = expected parse result (parsed with pattern [0]) | |
1155 | * | |
1156 | * If expect parse failure, then [i+2] should be NULL. | |
1157 | */ | |
1158 | void DateFormatTest::expectParse(const char** data, int32_t data_length, | |
1159 | const Locale& loc) { | |
1160 | const UDate FAIL = (UDate) -1; | |
1161 | const UnicodeString FAIL_STR("parse failure"); | |
1162 | int32_t i = 0; | |
1163 | ||
1164 | UErrorCode ec = U_ZERO_ERROR; | |
1165 | SimpleDateFormat fmt("", loc, ec); | |
1166 | SimpleDateFormat ref(data[i++], loc, ec); | |
1167 | SimpleDateFormat gotfmt("G yyyy MM dd HH:mm:ss z", loc, ec); | |
1168 | if (U_FAILURE(ec)) { | |
1169 | errln("FAIL: SimpleDateFormat constructor"); | |
1170 | return; | |
1171 | } | |
1172 | ||
1173 | const char* currentPat = NULL; | |
1174 | while (i<data_length) { | |
1175 | const char* pattern = data[i++]; | |
1176 | const char* input = data[i++]; | |
1177 | const char* expected = data[i++]; | |
1178 | ||
1179 | ec = U_ZERO_ERROR; | |
1180 | if (pattern != NULL) { | |
1181 | fmt.applyPattern(pattern); | |
1182 | currentPat = pattern; | |
1183 | } | |
1184 | UDate got = fmt.parse(input, ec); | |
1185 | UnicodeString gotstr(FAIL_STR); | |
1186 | if (U_FAILURE(ec)) { | |
1187 | got = FAIL; | |
1188 | } else { | |
1189 | gotstr.remove(); | |
1190 | gotfmt.format(got, gotstr); | |
1191 | } | |
1192 | ||
1193 | UErrorCode ec2 = U_ZERO_ERROR; | |
1194 | UDate exp = FAIL; | |
1195 | UnicodeString expstr(FAIL_STR); | |
1196 | if (expected != NULL) { | |
1197 | expstr = expected; | |
1198 | exp = ref.parse(expstr, ec2); | |
1199 | if (U_FAILURE(ec2)) { | |
1200 | // This only happens if expected is in wrong format -- | |
1201 | // should never happen once test is debugged. | |
1202 | errln("FAIL: Internal test error"); | |
1203 | return; | |
1204 | } | |
1205 | } | |
1206 | ||
1207 | if (got == exp) { | |
1208 | logln((UnicodeString)"Ok: " + input + " x " + | |
1209 | currentPat + " => " + gotstr); | |
1210 | } else { | |
1211 | errln((UnicodeString)"FAIL: " + input + " x " + | |
1212 | currentPat + " => " + gotstr + ", expected " + | |
1213 | expstr); | |
1214 | } | |
1215 | } | |
1216 | } | |
1217 | ||
374ca955 A |
1218 | /** |
1219 | * Test formatting and parsing. Input is an array that starts | |
1220 | * with the following header: | |
1221 | * | |
1222 | * [0] = pattern string to parse [i+2] with | |
1223 | * | |
1224 | * followed by test cases, each of which is 3 array elements: | |
1225 | * | |
1226 | * [i] = pattern, or null to reuse prior pattern | |
1227 | * [i+1] = control string, either "fp", "pf", or "F". | |
1228 | * [i+2..] = data strings | |
1229 | * | |
1230 | * The number of data strings depends on the control string. | |
1231 | * Examples: | |
1232 | * 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", | |
1233 | * 'f': Format date [i+2] (as parsed using pattern [0]) and expect string [i+3]. | |
1234 | * 'p': Parse string [i+3] and expect date [i+4]. | |
1235 | * | |
1236 | * 2. "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567" | |
1237 | * 'F': Format date [i+2] and expect string [i+3], | |
1238 | * then parse string [i+3] and expect date [i+2]. | |
1239 | * | |
1240 | * 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", | |
1241 | * 'p': Parse string [i+2] and expect date [i+3]. | |
1242 | * 'f': Format date [i+3] and expect string [i+4]. | |
1243 | */ | |
1244 | void DateFormatTest::expect(const char** data, int32_t data_length, | |
1245 | const Locale& loc) { | |
1246 | int32_t i = 0; | |
1247 | UErrorCode ec = U_ZERO_ERROR; | |
1248 | UnicodeString str, str2; | |
1249 | SimpleDateFormat fmt("", loc, ec); | |
1250 | SimpleDateFormat ref(data[i++], loc, ec); | |
1251 | SimpleDateFormat univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc, ec); | |
1252 | if (!assertSuccess("construct SimpleDateFormat", ec)) return; | |
1253 | ||
1254 | UnicodeString currentPat; | |
1255 | while (i<data_length) { | |
1256 | const char* pattern = data[i++]; | |
1257 | if (pattern != NULL) { | |
1258 | fmt.applyPattern(pattern); | |
1259 | currentPat = pattern; | |
1260 | } | |
1261 | ||
1262 | const char* control = data[i++]; | |
1263 | ||
1264 | if (uprv_strcmp(control, "fp") == 0) { | |
1265 | // 'f' | |
1266 | const char* datestr = data[i++]; | |
1267 | const char* string = data[i++]; | |
1268 | UDate date = ref.parse(datestr, ec); | |
1269 | if (!assertSuccess("parse", ec)) return; | |
1270 | assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")", | |
1271 | string, | |
1272 | fmt.format(date, str.remove())); | |
1273 | // 'p' | |
1274 | datestr = data[i++]; | |
1275 | date = ref.parse(datestr, ec); | |
1276 | if (!assertSuccess("parse", ec)) return; | |
1277 | UDate parsedate = fmt.parse(string, ec); | |
1278 | if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) { | |
1279 | assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", | |
1280 | univ.format(date, str.remove()), | |
1281 | univ.format(parsedate, str2.remove())); | |
1282 | } | |
1283 | } | |
1284 | ||
1285 | else if (uprv_strcmp(control, "pf") == 0) { | |
1286 | // 'p' | |
1287 | const char* string = data[i++]; | |
1288 | const char* datestr = data[i++]; | |
1289 | UDate date = ref.parse(datestr, ec); | |
1290 | if (!assertSuccess("parse", ec)) return; | |
1291 | UDate parsedate = fmt.parse(string, ec); | |
1292 | if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) { | |
1293 | assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", | |
1294 | univ.format(date, str.remove()), | |
1295 | univ.format(parsedate, str2.remove())); | |
1296 | } | |
1297 | // 'f' | |
1298 | string = data[i++]; | |
1299 | assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")", | |
1300 | string, | |
1301 | fmt.format(date, str.remove())); | |
1302 | } | |
1303 | ||
1304 | else if (uprv_strcmp(control, "F") == 0) { | |
1305 | const char* datestr = data[i++]; | |
1306 | const char* string = data[i++]; | |
1307 | UDate date = ref.parse(datestr, ec); | |
1308 | if (!assertSuccess("parse", ec)) return; | |
1309 | assertEquals((UnicodeString)"\"" + currentPat + "\".format(" + datestr + ")", | |
1310 | string, | |
1311 | fmt.format(date, str.remove())); | |
1312 | ||
1313 | UDate parsedate = fmt.parse(string, ec); | |
1314 | if (assertSuccess((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", ec)) { | |
1315 | assertEquals((UnicodeString)"\"" + currentPat + "\".parse(" + string + ")", | |
1316 | univ.format(date, str.remove()), | |
1317 | univ.format(parsedate, str2.remove())); | |
1318 | } | |
1319 | } | |
1320 | ||
1321 | else { | |
1322 | errln((UnicodeString)"FAIL: Invalid control string " + control); | |
1323 | return; | |
1324 | } | |
1325 | } | |
1326 | } | |
1327 | ||
b75a7d8f A |
1328 | #endif /* #if !UCONFIG_NO_FORMATTING */ |
1329 | ||
1330 | //eof |