]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/intltest/dtfmttst.cpp
ICU-6.2.13.tar.gz
[apple/icu.git] / icuSources / test / intltest / dtfmttst.cpp
CommitLineData
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
26void 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.
59void 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 */
160void
161DateFormatTest::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 */
175void
176DateFormatTest::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
203UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }
204
205UnicodeString&
206DateFormatTest::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 */
229static 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 */
235static 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
262static 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
268void 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 */
353void 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 */
373void
374DateFormatTest::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
390void
391DateFormatTest::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 */
431void
432DateFormatTest::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 */
458void
459DateFormatTest::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
477void
478DateFormatTest::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 */
506void
507DateFormatTest::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 */
543void
544DateFormatTest::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 */
574void
575DateFormatTest::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
591void
592DateFormatTest::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 */
619void
620DateFormatTest::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 */
638void
639DateFormatTest::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
691const 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
703const 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 */
724void
725DateFormatTest::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 */
805void
806DateFormatTest::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
820void
821DateFormatTest::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 */
842void
843DateFormatTest::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 */
876void
877DateFormatTest::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 */
948void
949DateFormatTest::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 */
978void 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 */
1062void 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 */
1082void 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 */
1103void 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
1119void 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
1130void 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 */
1158void 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 */
1244void 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