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