1 /********************************************************************
3 * Copyright (c) 1997-2006, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
7 #include "unicode/utypes.h"
9 #if !UCONFIG_NO_FORMATTING
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 "unicode/dtfmtsym.h"
21 #include "caltest.h" // for fieldName
27 #define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
29 #define ASSERT_OK(status) if(U_FAILURE(status)) {errln(#status " = %s", u_errorName(status)); return; }
31 //--------------------------------------------------------------------
32 // Time bomb - allows temporary behavior that expires at a given
34 //--------------------------------------------------------------------
35 static const UVersionInfo ICU_37
= {3,7,0,0};
37 // *****************************************************************************
38 // class DateFormatTest
39 // *****************************************************************************
41 void DateFormatTest::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
43 // if (exec) logln((UnicodeString)"TestSuite DateFormatTest");
45 TESTCASE(0,TestEquals
);
46 TESTCASE(1,TestTwoDigitYearDSTParse
);
47 TESTCASE(2,TestFieldPosition
);
48 TESTCASE(3,TestPartialParse994
);
49 TESTCASE(4,TestRunTogetherPattern985
);
50 TESTCASE(5,TestRunTogetherPattern917
);
51 TESTCASE(6,TestCzechMonths459
);
52 TESTCASE(7,TestLetterDPattern212
);
53 TESTCASE(8,TestDayOfYearPattern195
);
54 TESTCASE(9,TestQuotePattern161
);
55 TESTCASE(10,TestBadInput135
);
56 TESTCASE(11,TestBadInput135a
);
57 TESTCASE(12,TestTwoDigitYear
);
58 TESTCASE(13,TestDateFormatZone061
);
59 TESTCASE(14,TestDateFormatZone146
);
60 TESTCASE(15,TestLocaleDateFormat
);
61 TESTCASE(16,TestWallyWedel
);
62 TESTCASE(17,TestDateFormatCalendar
);
63 TESTCASE(18,TestSpaceParsing
);
64 TESTCASE(19,TestExactCountFormat
);
65 TESTCASE(20,TestWhiteSpaceParsing
);
66 TESTCASE(21,TestInvalidPattern
);
67 TESTCASE(22,TestGeneral
);
68 TESTCASE(23,TestGreekMay
);
69 TESTCASE(24,TestGenericTime
);
70 TESTCASE(25,TestGenericTimeZoneOrder
);
71 TESTCASE(26,TestTimeZoneStringsAPI
);
72 TESTCASE(27,TestHost
);
73 TESTCASE(28,TestEras
);
74 TESTCASE(29,TestNarrowNames
);
75 TESTCASE(30,TestStandAloneDays
);
76 TESTCASE(31,TestStandAloneMonths
);
77 TESTCASE(32,TestQuarters
);
78 default: name
= ""; break;
82 // Test written by Wally Wedel and emailed to me.
83 void DateFormatTest::TestWallyWedel()
85 UErrorCode status
= U_ZERO_ERROR
;
87 * Instantiate a TimeZone so we can get the ids.
89 TimeZone
*tz
= new SimpleTimeZone(7,"");
91 * Computational variables.
93 int32_t offset
, hours
, minutes
;
95 * Instantiate a SimpleDateFormat set up to produce a full time
98 SimpleDateFormat
*sdf
= new SimpleDateFormat((UnicodeString
)"zzzz", status
);
100 * A String array for the time zone ids.
103 StringEnumeration
* ids
= TimeZone::createEnumeration();
104 ids_length
= ids
->count(status
);
106 * How many ids do we have?
108 logln("Time Zone IDs size: %d", ids_length
);
110 * Column headings (sort of)
112 logln("Ordinal ID offset(h:m) name");
114 * Loop through the tzs.
116 UDate today
= Calendar::getNow();
117 Calendar
*cal
= Calendar::createInstance(status
);
118 for (int32_t i
= 0; i
< ids_length
; i
++) {
119 // logln(i + " " + ids[i]);
120 const UnicodeString
* id
= ids
->snext(status
);
121 TimeZone
*ttz
= TimeZone::createTimeZone(*id
);
122 // offset = ttz.getRawOffset();
123 cal
->setTimeZone(*ttz
);
124 cal
->setTime(today
, status
);
125 offset
= cal
->get(UCAL_ZONE_OFFSET
, status
) + cal
->get(UCAL_DST_OFFSET
, status
);
126 // logln(i + " " + ids[i] + " offset " + offset);
127 const char* sign
= "+";
132 hours
= offset
/3600000;
133 minutes
= (offset%3600000
)/60000;
134 UnicodeString dstOffset
= (UnicodeString
)"" + sign
+ (hours
< 10 ? "0" : "") +
135 (int32_t)hours
+ ":" + (minutes
< 10 ? "0" : "") + (int32_t)minutes
;
137 * Instantiate a date so we can display the time zone name.
139 sdf
->setTimeZone(*ttz
);
143 UnicodeString fmtOffset
;
144 FieldPosition
pos(0);
145 sdf
->format(today
,fmtOffset
, pos
);
146 // UnicodeString fmtOffset = tzS.toString();
147 UnicodeString
*fmtDstOffset
= 0;
148 if (fmtOffset
.startsWith("GMT"))
150 //fmtDstOffset = fmtOffset->substring(3);
151 fmtDstOffset
= new UnicodeString();
152 fmtOffset
.extract(3, fmtOffset
.length(), *fmtDstOffset
);
157 UBool ok
= fmtDstOffset
== 0 || *fmtDstOffset
== dstOffset
;
160 logln(UnicodeString() + i
+ " " + *id
+ " " + dstOffset
+
162 (fmtDstOffset
!= 0 ? " ok" : " ?"));
166 errln(UnicodeString() + i
+ " " + *id
+ " " + dstOffset
+
167 " " + fmtOffset
+ " *** FAIL ***");
173 // delete ids; // TODO: BAD API
179 // -------------------------------------
185 DateFormatTest::TestEquals()
187 DateFormat
* fmtA
= DateFormat::createDateTimeInstance(DateFormat::MEDIUM
, DateFormat::FULL
);
188 DateFormat
* fmtB
= DateFormat::createDateTimeInstance(DateFormat::MEDIUM
, DateFormat::FULL
);
189 if ( fmtA
== NULL
|| fmtB
== NULL
){
190 dataerrln("Error calling DateFormat::createDateTimeInstance");
196 if (!(*fmtA
== *fmtB
)) errln((UnicodeString
)"FAIL");
200 TimeZone
* test
= TimeZone::createTimeZone("PDT");
204 // -------------------------------------
207 * Test the parsing of 2-digit years.
210 DateFormatTest::TestTwoDigitYearDSTParse(void)
212 UErrorCode status
= U_ZERO_ERROR
;
213 SimpleDateFormat
* fullFmt
= new SimpleDateFormat((UnicodeString
)"EEE MMM dd HH:mm:ss.SSS zzz yyyy G", status
);
214 SimpleDateFormat
*fmt
= new SimpleDateFormat((UnicodeString
)"dd-MMM-yy h:mm:ss 'o''clock' a z", Locale::getEnglish(), status
);
215 //DateFormat* fmt = DateFormat::createDateTimeInstance(DateFormat::MEDIUM, DateFormat::FULL, Locale::ENGLISH);
216 UnicodeString
* s
= new UnicodeString("03-Apr-04 2:20:47 o'clock AM PST", "");
217 TimeZone
* defaultTZ
= TimeZone::createDefault();
218 TimeZone
* PST
= TimeZone::createTimeZone("PST");
219 int32_t defaultOffset
= defaultTZ
->getRawOffset();
220 int32_t PSTOffset
= PST
->getRawOffset();
221 int32_t hour
= 2 + (defaultOffset
- PSTOffset
) / (60*60*1000);
222 // hour is the expected hour of day, in units of seconds
223 hour
= ((hour
< 0) ? hour
+ 24 : hour
) * 60*60;
227 if(U_FAILURE(status
)) {
228 errln("Could not set up test. exitting");
232 UDate d
= fmt
->parse(*s
, status
);
233 logln(*s
+ " P> " + ((DateFormat
*)fullFmt
)->format(d
, str
));
234 int32_t y
, m
, day
, hr
, min
, sec
;
235 dateToFields(d
, y
, m
, day
, hr
, min
, sec
);
236 hour
+= defaultTZ
->inDaylightTime(d
, status
) ? 1 : 0;
239 errln((UnicodeString
)"FAIL: Should parse to hour " + hour
+ " but got " + hr
);
241 if (U_FAILURE(status
))
242 errln((UnicodeString
)"FAIL: " + (int32_t)status
);
251 // -------------------------------------
253 UChar
toHexString(int32_t i
) { return (UChar
)(i
+ (i
< 10 ? 0x30 : (0x41 - 10))); }
256 DateFormatTest::escape(UnicodeString
& s
)
259 for (int32_t i
=0; i
<s
.length(); ++i
)
261 UChar c
= s
[(int32_t)i
];
262 if (c
<= (UChar
)0x7F) buf
+= c
;
264 buf
+= (UChar
)0x5c; buf
+= (UChar
)0x55;
265 buf
+= toHexString((c
& 0xF000) >> 12);
266 buf
+= toHexString((c
& 0x0F00) >> 8);
267 buf
+= toHexString((c
& 0x00F0) >> 4);
268 buf
+= toHexString(c
& 0x000F);
274 // -------------------------------------
277 * This MUST be kept in sync with DateFormatSymbols.gPatternChars.
279 static const char* PATTERN_CHARS
= "GyMdkHmsSEDFwWahKzYeugAZvcLQq";
282 * A list of the names of all the fields in DateFormat.
283 * This MUST be kept in sync with DateFormat.
285 static const char* DATEFORMAT_FIELD_NAMES
[] = {
290 "HOUR_OF_DAY1_FIELD",
291 "HOUR_OF_DAY0_FIELD",
297 "DAY_OF_WEEK_IN_MONTH_FIELD",
298 "WEEK_OF_YEAR_FIELD",
299 "WEEK_OF_MONTH_FIELD",
306 "EXTENDED_YEAR_FIELD",
308 "MILLISECONDS_IN_DAY_FIELD",
309 "TIMEZONE_RFC_FIELD",
310 "GENERIC_TIMEZONE_FIELD",
311 "STAND_ALONE_DAY_FIELD",
312 "STAND_ALONE_MONTH_FIELD",
314 "STAND_ALONE_QUARTER_FIELD"
317 static const int32_t DATEFORMAT_FIELD_NAMES_LENGTH
=
318 sizeof(DATEFORMAT_FIELD_NAMES
) / sizeof(DATEFORMAT_FIELD_NAMES
[0]);
321 * Verify that returned field position indices are correct.
323 void DateFormatTest::TestFieldPosition() {
324 UErrorCode ec
= U_ZERO_ERROR
;
329 DateFormatSymbols
rootSyms(Locale(""), ec
);
330 assertSuccess("DateFormatSymbols", ec
);
332 // local pattern chars not accurate when CLDR 1.4 data
333 // first introduced...
334 if(isICUVersionAtLeast(ICU_37
)) {
335 assertEquals("patternChars", PATTERN_CHARS
, rootSyms
.getLocalPatternChars(buf
));
338 assertEquals("patternChars", PATTERN_CHARS
, DateFormatSymbols::getPatternUChars());
339 assertTrue("DATEFORMAT_FIELD_NAMES", DATEFORMAT_FIELD_NAMES_LENGTH
== UDAT_FIELD_COUNT
);
340 assertTrue("Data", UDAT_FIELD_COUNT
== uprv_strlen(PATTERN_CHARS
));
342 // Create test formatters
343 const int32_t COUNT
= 4;
344 DateFormat
* dateFormats
[COUNT
];
345 dateFormats
[0] = DateFormat::createDateTimeInstance(DateFormat::kFull
, DateFormat::kFull
, Locale::getUS());
346 dateFormats
[1] = DateFormat::createDateTimeInstance(DateFormat::kFull
, DateFormat::kFull
, Locale::getFrance());
347 // Make the pattern "G y M d..."
348 buf
.remove().append(PATTERN_CHARS
);
349 for (j
=buf
.length()-1; j
>=0; --j
) buf
.insert(j
, (UChar
)32/*' '*/);
350 dateFormats
[2] = new SimpleDateFormat(buf
, Locale::getUS(), ec
);
351 // Make the pattern "GGGG yyyy MMMM dddd..."
352 for (j
=buf
.length()-1; j
>=0; j
-=2) {
353 for (i
=0; i
<3; ++i
) {
354 buf
.insert(j
, buf
.charAt(j
));
357 dateFormats
[3] = new SimpleDateFormat(buf
, Locale::getUS(), ec
);
359 errln(UnicodeString("Could not create SimpleDateFormat object for locale en_US. Error: " )+ UnicodeString(u_errorName(ec
)));
362 UDate aug13
= 871508052513.0;
364 // Expected output field values for above DateFormats on aug13
365 // Fields are given in order of DateFormat field number
366 const char* EXPECTED
[] = {
367 "", "1997", "August", "13", "", "", "34", "12", "",
368 "Wednesday", "", "", "", "", "PM", "2", "", "", "", "", "", "", "", "", "PT", "", "", "", "",
370 "", "1997", "ao\\u00FBt", "13", "", "14", "34", "", "",
371 "mercredi", "", "", "", "", "", "", "", "HAP (\\u00C9UA)", "", "", "", "", "", "", "", "", "", "", "",
373 "AD", "1997", "8", "13", "14", "14", "34", "12", "5",
374 "Wed", "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4", "1997", "2450674", "52452513", "-0700", "PT", "4", "8", "3", "3",
376 "Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130",
377 "Wednesday", "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "0004", "1997", "2450674", "52452513", "-0700",
378 "Pacific Time", "Wednesday", "August", "3rd quarter", "3rd quarter"
381 const int32_t EXPECTED_LENGTH
= sizeof(EXPECTED
)/sizeof(EXPECTED
[0]);
383 assertTrue("data size", EXPECTED_LENGTH
== COUNT
* UDAT_FIELD_COUNT
);
385 TimeZone
* PT
= TimeZone::createTimeZone("America/Los_Angeles");
386 for (j
= 0, exp
= 0; j
< COUNT
; ++j
) {
388 DateFormat
* df
= dateFormats
[j
];
389 df
->setTimeZone(*PT
);
390 if (df
->getDynamicClassID() == SimpleDateFormat::getStaticClassID()) {
391 logln(" Pattern = " + ((SimpleDateFormat
*) df
)->toPattern(buf
.remove()));
393 logln(" Pattern = ? (not a SimpleDateFormat)");
395 logln((UnicodeString
)" Result = " + df
->format(aug13
, buf
.remove()));
397 for (i
= 0; i
< UDAT_FIELD_COUNT
; ++i
, ++exp
) {
398 FieldPosition
pos(i
);
400 df
->format(aug13
, buf
, pos
);
402 buf
.extractBetween(pos
.getBeginIndex(), pos
.getEndIndex(), field
);
403 assertEquals((UnicodeString
)"field #" + i
+ " " + DATEFORMAT_FIELD_NAMES
[i
],
404 ctou(EXPECTED
[exp
]), field
);
408 for (i
=0; i
<COUNT
; ++i
) {
409 delete dateFormats
[i
];
414 // -------------------------------------
417 * General parse/format tests. Add test cases as needed.
419 void DateFormatTest::TestGeneral() {
420 const char* DATA
[] = {
421 "yyyy MM dd HH:mm:ss.SSS",
423 // Milliseconds are left-justified, since they format as fractions of a second
424 "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",
425 "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",
426 "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567",
427 "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",
429 expect(DATA
, ARRAY_SIZE(DATA
), Locale("en", "", ""));
432 // -------------------------------------
435 * Verify that strings which contain incomplete specifications are parsed
436 * correctly. In some instances, this means not being parsed at all, and
437 * returning an appropriate error.
440 DateFormatTest::TestPartialParse994()
442 UErrorCode status
= U_ZERO_ERROR
;
443 SimpleDateFormat
* f
= new SimpleDateFormat(status
);
446 tryPat994(f
, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", date(97, 1 - 1, 17, 10, 11, 42));
447 tryPat994(f
, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null
);
448 tryPat994(f
, "yy/MM/dd HH:mm:ss", "97/01/17 10", null
);
449 tryPat994(f
, "yy/MM/dd HH:mm:ss", "97/01/17 ", null
);
450 tryPat994(f
, "yy/MM/dd HH:mm:ss", "97/01/17", null
);
451 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: UErrorCode received during test: " + (int32_t)status
);
455 // -------------------------------------
458 DateFormatTest::tryPat994(SimpleDateFormat
* format
, const char* pat
, const char* str
, UDate expected
)
460 UErrorCode status
= U_ZERO_ERROR
;
462 logln(UnicodeString("Pattern \"") + pat
+ "\" String \"" + str
+ "\"");
464 format
->applyPattern(pat
);
465 UDate date
= format
->parse(str
, status
);
466 if (U_FAILURE(status
) || date
== null
)
468 logln((UnicodeString
)"ParseException: " + (int32_t)status
);
469 if (expected
!= null
) errln((UnicodeString
)"FAIL: Expected " + dateToString(expected
));
474 ((DateFormat
*)format
)->format(date
, f
);
475 logln(UnicodeString(" parse(") + str
+ ") -> " + dateToString(date
));
476 logln((UnicodeString
)" format -> " + f
);
477 if (expected
== null
||
478 !(date
== expected
)) errln((UnicodeString
)"FAIL: Expected null");//" + expected);
479 if (!(f
== str
)) errln(UnicodeString("FAIL: Expected ") + str
);
482 //catch(ParseException e) {
483 // logln((UnicodeString)"ParseException: " + e.getMessage());
484 // if (expected != null) errln((UnicodeString)"FAIL: Expected " + dateToString(expected));
486 //catch(Exception e) {
487 // errln((UnicodeString)"*** Exception:");
488 // e.printStackTrace();
492 // -------------------------------------
495 * Verify the behavior of patterns in which digits for different fields run together
496 * without intervening separators.
499 DateFormatTest::TestRunTogetherPattern985()
501 UErrorCode status
= U_ZERO_ERROR
;
502 UnicodeString
format("yyyyMMddHHmmssSSS");
503 UnicodeString now
, then
;
505 SimpleDateFormat
*formatter
= new SimpleDateFormat(format
, status
);
507 UDate date1
= Calendar::getNow();
508 ((DateFormat
*)formatter
)->format(date1
, now
);
510 ParsePosition
pos(0);
511 UDate date2
= formatter
->parse(now
, pos
);
512 if (date2
== 0) then
= "Parse stopped at " + pos
.getIndex();
513 else ((DateFormat
*)formatter
)->format(date2
, then
);
515 if (!(date2
== date1
)) errln((UnicodeString
)"FAIL");
517 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: UErrorCode received during test: " + (int32_t)status
);
520 // -------------------------------------
523 * Verify the behavior of patterns in which digits for different fields run together
524 * without intervening separators.
527 DateFormatTest::TestRunTogetherPattern917()
529 UErrorCode status
= U_ZERO_ERROR
;
530 SimpleDateFormat
* fmt
;
531 UnicodeString myDate
;
532 fmt
= new SimpleDateFormat((UnicodeString
)"yyyy/MM/dd", status
);
534 myDate
= "1997/02/03";
535 testIt917(fmt
, myDate
, date(97, 2 - 1, 3));
537 fmt
= new SimpleDateFormat((UnicodeString
)"yyyyMMdd", status
);
539 testIt917(fmt
, myDate
, date(97, 3 - 1, 4));
541 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: UErrorCode received during test: " + (int32_t)status
);
544 // -------------------------------------
547 DateFormatTest::testIt917(SimpleDateFormat
* fmt
, UnicodeString
& str
, UDate expected
)
549 UErrorCode status
= U_ZERO_ERROR
;
550 UnicodeString pattern
;
551 logln((UnicodeString
)"pattern=" + fmt
->toPattern(pattern
) + " string=" + str
);
554 ((Format
*)fmt
)->parseObject(str
, o
, status
);
556 if (U_FAILURE(status
)) return;
557 //catch(ParseException e) {
558 // e.printStackTrace();
561 logln((UnicodeString
)"Parsed object: " + dateToString(o
.getDate()));
562 if (!(o
.getDate() == expected
)) errln((UnicodeString
)"FAIL: Expected " + dateToString(expected
));
563 UnicodeString formatted
; ((Format
*)fmt
)->format(o
, formatted
, status
);
564 logln((UnicodeString
)"Formatted string: " + formatted
);
565 if (!(formatted
== str
)) errln((UnicodeString
)"FAIL: Expected " + str
);
566 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: UErrorCode received during test: " + (int32_t)status
);
569 // -------------------------------------
572 * Verify the handling of Czech June and July, which have the unique attribute that
573 * one is a proper prefix substring of the other.
576 DateFormatTest::TestCzechMonths459()
578 UErrorCode status
= U_ZERO_ERROR
;
579 DateFormat
* fmt
= DateFormat::createDateInstance(DateFormat::FULL
, Locale("cs", "", ""));
581 dataerrln("Error calling DateFormat::createDateInstance()");
585 UnicodeString pattern
;
586 logln((UnicodeString
)"Pattern " + ((SimpleDateFormat
*) fmt
)->toPattern(pattern
));
587 UDate june
= date(97, UCAL_JUNE
, 15);
588 UDate july
= date(97, UCAL_JULY
, 15);
589 UnicodeString juneStr
; fmt
->format(june
, juneStr
);
590 UnicodeString julyStr
; fmt
->format(july
, julyStr
);
592 logln((UnicodeString
)"format(June 15 1997) = " + juneStr
);
593 UDate d
= fmt
->parse(juneStr
, status
);
594 UnicodeString s
; fmt
->format(d
, s
);
595 int32_t month
,yr
,day
,hr
,min
,sec
; dateToFields(d
,yr
,month
,day
,hr
,min
,sec
);
596 logln((UnicodeString
)" -> parse -> " + s
+ " (month = " + month
+ ")");
597 if (month
!= UCAL_JUNE
) errln((UnicodeString
)"FAIL: Month should be June");
598 logln((UnicodeString
)"format(July 15 1997) = " + julyStr
);
599 d
= fmt
->parse(julyStr
, status
);
601 dateToFields(d
,yr
,month
,day
,hr
,min
,sec
);
602 logln((UnicodeString
)" -> parse -> " + s
+ " (month = " + month
+ ")");
603 if (month
!= UCAL_JULY
) errln((UnicodeString
)"FAIL: Month should be July");
605 //catch(ParseException e) {
606 if (U_FAILURE(status
))
607 errln((UnicodeString
)"Exception: " + (int32_t)status
);
612 // -------------------------------------
615 * Test the handling of 'D' in patterns.
618 DateFormatTest::TestLetterDPattern212()
620 UErrorCode status
= U_ZERO_ERROR
;
621 UnicodeString
dateString("1995-040.05:01:29");
622 UnicodeString
bigD("yyyy-DDD.hh:mm:ss");
623 UnicodeString
littleD("yyyy-ddd.hh:mm:ss");
624 UDate expLittleD
= date(95, 0, 1, 5, 1, 29);
625 UDate expBigD
= expLittleD
+ 39 * 24 * 3600000.0;
626 expLittleD
= expBigD
; // Expect the same, with default lenient parsing
627 logln((UnicodeString
)"dateString= " + dateString
);
628 SimpleDateFormat
*formatter
= new SimpleDateFormat(bigD
, status
);
630 ParsePosition
pos(0);
631 UDate myDate
= formatter
->parse(dateString
, pos
);
632 logln((UnicodeString
)"Using " + bigD
+ " -> " + myDate
);
633 if (myDate
!= expBigD
) errln((UnicodeString
)"FAIL: Expected " + dateToString(expBigD
));
635 formatter
= new SimpleDateFormat(littleD
, status
);
637 pos
= ParsePosition(0);
638 myDate
= formatter
->parse(dateString
, pos
);
639 logln((UnicodeString
)"Using " + littleD
+ " -> " + dateToString(myDate
));
640 if (myDate
!= expLittleD
) errln((UnicodeString
)"FAIL: Expected " + dateToString(expLittleD
));
642 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: UErrorCode received during test: " + (int32_t)status
);
645 // -------------------------------------
648 * Test the day of year pattern.
651 DateFormatTest::TestDayOfYearPattern195()
653 UErrorCode status
= U_ZERO_ERROR
;
654 UDate today
= Calendar::getNow();
655 int32_t year
,month
,day
,hour
,min
,sec
; dateToFields(today
,year
,month
,day
,hour
,min
,sec
);
656 UDate expected
= date(year
, month
, day
);
657 logln((UnicodeString
)"Test Date: " + dateToString(today
));
658 SimpleDateFormat
* sdf
= (SimpleDateFormat
*)DateFormat::createDateInstance();
660 dataerrln("Error calling DateFormat::createDateInstance()");
663 tryPattern(*sdf
, today
, 0, expected
);
664 tryPattern(*sdf
, today
, "G yyyy DDD", expected
);
666 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: UErrorCode received during test: " + (int32_t)status
);
669 // -------------------------------------
672 DateFormatTest::tryPattern(SimpleDateFormat
& sdf
, UDate d
, const char* pattern
, UDate expected
)
674 UErrorCode status
= U_ZERO_ERROR
;
675 if (pattern
!= 0) sdf
.applyPattern(pattern
);
676 UnicodeString thePat
;
677 logln((UnicodeString
)"pattern: " + sdf
.toPattern(thePat
));
678 UnicodeString formatResult
; (*(DateFormat
*)&sdf
).format(d
, formatResult
);
679 logln((UnicodeString
)" format -> " + formatResult
);
681 UDate d2
= sdf
.parse(formatResult
, status
);
682 logln((UnicodeString
)" parse(" + formatResult
+ ") -> " + dateToString(d2
));
683 if (d2
!= expected
) errln((UnicodeString
)"FAIL: Expected " + dateToString(expected
));
684 UnicodeString format2
; (*(DateFormat
*)&sdf
).format(d2
, format2
);
685 logln((UnicodeString
)" format -> " + format2
);
686 if (!(formatResult
== format2
)) errln((UnicodeString
)"FAIL: Round trip drift");
688 //catch(Exception e) {
689 if (U_FAILURE(status
))
690 errln((UnicodeString
)"Error: " + (int32_t)status
);
694 // -------------------------------------
697 * Test the handling of single quotes in patterns.
700 DateFormatTest::TestQuotePattern161()
702 UErrorCode status
= U_ZERO_ERROR
;
703 SimpleDateFormat
* formatter
= new SimpleDateFormat((UnicodeString
)"MM/dd/yyyy 'at' hh:mm:ss a zzz", status
);
705 UDate currentTime_1
= date(97, UCAL_AUGUST
, 13, 10, 42, 28);
706 UnicodeString dateString
; ((DateFormat
*)formatter
)->format(currentTime_1
, dateString
);
707 UnicodeString
exp("08/13/1997 at 10:42:28 AM ");
708 logln((UnicodeString
)"format(" + dateToString(currentTime_1
) + ") = " + dateString
);
709 if (0 != dateString
.compareBetween(0, exp
.length(), exp
, 0, exp
.length())) errln((UnicodeString
)"FAIL: Expected " + exp
);
711 if (U_FAILURE(status
)) errln((UnicodeString
)"FAIL: UErrorCode received during test: " + (int32_t)status
);
714 // -------------------------------------
717 * Verify the correct behavior when handling invalid input strings.
720 DateFormatTest::TestBadInput135()
722 UErrorCode status
= U_ZERO_ERROR
;
723 DateFormat::EStyle looks
[] = {
724 DateFormat::SHORT
, DateFormat::MEDIUM
, DateFormat::LONG
, DateFormat::FULL
726 int32_t looks_length
= (int32_t)(sizeof(looks
) / sizeof(looks
[0]));
727 const char* strings
[] = {
728 "Mar 15", "Mar 15 1997", "asdf", "3/1/97 1:23:", "3/1/00 1:23:45 AM"
730 int32_t strings_length
= (int32_t)(sizeof(strings
) / sizeof(strings
[0]));
731 DateFormat
*full
= DateFormat::createDateTimeInstance(DateFormat::LONG
, DateFormat::LONG
);
733 errln("could not create date time instance");
736 UnicodeString
expected("March 1, 2000 1:23:45 AM ");
737 for (int32_t i
= 0; i
< strings_length
;++i
) {
738 const char* text
= strings
[i
];
739 for (int32_t j
= 0; j
< looks_length
;++j
) {
740 DateFormat::EStyle dateLook
= looks
[j
];
741 for (int32_t k
= 0; k
< looks_length
;++k
) {
742 DateFormat::EStyle timeLook
= looks
[k
];
743 DateFormat
*df
= DateFormat::createDateTimeInstance(dateLook
, timeLook
);
745 dataerrln("Error calling DateFormat::createDateTimeInstance()");
748 UnicodeString prefix
= UnicodeString(text
) + ", " + dateLook
+ "/" + timeLook
+ ": ";
750 UDate when
= df
->parse(text
, status
);
751 if (when
== 0 && U_SUCCESS(status
)) {
752 errln(prefix
+ "SHOULD NOT HAPPEN: parse returned 0.");
755 if (U_SUCCESS(status
))
757 UnicodeString format
;
758 full
->format(when
, format
);
759 logln(prefix
+ "OK: " + format
);
760 if (0!=format
.compareBetween(0, expected
.length(), expected
, 0, expected
.length()))
761 errln((UnicodeString
)"FAIL: Expected " + expected
+ " got " + format
);
764 //catch(ParseException e) {
766 status
= U_ZERO_ERROR
;
768 //catch(StringIndexOutOfBoundsException e) {
769 // errln(prefix + "SHOULD NOT HAPPEN: " + (int)status);
776 if (U_FAILURE(status
))
777 errln((UnicodeString
)"FAIL: UErrorCode received during test: " + (int32_t)status
);
780 const char* DateFormatTest::parseFormats
[] = {
789 "h:mm a MMMM d, yyyy"
792 const char* DateFormatTest::inputStrings
[] = {
793 "bogus string", 0, 0, 0, 0, 0, 0, 0, 0, 0,
794 "April 1, 1997", "April 1, 1997", 0, 0, 0, 0, 0, "April 1", 0, 0,
795 "Jan 1, 1970", "January 1, 1970", 0, 0, 0, 0, 0, "January 1", 0, 0,
796 "Jan 1 2037", 0, "January 1 2037", 0, 0, 0, 0, "January 1", 0, 0,
797 "1/1/70", 0, 0, "1/1/70", 0, 0, 0, 0, "0001", 0,
798 "5 May 1997", 0, 0, 0, 0, "5 May 1997", "5 May", 0, "0005", 0,
799 "16 May", 0, 0, 0, 0, 0, "16 May", 0, "0016", 0,
800 "April 30", 0, 0, 0, 0, 0, 0, "April 30", 0, 0,
801 "1998", 0, 0, 0, 0, 0, 0, 0, "1998", 0,
802 "1", 0, 0, 0, 0, 0, 0, 0, "0001", 0,
803 "3:00 pm Jan 1, 1997", 0, 0, 0, 0, 0, 0, 0, "0003", "3:00 PM January 1, 1997",
806 // -------------------------------------
809 * Verify the correct behavior when parsing an array of inputs against an
810 * array of patterns, with known results. The results are encoded after
811 * the input strings in each row.
814 DateFormatTest::TestBadInput135a()
816 UErrorCode status
= U_ZERO_ERROR
;
817 SimpleDateFormat
* dateParse
= new SimpleDateFormat(status
);
818 if(U_FAILURE(status
)) {
819 errln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status
));
825 const uint32_t PF_LENGTH
= (int32_t)(sizeof(parseFormats
)/sizeof(parseFormats
[0]));
826 const uint32_t INPUT_LENGTH
= (int32_t)(sizeof(inputStrings
)/sizeof(inputStrings
[0]));
828 dateParse
->applyPattern("d MMMM, yyyy");
829 dateParse
->adoptTimeZone(TimeZone::createDefault());
831 UnicodeString thePat
;
832 logln(UnicodeString("Trying to parse \"") + s
+ "\" with " + dateParse
->toPattern(thePat
));
834 date
= dateParse
->parse(s
, status
);
835 if (U_SUCCESS(status
))
836 errln((UnicodeString
)"FAIL: Expected exception during parse");
838 //catch(Exception ex) {
840 logln((UnicodeString
)"Exception during parse: " + (int32_t)status
);
841 status
= U_ZERO_ERROR
;
843 for (uint32_t i
= 0; i
< INPUT_LENGTH
; i
+= (PF_LENGTH
+ 1)) {
844 ParsePosition
parsePosition(0);
845 UnicodeString
s( inputStrings
[i
]);
846 for (uint32_t index
= 0; index
< PF_LENGTH
;++index
) {
847 const char* expected
= inputStrings
[i
+ 1 + index
];
848 dateParse
->applyPattern(parseFormats
[index
]);
849 dateParse
->adoptTimeZone(TimeZone::createDefault());
851 parsePosition
.setIndex(0);
852 date
= dateParse
->parse(s
, parsePosition
);
853 if (parsePosition
.getIndex() != 0) {
854 UnicodeString s1
, s2
;
855 s
.extract(0, parsePosition
.getIndex(), s1
);
856 s
.extract(parsePosition
.getIndex(), s
.length(), s2
);
858 errln((UnicodeString
)"ERROR: null result fmt=\"" +
859 parseFormats
[index
] +
860 "\" pos=" + parsePosition
.getIndex() + " " +
864 UnicodeString result
;
865 ((DateFormat
*)dateParse
)->format(date
, result
);
866 logln((UnicodeString
)"Parsed \"" + s
+ "\" using \"" + dateParse
->toPattern(thePat
) + "\" to: " + result
);
868 errln((UnicodeString
)"FAIL: Expected parse failure");
869 else if (!(result
== expected
))
870 errln(UnicodeString("FAIL: Expected ") + expected
);
873 else if (expected
!= 0) {
874 errln(UnicodeString("FAIL: Expected ") + expected
+ " from \"" +
875 s
+ "\" with \"" + dateParse
->toPattern(thePat
) + "\"");
878 //catch(Exception ex) {
879 if (U_FAILURE(status
))
880 errln((UnicodeString
)"An exception was thrown during parse: " + (int32_t)status
);
885 if (U_FAILURE(status
))
886 errln((UnicodeString
)"FAIL: UErrorCode received during test: " + (int32_t)status
);
889 // -------------------------------------
892 * Test the parsing of two-digit years.
895 DateFormatTest::TestTwoDigitYear()
897 UErrorCode ec
= U_ZERO_ERROR
;
898 SimpleDateFormat
fmt("dd/MM/yy", Locale::getUK(), ec
);
900 errln("FAIL: SimpleDateFormat constructor");
903 parse2DigitYear(fmt
, "5/6/17", date(117, UCAL_JUNE
, 5));
904 parse2DigitYear(fmt
, "4/6/34", date(34, UCAL_JUNE
, 4));
907 // -------------------------------------
910 DateFormatTest::parse2DigitYear(DateFormat
& fmt
, const char* str
, UDate expected
)
912 UErrorCode status
= U_ZERO_ERROR
;
914 UDate d
= fmt
.parse(str
, status
);
915 UnicodeString thePat
;
916 logln(UnicodeString("Parsing \"") + str
+ "\" with " + ((SimpleDateFormat
*)&fmt
)->toPattern(thePat
) +
917 " => " + dateToString(d
));
918 if (d
!= expected
) errln((UnicodeString
)"FAIL: Expected " + expected
);
920 //catch(ParseException e) {
921 if (U_FAILURE(status
))
922 errln((UnicodeString
)"FAIL: Got exception");
926 // -------------------------------------
929 * Test the formatting of time zones.
932 DateFormatTest::TestDateFormatZone061()
934 UErrorCode status
= U_ZERO_ERROR
;
936 DateFormat
*formatter
;
937 date
= 859248000000.0;
938 logln((UnicodeString
)"Date 1997/3/25 00:00 GMT: " + date
);
939 formatter
= new SimpleDateFormat((UnicodeString
)"dd-MMM-yyyyy HH:mm", Locale::getUK(), status
);
940 if(U_FAILURE(status
)) {
941 errln("Failed creating SimpleDateFormat with %s. Quitting test", u_errorName(status
));
945 formatter
->adoptTimeZone(TimeZone::createTimeZone("GMT"));
946 UnicodeString temp
; formatter
->format(date
, temp
);
947 logln((UnicodeString
)"Formatted in GMT to: " + temp
);
949 UDate tempDate
= formatter
->parse(temp
, status
);
950 logln((UnicodeString
)"Parsed to: " + dateToString(tempDate
));
951 if (tempDate
!= date
) errln((UnicodeString
)"FAIL: Expected " + dateToString(date
));
953 //catch(Throwable t) {
954 if (U_FAILURE(status
))
955 errln((UnicodeString
)"Date Formatter throws: " + (int32_t)status
);
960 // -------------------------------------
963 * Test the formatting of time zones.
966 DateFormatTest::TestDateFormatZone146()
968 TimeZone
*saveDefault
= TimeZone::createDefault();
971 TimeZone
*thedefault
= TimeZone::createTimeZone("GMT");
972 TimeZone::setDefault(*thedefault
);
973 // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
975 // check to be sure... its GMT all right
976 TimeZone
*testdefault
= TimeZone::createDefault();
977 UnicodeString testtimezone
;
978 testdefault
->getID(testtimezone
);
979 if (testtimezone
== "GMT")
980 logln("Test timezone = " + testtimezone
);
982 errln("Test timezone should be GMT, not " + testtimezone
);
984 UErrorCode status
= U_ZERO_ERROR
;
985 // now try to use the default GMT time zone
986 GregorianCalendar
*greenwichcalendar
=
987 new GregorianCalendar(1997, 3, 4, 23, 0, status
);
988 failure(status
, "new GregorianCalendar");
989 //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
990 //greenwichcalendar.set(1997, 3, 4, 23, 0);
991 // try anything to set hour to 23:00 !!!
992 greenwichcalendar
->set(UCAL_HOUR_OF_DAY
, 23);
994 UDate greenwichdate
= greenwichcalendar
->getTime(status
);
996 UnicodeString DATA
[] = {
997 UnicodeString("simple format: "), UnicodeString("04/04/97 23:00 GMT+00:00"),
998 UnicodeString("MM/dd/yy HH:mm z"),
999 UnicodeString("full format: "), UnicodeString("Friday, April 4, 1997 11:00:00 o'clock PM GMT+00:00"),
1000 UnicodeString("EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z"),
1001 UnicodeString("long format: "), UnicodeString("April 4, 1997 11:00:00 PM GMT+00:00"),
1002 UnicodeString("MMMM d, yyyy h:mm:ss a z"),
1003 UnicodeString("default format: "), UnicodeString("04-Apr-97 11:00:00 PM"),
1004 UnicodeString("dd-MMM-yy h:mm:ss a"),
1005 UnicodeString("short format: "), UnicodeString("4/4/97 11:00 PM"),
1006 UnicodeString("M/d/yy h:mm a")
1008 int32_t DATA_length
= (int32_t)(sizeof(DATA
) / sizeof(DATA
[0]));
1010 for (int32_t i
=0; i
<DATA_length
; i
+=3) {
1011 DateFormat
*fmt
= new SimpleDateFormat(DATA
[i
+2], Locale::getEnglish(), status
);
1012 if(failure(status
, "new SimpleDateFormat")) break;
1013 fmt
->setCalendar(*greenwichcalendar
);
1014 UnicodeString result
;
1015 result
= fmt
->format(greenwichdate
, result
);
1016 logln(DATA
[i
] + result
);
1017 if (result
!= DATA
[i
+1])
1018 errln("FAIL: Expected " + DATA
[i
+1] + ", got " + result
);
1023 TimeZone::adoptDefault(saveDefault
);
1026 delete greenwichcalendar
;
1032 // -------------------------------------
1035 * Test the formatting of dates in different locales.
1038 DateFormatTest::TestLocaleDateFormat() // Bug 495
1040 UDate testDate
= date(97, UCAL_SEPTEMBER
, 15);
1041 DateFormat
*dfFrench
= DateFormat::createDateTimeInstance(DateFormat::FULL
,
1042 DateFormat::FULL
, Locale::getFrench());
1043 DateFormat
*dfUS
= DateFormat::createDateTimeInstance(DateFormat::FULL
,
1044 DateFormat::FULL
, Locale::getUS());
1045 UnicodeString
expectedFRENCH ( "lundi 15 septembre 1997 00 h 00 HAP (\\u00C9UA)" );
1046 expectedFRENCH
= expectedFRENCH
.unescape();
1047 //UnicodeString expectedUS ( "Monday, September 15, 1997 12:00:00 o'clock AM PDT" );
1048 UnicodeString
expectedUS ( "Monday, September 15, 1997 12:00:00 AM PT" );
1049 logln((UnicodeString
)"Date set to : " + dateToString(testDate
));
1051 if (dfUS
== NULL
|| dfFrench
== NULL
){
1052 dataerrln("Error calling DateFormat::createDateTimeInstance)");
1058 dfFrench
->format(testDate
, out
);
1059 logln((UnicodeString
)"Date Formated with French Locale " + out
);
1060 if (!(out
== expectedFRENCH
))
1061 errln((UnicodeString
)"FAIL: Expected " + expectedFRENCH
);
1063 dfUS
->format(testDate
, out
);
1064 logln((UnicodeString
)"Date Formated with US Locale " + out
);
1065 if (!(out
== expectedUS
))
1066 errln((UnicodeString
)"FAIL: Expected " + expectedUS
);
1072 * Test DateFormat(Calendar) API
1074 void DateFormatTest::TestDateFormatCalendar() {
1075 DateFormat
*date
=0, *time
=0, *full
=0;
1080 UErrorCode ec
= U_ZERO_ERROR
;
1082 /* Create a formatter for date fields. */
1083 date
= DateFormat::createDateInstance(DateFormat::kShort
, Locale::getUS());
1085 errln("FAIL: createDateInstance failed");
1089 /* Create a formatter for time fields. */
1090 time
= DateFormat::createTimeInstance(DateFormat::kShort
, Locale::getUS());
1092 errln("FAIL: createTimeInstance failed");
1096 /* Create a full format for output */
1097 full
= DateFormat::createDateTimeInstance(DateFormat::kFull
, DateFormat::kFull
,
1100 errln("FAIL: createInstance failed");
1104 /* Create a calendar */
1105 cal
= Calendar::createInstance(Locale::getUS(), ec
);
1106 if (cal
== NULL
|| U_FAILURE(ec
)) {
1107 errln((UnicodeString
)"FAIL: Calendar::createInstance failed with " +
1112 /* Parse the date */
1114 str
= UnicodeString("4/5/2001", "");
1116 date
->parse(str
, *cal
, pos
);
1117 if (pos
.getIndex() != str
.length()) {
1118 errln((UnicodeString
)"FAIL: DateFormat::parse(4/5/2001) failed at " +
1123 /* Parse the time */
1124 str
= UnicodeString("5:45 PM", "");
1126 time
->parse(str
, *cal
, pos
);
1127 if (pos
.getIndex() != str
.length()) {
1128 errln((UnicodeString
)"FAIL: DateFormat::parse(17:45) failed at " +
1134 when
= cal
->getTime(ec
);
1135 if (U_FAILURE(ec
)) {
1136 errln((UnicodeString
)"FAIL: cal->getTime() failed with " + u_errorName(ec
));
1140 full
->format(when
, str
);
1141 // Thursday, April 5, 2001 5:45:00 PM PDT 986517900000
1142 if (when
== 986517900000.0) {
1143 logln("Ok: Parsed result: " + str
);
1145 errln("FAIL: Parsed result: " + str
+ ", exp 4/5/2001 5:45 PM");
1156 * Test DateFormat's parsing of space characters. See jitterbug 1916.
1158 void DateFormatTest::TestSpaceParsing() {
1159 const char* DATA
[] = {
1160 "yyyy MM dd HH:mm:ss",
1162 // pattern, input, expected parse or NULL if expect parse failure
1163 "MMMM d yy", " 04 05 06", NULL
, // MMMM wants Apr/April
1164 NULL
, "04 05 06", NULL
,
1165 "MM d yy", " 04 05 06", "2006 04 05 00:00:00",
1166 NULL
, "04 05 06", "2006 04 05 00:00:00",
1167 "MMMM d yy", " Apr 05 06", "2006 04 05 00:00:00",
1168 NULL
, "Apr 05 06", "2006 04 05 00:00:00",
1170 const int32_t DATA_len
= sizeof(DATA
)/sizeof(DATA
[0]);
1172 expectParse(DATA
, DATA_len
, Locale("en"));
1176 * Test handling of "HHmmss" pattern.
1178 void DateFormatTest::TestExactCountFormat() {
1179 const char* DATA
[] = {
1180 "yyyy MM dd HH:mm:ss",
1182 // pattern, input, expected parse or NULL if expect parse failure
1183 "HHmmss", "123456", "1970 01 01 12:34:56",
1184 NULL
, "12345", "1970 01 01 01:23:45",
1186 NULL
, "00-05", NULL
,
1187 NULL
, "12-34", NULL
,
1188 NULL
, "00+05", NULL
,
1189 "ahhmm", "PM730", "1970 01 01 19:30:00",
1191 const int32_t DATA_len
= sizeof(DATA
)/sizeof(DATA
[0]);
1193 expectParse(DATA
, DATA_len
, Locale("en"));
1197 * Test handling of white space.
1199 void DateFormatTest::TestWhiteSpaceParsing() {
1200 const char* DATA
[] = {
1203 // pattern, input, expected parse or null if expect parse failure
1205 // Pattern space run should parse input text space run
1206 "MM d yy", " 04 01 03", "2003 04 01",
1207 NULL
, " 04 01 03 ", "2003 04 01",
1209 const int32_t DATA_len
= sizeof(DATA
)/sizeof(DATA
[0]);
1211 expectParse(DATA
, DATA_len
, Locale("en"));
1215 void DateFormatTest::TestInvalidPattern() {
1216 UErrorCode ec
= U_ZERO_ERROR
;
1217 SimpleDateFormat
f(UnicodeString("Yesterday"), ec
);
1221 f
.format((UDate
)0, out
, pos
);
1223 // The bug is that the call to format() will crash. By not
1224 // crashing, the test passes.
1227 void DateFormatTest::TestGreekMay() {
1228 UErrorCode ec
= U_ZERO_ERROR
;
1229 UDate date
= -9896080848000.0;
1230 SimpleDateFormat
fmt("EEEE, dd MMMM yyyy h:mm:ss a", Locale("el", "", ""), ec
);
1231 if (!assertSuccess("SimpleDateFormat::ct", ec
)) return;
1233 fmt
.format(date
, str
);
1234 ParsePosition
pos(0);
1235 UDate d2
= fmt
.parse(str
, pos
);
1237 errln("FAIL: unable to parse strings where case-folding changes length");
1241 void DateFormatTest::TestStandAloneMonths()
1243 const char *EN_DATA
[] = {
1244 "yyyy MM dd HH:mm:ss",
1246 "yyyy LLLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 March 10 16:36:31", "2004 03 10 16:36:31",
1247 "yyyy LLL dd H:mm:ss", "fp", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31",
1248 "yyyy LLLL dd H:mm:ss", "F", "2004 03 10 16:36:31", "2004 March 10 16:36:31",
1249 "yyyy LLL dd H:mm:ss", "pf", "2004 Mar 10 16:36:31", "2004 03 10 16:36:31", "2004 Mar 10 16:36:31",
1251 "LLLL", "fp", "1970 01 01 0:00:00", "January", "1970 01 01 0:00:00",
1252 "LLLL", "fp", "1970 02 01 0:00:00", "February", "1970 02 01 0:00:00",
1253 "LLLL", "fp", "1970 03 01 0:00:00", "March", "1970 03 01 0:00:00",
1254 "LLLL", "fp", "1970 04 01 0:00:00", "April", "1970 04 01 0:00:00",
1255 "LLLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1256 "LLLL", "fp", "1970 06 01 0:00:00", "June", "1970 06 01 0:00:00",
1257 "LLLL", "fp", "1970 07 01 0:00:00", "July", "1970 07 01 0:00:00",
1258 "LLLL", "fp", "1970 08 01 0:00:00", "August", "1970 08 01 0:00:00",
1259 "LLLL", "fp", "1970 09 01 0:00:00", "September", "1970 09 01 0:00:00",
1260 "LLLL", "fp", "1970 10 01 0:00:00", "October", "1970 10 01 0:00:00",
1261 "LLLL", "fp", "1970 11 01 0:00:00", "November", "1970 11 01 0:00:00",
1262 "LLLL", "fp", "1970 12 01 0:00:00", "December", "1970 12 01 0:00:00",
1264 "LLL", "fp", "1970 01 01 0:00:00", "Jan", "1970 01 01 0:00:00",
1265 "LLL", "fp", "1970 02 01 0:00:00", "Feb", "1970 02 01 0:00:00",
1266 "LLL", "fp", "1970 03 01 0:00:00", "Mar", "1970 03 01 0:00:00",
1267 "LLL", "fp", "1970 04 01 0:00:00", "Apr", "1970 04 01 0:00:00",
1268 "LLL", "fp", "1970 05 01 0:00:00", "May", "1970 05 01 0:00:00",
1269 "LLL", "fp", "1970 06 01 0:00:00", "Jun", "1970 06 01 0:00:00",
1270 "LLL", "fp", "1970 07 01 0:00:00", "Jul", "1970 07 01 0:00:00",
1271 "LLL", "fp", "1970 08 01 0:00:00", "Aug", "1970 08 01 0:00:00",
1272 "LLL", "fp", "1970 09 01 0:00:00", "Sep", "1970 09 01 0:00:00",
1273 "LLL", "fp", "1970 10 01 0:00:00", "Oct", "1970 10 01 0:00:00",
1274 "LLL", "fp", "1970 11 01 0:00:00", "Nov", "1970 11 01 0:00:00",
1275 "LLL", "fp", "1970 12 01 0:00:00", "Dec", "1970 12 01 0:00:00",
1278 const char *CS_DATA
[] = {
1279 "yyyy MM dd HH:mm:ss",
1281 "yyyy LLLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 duben 10 16:36:31", "2004 04 10 16:36:31",
1282 "yyyy MMMM dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31",
1283 "yyyy LLL dd H:mm:ss", "fp", "2004 04 10 16:36:31", "2004 4. 10 16:36:31", "2004 04 10 16:36:31",
1284 "yyyy LLLL dd H:mm:ss", "F", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1285 "yyyy MMMM dd H:mm:ss", "F", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1286 "yyyy LLLL dd H:mm:ss", "pf", "2004 duben 10 16:36:31", "2004 04 10 16:36:31", "2004 duben 10 16:36:31",
1287 "yyyy MMMM dd H:mm:ss", "pf", "2004 dubna 10 16:36:31", "2004 04 10 16:36:31", "2004 dubna 10 16:36:31",
1289 "LLLL", "fp", "1970 01 01 0:00:00", "leden", "1970 01 01 0:00:00",
1290 "LLLL", "fp", "1970 02 01 0:00:00", "\\u00FAnor", "1970 02 01 0:00:00",
1291 "LLLL", "fp", "1970 03 01 0:00:00", "b\\u0159ezen", "1970 03 01 0:00:00",
1292 "LLLL", "fp", "1970 04 01 0:00:00", "duben", "1970 04 01 0:00:00",
1293 "LLLL", "fp", "1970 05 01 0:00:00", "kv\\u011Bten", "1970 05 01 0:00:00",
1294 "LLLL", "fp", "1970 06 01 0:00:00", "\\u010Derven", "1970 06 01 0:00:00",
1295 "LLLL", "fp", "1970 07 01 0:00:00", "\\u010Dervenec", "1970 07 01 0:00:00",
1296 "LLLL", "fp", "1970 08 01 0:00:00", "srpen", "1970 08 01 0:00:00",
1297 "LLLL", "fp", "1970 09 01 0:00:00", "z\\u00E1\\u0159\\u00ED", "1970 09 01 0:00:00",
1298 "LLLL", "fp", "1970 10 01 0:00:00", "\\u0159\\u00EDjen", "1970 10 01 0:00:00",
1299 "LLLL", "fp", "1970 11 01 0:00:00", "listopad", "1970 11 01 0:00:00",
1300 "LLLL", "fp", "1970 12 01 0:00:00", "prosinec", "1970 12 01 0:00:00",
1302 "LLL", "fp", "1970 01 01 0:00:00", "1.", "1970 01 01 0:00:00",
1303 "LLL", "fp", "1970 02 01 0:00:00", "2.", "1970 02 01 0:00:00",
1304 "LLL", "fp", "1970 03 01 0:00:00", "3.", "1970 03 01 0:00:00",
1305 "LLL", "fp", "1970 04 01 0:00:00", "4.", "1970 04 01 0:00:00",
1306 "LLL", "fp", "1970 05 01 0:00:00", "5.", "1970 05 01 0:00:00",
1307 "LLL", "fp", "1970 06 01 0:00:00", "6.", "1970 06 01 0:00:00",
1308 "LLL", "fp", "1970 07 01 0:00:00", "7.", "1970 07 01 0:00:00",
1309 "LLL", "fp", "1970 08 01 0:00:00", "8.", "1970 08 01 0:00:00",
1310 "LLL", "fp", "1970 09 01 0:00:00", "9.", "1970 09 01 0:00:00",
1311 "LLL", "fp", "1970 10 01 0:00:00", "10.", "1970 10 01 0:00:00",
1312 "LLL", "fp", "1970 11 01 0:00:00", "11.", "1970 11 01 0:00:00",
1313 "LLL", "fp", "1970 12 01 0:00:00", "12.", "1970 12 01 0:00:00",
1316 expect(EN_DATA
, ARRAY_SIZE(EN_DATA
), Locale("en", "", ""));
1317 expect(CS_DATA
, ARRAY_SIZE(CS_DATA
), Locale("cs", "", ""));
1320 void DateFormatTest::TestStandAloneDays()
1322 const char *EN_DATA
[] = {
1323 "yyyy MM dd HH:mm:ss",
1325 "cccc", "fp", "1970 01 04 0:00:00", "Sunday", "1970 01 04 0:00:00",
1326 "cccc", "fp", "1970 01 05 0:00:00", "Monday", "1970 01 05 0:00:00",
1327 "cccc", "fp", "1970 01 06 0:00:00", "Tuesday", "1970 01 06 0:00:00",
1328 "cccc", "fp", "1970 01 07 0:00:00", "Wednesday", "1970 01 07 0:00:00",
1329 "cccc", "fp", "1970 01 01 0:00:00", "Thursday", "1970 01 01 0:00:00",
1330 "cccc", "fp", "1970 01 02 0:00:00", "Friday", "1970 01 02 0:00:00",
1331 "cccc", "fp", "1970 01 03 0:00:00", "Saturday", "1970 01 03 0:00:00",
1333 "ccc", "fp", "1970 01 04 0:00:00", "Sun", "1970 01 04 0:00:00",
1334 "ccc", "fp", "1970 01 05 0:00:00", "Mon", "1970 01 05 0:00:00",
1335 "ccc", "fp", "1970 01 06 0:00:00", "Tue", "1970 01 06 0:00:00",
1336 "ccc", "fp", "1970 01 07 0:00:00", "Wed", "1970 01 07 0:00:00",
1337 "ccc", "fp", "1970 01 01 0:00:00", "Thu", "1970 01 01 0:00:00",
1338 "ccc", "fp", "1970 01 02 0:00:00", "Fri", "1970 01 02 0:00:00",
1339 "ccc", "fp", "1970 01 03 0:00:00", "Sat", "1970 01 03 0:00:00",
1342 const char *CS_DATA
[] = {
1343 "yyyy MM dd HH:mm:ss",
1345 "cccc", "fp", "1970 01 04 0:00:00", "ned\\u011Ble", "1970 01 04 0:00:00",
1346 "cccc", "fp", "1970 01 05 0:00:00", "pond\\u011Bl\\u00ED", "1970 01 05 0:00:00",
1347 "cccc", "fp", "1970 01 06 0:00:00", "\\u00FAter\\u00FD", "1970 01 06 0:00:00",
1348 "cccc", "fp", "1970 01 07 0:00:00", "st\\u0159eda", "1970 01 07 0:00:00",
1349 "cccc", "fp", "1970 01 01 0:00:00", "\\u010Dtvrtek", "1970 01 01 0:00:00",
1350 "cccc", "fp", "1970 01 02 0:00:00", "p\\u00E1tek", "1970 01 02 0:00:00",
1351 "cccc", "fp", "1970 01 03 0:00:00", "sobota", "1970 01 03 0:00:00",
1353 "ccc", "fp", "1970 01 04 0:00:00", "ne", "1970 01 04 0:00:00",
1354 "ccc", "fp", "1970 01 05 0:00:00", "po", "1970 01 05 0:00:00",
1355 "ccc", "fp", "1970 01 06 0:00:00", "\\u00FAt", "1970 01 06 0:00:00",
1356 "ccc", "fp", "1970 01 07 0:00:00", "st", "1970 01 07 0:00:00",
1357 "ccc", "fp", "1970 01 01 0:00:00", "\\u010Dt", "1970 01 01 0:00:00",
1358 "ccc", "fp", "1970 01 02 0:00:00", "p\\u00E1", "1970 01 02 0:00:00",
1359 "ccc", "fp", "1970 01 03 0:00:00", "so", "1970 01 03 0:00:00",
1362 expect(EN_DATA
, ARRAY_SIZE(EN_DATA
), Locale("en", "", ""));
1363 expect(CS_DATA
, ARRAY_SIZE(CS_DATA
), Locale("cs", "", ""));
1366 void DateFormatTest::TestNarrowNames()
1368 const char *EN_DATA
[] = {
1369 "yyyy MM dd HH:mm:ss",
1371 "yyyy MMMMM dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1372 "yyyy LLLLL dd H:mm:ss", "2004 03 10 16:36:31", "2004 M 10 16:36:31",
1374 "MMMMM", "1970 01 01 0:00:00", "J",
1375 "MMMMM", "1970 02 01 0:00:00", "F",
1376 "MMMMM", "1970 03 01 0:00:00", "M",
1377 "MMMMM", "1970 04 01 0:00:00", "A",
1378 "MMMMM", "1970 05 01 0:00:00", "M",
1379 "MMMMM", "1970 06 01 0:00:00", "J",
1380 "MMMMM", "1970 07 01 0:00:00", "J",
1381 "MMMMM", "1970 08 01 0:00:00", "A",
1382 "MMMMM", "1970 09 01 0:00:00", "S",
1383 "MMMMM", "1970 10 01 0:00:00", "O",
1384 "MMMMM", "1970 11 01 0:00:00", "N",
1385 "MMMMM", "1970 12 01 0:00:00", "D",
1387 "LLLLL", "1970 01 01 0:00:00", "J",
1388 "LLLLL", "1970 02 01 0:00:00", "F",
1389 "LLLLL", "1970 03 01 0:00:00", "M",
1390 "LLLLL", "1970 04 01 0:00:00", "A",
1391 "LLLLL", "1970 05 01 0:00:00", "M",
1392 "LLLLL", "1970 06 01 0:00:00", "J",
1393 "LLLLL", "1970 07 01 0:00:00", "J",
1394 "LLLLL", "1970 08 01 0:00:00", "A",
1395 "LLLLL", "1970 09 01 0:00:00", "S",
1396 "LLLLL", "1970 10 01 0:00:00", "O",
1397 "LLLLL", "1970 11 01 0:00:00", "N",
1398 "LLLLL", "1970 12 01 0:00:00", "D",
1400 "EEEEE", "1970 01 04 0:00:00", "S",
1401 "EEEEE", "1970 01 05 0:00:00", "M",
1402 "EEEEE", "1970 01 06 0:00:00", "T",
1403 "EEEEE", "1970 01 07 0:00:00", "W",
1404 "EEEEE", "1970 01 01 0:00:00", "T",
1405 "EEEEE", "1970 01 02 0:00:00", "F",
1406 "EEEEE", "1970 01 03 0:00:00", "S",
1408 "ccccc", "1970 01 04 0:00:00", "S",
1409 "ccccc", "1970 01 05 0:00:00", "M",
1410 "ccccc", "1970 01 06 0:00:00", "T",
1411 "ccccc", "1970 01 07 0:00:00", "W",
1412 "ccccc", "1970 01 01 0:00:00", "T",
1413 "ccccc", "1970 01 02 0:00:00", "F",
1414 "ccccc", "1970 01 03 0:00:00", "S",
1417 const char *CS_DATA
[] = {
1418 "yyyy MM dd HH:mm:ss",
1420 "yyyy LLLLL dd H:mm:ss", "2004 04 10 16:36:31", "2004 d 10 16:36:31",
1421 "yyyy MMMMM dd H:mm:ss", "2004 04 10 16:36:31", "2004 d 10 16:36:31",
1423 "MMMMM", "1970 01 01 0:00:00", "l",
1424 "MMMMM", "1970 02 01 0:00:00", "\\u00FA",
1425 "MMMMM", "1970 03 01 0:00:00", "b",
1426 "MMMMM", "1970 04 01 0:00:00", "d",
1427 "MMMMM", "1970 05 01 0:00:00", "k",
1428 "MMMMM", "1970 06 01 0:00:00", "\\u010D",
1429 "MMMMM", "1970 07 01 0:00:00", "\\u010D",
1430 "MMMMM", "1970 08 01 0:00:00", "s",
1431 "MMMMM", "1970 09 01 0:00:00", "z",
1432 "MMMMM", "1970 10 01 0:00:00", "\\u0159",
1433 "MMMMM", "1970 11 01 0:00:00", "l",
1434 "MMMMM", "1970 12 01 0:00:00", "p",
1436 "LLLLL", "1970 01 01 0:00:00", "l",
1437 "LLLLL", "1970 02 01 0:00:00", "\\u00FA",
1438 "LLLLL", "1970 03 01 0:00:00", "b",
1439 "LLLLL", "1970 04 01 0:00:00", "d",
1440 "LLLLL", "1970 05 01 0:00:00", "k",
1441 "LLLLL", "1970 06 01 0:00:00", "\\u010D",
1442 "LLLLL", "1970 07 01 0:00:00", "\\u010D",
1443 "LLLLL", "1970 08 01 0:00:00", "s",
1444 "LLLLL", "1970 09 01 0:00:00", "z",
1445 "LLLLL", "1970 10 01 0:00:00", "\\u0159",
1446 "LLLLL", "1970 11 01 0:00:00", "l",
1447 "LLLLL", "1970 12 01 0:00:00", "p",
1449 "EEEEE", "1970 01 04 0:00:00", "N",
1450 "EEEEE", "1970 01 05 0:00:00", "P",
1451 "EEEEE", "1970 01 06 0:00:00", "\\u00DA",
1452 "EEEEE", "1970 01 07 0:00:00", "S",
1453 "EEEEE", "1970 01 01 0:00:00", "\\u010C",
1454 "EEEEE", "1970 01 02 0:00:00", "P",
1455 "EEEEE", "1970 01 03 0:00:00", "S",
1457 "ccccc", "1970 01 04 0:00:00", "N",
1458 "ccccc", "1970 01 05 0:00:00", "P",
1459 "ccccc", "1970 01 06 0:00:00", "\\u00DA",
1460 "ccccc", "1970 01 07 0:00:00", "S",
1461 "ccccc", "1970 01 01 0:00:00", "\\u010C",
1462 "ccccc", "1970 01 02 0:00:00", "P",
1463 "ccccc", "1970 01 03 0:00:00", "S",
1466 expectFormat(EN_DATA
, ARRAY_SIZE(EN_DATA
), Locale("en", "", ""));
1467 expectFormat(CS_DATA
, ARRAY_SIZE(CS_DATA
), Locale("cs", "", ""));
1470 void DateFormatTest::TestEras()
1472 const char *EN_DATA
[] = {
1475 "MMMM dd yyyy G", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1476 "MMMM dd yyyy GG", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1477 "MMMM dd yyyy GGG", "fp", "1951 07 17", "July 17 1951 AD", "1951 07 17",
1478 "MMMM dd yyyy GGGG", "fp", "1951 07 17", "July 17 1951 Anno Domini", "1951 07 17",
1480 "MMMM dd yyyy G", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1481 "MMMM dd yyyy GG", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1482 "MMMM dd yyyy GGG", "fp", "-438 07 17", "July 17 0439 BC", "-438 07 17",
1483 "MMMM dd yyyy GGGG", "fp", "-438 07 17", "July 17 0439 Before Christ", "-438 07 17",
1486 expect(EN_DATA
, ARRAY_SIZE(EN_DATA
), Locale("en", "", ""));
1489 void DateFormatTest::TestQuarters()
1491 const char *EN_DATA
[] = {
1494 "Q", "fp", "1970 01 01", "1", "1970 01 01",
1495 "QQ", "fp", "1970 04 01", "02", "1970 04 01",
1496 "QQQ", "fp", "1970 07 01", "Q3", "1970 07 01",
1497 "QQQQ", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1499 "q", "fp", "1970 01 01", "1", "1970 01 01",
1500 "qq", "fp", "1970 04 01", "02", "1970 04 01",
1501 "qqq", "fp", "1970 07 01", "Q3", "1970 07 01",
1502 "qqqq", "fp", "1970 10 01", "4th quarter", "1970 10 01",
1505 expect(EN_DATA
, ARRAY_SIZE(EN_DATA
), Locale("en", "", ""));
1509 * Test parsing. Input is an array that starts with the following
1512 * [0] = pattern string to parse [i+2] with
1514 * followed by test cases, each of which is 3 array elements:
1516 * [i] = pattern, or NULL to reuse prior pattern
1517 * [i+1] = input string
1518 * [i+2] = expected parse result (parsed with pattern [0])
1520 * If expect parse failure, then [i+2] should be NULL.
1522 void DateFormatTest::expectParse(const char** data
, int32_t data_length
,
1523 const Locale
& loc
) {
1524 const UDate FAIL
= (UDate
) -1;
1525 const UnicodeString
FAIL_STR("parse failure");
1528 UErrorCode ec
= U_ZERO_ERROR
;
1529 SimpleDateFormat
fmt("", loc
, ec
);
1530 SimpleDateFormat
ref(data
[i
++], loc
, ec
);
1531 SimpleDateFormat
gotfmt("G yyyy MM dd HH:mm:ss z", loc
, ec
);
1532 if (U_FAILURE(ec
)) {
1533 errln("FAIL: SimpleDateFormat constructor");
1537 const char* currentPat
= NULL
;
1538 while (i
<data_length
) {
1539 const char* pattern
= data
[i
++];
1540 const char* input
= data
[i
++];
1541 const char* expected
= data
[i
++];
1544 if (pattern
!= NULL
) {
1545 fmt
.applyPattern(pattern
);
1546 currentPat
= pattern
;
1548 UDate got
= fmt
.parse(input
, ec
);
1549 UnicodeString
gotstr(FAIL_STR
);
1550 if (U_FAILURE(ec
)) {
1554 gotfmt
.format(got
, gotstr
);
1557 UErrorCode ec2
= U_ZERO_ERROR
;
1559 UnicodeString
expstr(FAIL_STR
);
1560 if (expected
!= NULL
) {
1562 exp
= ref
.parse(expstr
, ec2
);
1563 if (U_FAILURE(ec2
)) {
1564 // This only happens if expected is in wrong format --
1565 // should never happen once test is debugged.
1566 errln("FAIL: Internal test error");
1572 logln((UnicodeString
)"Ok: " + input
+ " x " +
1573 currentPat
+ " => " + gotstr
);
1575 errln((UnicodeString
)"FAIL: " + input
+ " x " +
1576 currentPat
+ " => " + gotstr
+ ", expected " +
1583 * Test formatting and parsing. Input is an array that starts
1584 * with the following header:
1586 * [0] = pattern string to parse [i+2] with
1588 * followed by test cases, each of which is 3 array elements:
1590 * [i] = pattern, or null to reuse prior pattern
1591 * [i+1] = control string, either "fp", "pf", or "F".
1592 * [i+2..] = data strings
1594 * The number of data strings depends on the control string.
1596 * 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",
1597 * 'f': Format date [i+2] (as parsed using pattern [0]) and expect string [i+3].
1598 * 'p': Parse string [i+3] and expect date [i+4].
1600 * 2. "y/M/d H:mm:ss.SSS", "F", "2004 03 10 16:36:31.567", "2004/3/10 16:36:31.567"
1601 * 'F': Format date [i+2] and expect string [i+3],
1602 * then parse string [i+3] and expect date [i+2].
1604 * 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",
1605 * 'p': Parse string [i+2] and expect date [i+3].
1606 * 'f': Format date [i+3] and expect string [i+4].
1608 void DateFormatTest::expect(const char** data
, int32_t data_length
,
1609 const Locale
& loc
) {
1611 UErrorCode ec
= U_ZERO_ERROR
;
1612 UnicodeString str
, str2
;
1613 SimpleDateFormat
fmt("", loc
, ec
);
1614 SimpleDateFormat
ref(data
[i
++], loc
, ec
);
1615 SimpleDateFormat
univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc
, ec
);
1616 if (!assertSuccess("construct SimpleDateFormat", ec
)) return;
1618 UnicodeString currentPat
;
1619 while (i
<data_length
) {
1620 const char* pattern
= data
[i
++];
1621 if (pattern
!= NULL
) {
1622 fmt
.applyPattern(pattern
);
1623 currentPat
= pattern
;
1626 const char* control
= data
[i
++];
1628 if (uprv_strcmp(control
, "fp") == 0) {
1630 const char* datestr
= data
[i
++];
1631 const char* string
= data
[i
++];
1632 UDate date
= ref
.parse(ctou(datestr
), ec
);
1633 if (!assertSuccess("parse", ec
)) return;
1634 assertEquals((UnicodeString
)"\"" + currentPat
+ "\".format(" + datestr
+ ")",
1636 fmt
.format(date
, str
.remove()));
1638 datestr
= data
[i
++];
1639 date
= ref
.parse(ctou(datestr
), ec
);
1640 if (!assertSuccess("parse", ec
)) return;
1641 UDate parsedate
= fmt
.parse(ctou(string
), ec
);
1642 if (assertSuccess((UnicodeString
)"\"" + currentPat
+ "\".parse(" + string
+ ")", ec
)) {
1643 assertEquals((UnicodeString
)"\"" + currentPat
+ "\".parse(" + string
+ ")",
1644 univ
.format(date
, str
.remove()),
1645 univ
.format(parsedate
, str2
.remove()));
1649 else if (uprv_strcmp(control
, "pf") == 0) {
1651 const char* string
= data
[i
++];
1652 const char* datestr
= data
[i
++];
1653 UDate date
= ref
.parse(ctou(datestr
), ec
);
1654 if (!assertSuccess("parse", ec
)) return;
1655 UDate parsedate
= fmt
.parse(ctou(string
), ec
);
1656 if (assertSuccess((UnicodeString
)"\"" + currentPat
+ "\".parse(" + string
+ ")", ec
)) {
1657 assertEquals((UnicodeString
)"\"" + currentPat
+ "\".parse(" + string
+ ")",
1658 univ
.format(date
, str
.remove()),
1659 univ
.format(parsedate
, str2
.remove()));
1663 assertEquals((UnicodeString
)"\"" + currentPat
+ "\".format(" + datestr
+ ")",
1665 fmt
.format(date
, str
.remove()));
1668 else if (uprv_strcmp(control
, "F") == 0) {
1669 const char* datestr
= data
[i
++];
1670 const char* string
= data
[i
++];
1671 UDate date
= ref
.parse(ctou(datestr
), ec
);
1672 if (!assertSuccess("parse", ec
)) return;
1673 assertEquals((UnicodeString
)"\"" + currentPat
+ "\".format(" + datestr
+ ")",
1675 fmt
.format(date
, str
.remove()));
1677 UDate parsedate
= fmt
.parse(string
, ec
);
1678 if (assertSuccess((UnicodeString
)"\"" + currentPat
+ "\".parse(" + string
+ ")", ec
)) {
1679 assertEquals((UnicodeString
)"\"" + currentPat
+ "\".parse(" + string
+ ")",
1680 univ
.format(date
, str
.remove()),
1681 univ
.format(parsedate
, str2
.remove()));
1686 errln((UnicodeString
)"FAIL: Invalid control string " + control
);
1693 * Test formatting. Input is an array that starts
1694 * with the following header:
1696 * [0] = pattern string to parse [i+2] with
1698 * followed by test cases, each of which is 3 array elements:
1700 * [i] = pattern, or null to reuse prior pattern
1701 * [i+1] = data string a
1702 * [i+2] = data string b
1705 * Format date [i+1] and expect string [i+2].
1707 * "y/M/d H:mm:ss.SSSS", "2004/3/10 16:36:31.5679", "2004 03 10 16:36:31.567"
1709 void DateFormatTest::expectFormat(const char** data
, int32_t data_length
,
1710 const Locale
& loc
) {
1712 UErrorCode ec
= U_ZERO_ERROR
;
1713 UnicodeString str
, str2
;
1714 SimpleDateFormat
fmt("", loc
, ec
);
1715 SimpleDateFormat
ref(data
[i
++], loc
, ec
);
1716 SimpleDateFormat
univ("EE G yyyy MM dd HH:mm:ss.SSS z", loc
, ec
);
1717 if (!assertSuccess("construct SimpleDateFormat", ec
)) return;
1719 UnicodeString currentPat
;
1721 while (i
<data_length
) {
1722 const char* pattern
= data
[i
++];
1723 if (pattern
!= NULL
) {
1724 fmt
.applyPattern(pattern
);
1725 currentPat
= pattern
;
1728 const char* datestr
= data
[i
++];
1729 const char* string
= data
[i
++];
1730 UDate date
= ref
.parse(ctou(datestr
), ec
);
1731 if (!assertSuccess("parse", ec
)) return;
1732 assertEquals((UnicodeString
)"\"" + currentPat
+ "\".format(" + datestr
+ ")",
1734 fmt
.format(date
, str
.remove()));
1738 void DateFormatTest::TestGenericTime() {
1739 // any zone pattern should parse any zone
1740 const Locale
en("en");
1741 const char* ZDATA
[] = {
1742 "yyyy MM dd HH:mm zzz",
1744 "y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
1745 "y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
1746 "y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
1747 "y/M/d H:mm vvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
1748 // non-generic timezone string influences dst offset even if wrong for date/time
1749 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
1750 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 Pacific Time",
1751 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 PDT",
1752 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PST", "2004 07 01 02:00 PDT", "2004/7/1 2:00 Pacific Time",
1753 // generic timezone generates dst offset appropriate for local time
1754 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
1755 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
1756 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
1757 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
1758 // daylight savings time transition edge cases.
1759 // time to parse does not really exist, PT interpreted as earlier time
1760 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST", // adjust earlier
1761 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
1762 "y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
1763 "y/M/d H:mm vvv", "pf", "2005/4/3 2:30 PT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT", // adjust earlier
1764 "y/M/d H:mm vvv", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
1765 "y/M/d H:mm vvv", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT",
1766 "y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 01:30 PST", "2005/4/3 1:30",
1767 // time to parse is ambiguous, PT interpreted as LATER time (?)
1768 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST", // 1:30a PT -> 1:30a PST (later)
1769 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
1770 "y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
1771 "y/M/d H:mm vvv", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT", // 1:30a PT -> 1:30a PST (later)
1772 "y/M/d H:mm vvv", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
1773 "y/M/d H:mm vvv", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PT",
1774 "y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30", // 1:30a PT -> 1:30a PST (later)
1776 const int32_t ZDATA_length
= sizeof(ZDATA
)/ sizeof(ZDATA
[0]);
1777 expect(ZDATA
, ZDATA_length
, en
);
1779 UErrorCode status
= U_ZERO_ERROR
;
1781 logln("cross format/parse tests");
1782 UnicodeString
basepat("yy/MM/dd H:mm ");
1783 SimpleDateFormat formats
[] = {
1784 SimpleDateFormat(basepat
+ "vvv", en
, status
),
1785 SimpleDateFormat(basepat
+ "vvvv", en
, status
),
1786 SimpleDateFormat(basepat
+ "zzz", en
, status
),
1787 SimpleDateFormat(basepat
+ "zzzz", en
, status
)
1790 const int32_t formats_length
= sizeof(formats
)/sizeof(formats
[0]);
1793 SimpleDateFormat
univ("yyyy MM dd HH:mm zzz", en
, status
);
1795 const UnicodeString times
[] = {
1796 "2004 01 02 03:04 PST",
1797 "2004 07 08 09:10 PDT"
1799 int32_t times_length
= sizeof(times
)/sizeof(times
[0]);
1800 for (int i
= 0; i
< times_length
; ++i
) {
1801 UDate d
= univ
.parse(times
[i
], status
);
1802 logln(UnicodeString("\ntime: ") + d
);
1803 for (int j
= 0; j
< formats_length
; ++j
) {
1805 formats
[j
].format(d
, test
);
1806 logln("\ntest: '" + test
+ "'");
1807 for (int k
= 0; k
< formats_length
; ++k
) {
1808 UDate t
= formats
[k
].parse(test
, status
);
1809 if (U_SUCCESS(status
)) {
1811 errln((UnicodeString
)"FAIL: format " + k
+
1812 " incorrectly parsed output of format " + j
+
1813 " (" + test
+ "), returned " +
1814 dateToString(t
) + " instead of " + dateToString(d
));
1816 logln((UnicodeString
)"OK: format " + k
+ " parsed ok");
1818 } else if (status
== U_PARSE_ERROR
) {
1819 errln((UnicodeString
)"FAIL: format " + k
+
1820 " could not parse output of format " + j
+
1828 void DateFormatTest::TestGenericTimeZoneOrder() {
1829 // generic times should parse the same no matter what the placement of the time zone string
1830 // should work for standard and daylight times
1832 const char* XDATA
[] = {
1833 "yyyy MM dd HH:mm zzz",
1834 // standard time, explicit daylight/standard
1835 "y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
1836 "y/M/d zzz H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 PST 1:00",
1837 "zzz y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "PST 2004/1/1 1:00",
1839 // standard time, generic
1840 "y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PT", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
1841 "y/M/d vvvv H:mm", "pf", "2004/1/1 PT 1:00", "2004 01 01 01:00 PST", "2004/1/1 Pacific Time 1:00",
1842 "vvvv y/M/d H:mm", "pf", "PT 2004/1/1 1:00", "2004 01 01 01:00 PST", "Pacific Time 2004/1/1 1:00",
1844 // dahylight time, explicit daylight/standard
1845 "y/M/d H:mm zzz", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 PDT",
1846 "y/M/d zzz H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 PDT 1:00",
1847 "zzz y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "PDT 2004/7/1 1:00",
1849 // daylight time, generic
1850 "y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
1851 "y/M/d vvvv H:mm", "pf", "2004/7/1 PT 1:00", "2004 07 01 01:00 PDT", "2004/7/1 Pacific Time 1:00",
1852 "vvvv y/M/d H:mm", "pf", "PT 2004/7/1 1:00", "2004 07 01 01:00 PDT", "Pacific Time 2004/7/1 1:00",
1854 const int32_t XDATA_length
= sizeof(XDATA
)/sizeof(XDATA
[0]);
1856 expect(XDATA
, XDATA_length
, en
);
1859 void DateFormatTest::TestTimeZoneStringsAPI() {
1861 UErrorCode status
= U_ZERO_ERROR
;
1862 DateFormatSymbols
symbols(Locale::getUS(), status
);
1863 StringEnumeration
* keys
= symbols
.createZoneStringIDs(status
);
1864 if(U_FAILURE(status
)){
1865 errln("Could not create the StringEnumeration for Locale::getUS(). Error: %s", u_errorName(status
));
1869 StringEnumeration
* keys2
= symbols
.createZoneStringIDs(status
);
1872 errln("operator!= failed for TimeZoneStringsEnum");
1874 const UnicodeString
* key
= NULL
;
1876 while( (key
= keys
->snext(status
))!=NULL
){
1877 logln(prettify(*key
));
1879 if(U_FAILURE(status
)){
1880 errln("Could not iterate over the StringEnumeration. Error: %s", u_errorName(status
));
1883 UnicodeString
expectedKey("America/Los_Angeles");
1884 UnicodeString expectedStrs
[DateFormatSymbols::TIMEZONE_COUNT
];
1885 expectedStrs
[DateFormatSymbols::TIMEZONE_SHORT_GENERIC
].setTo("PT");
1886 expectedStrs
[DateFormatSymbols::TIMEZONE_SHORT_STANDARD
].setTo("PST");
1887 expectedStrs
[DateFormatSymbols::TIMEZONE_SHORT_DAYLIGHT
].setTo("PDT");
1888 expectedStrs
[DateFormatSymbols::TIMEZONE_LONG_GENERIC
].setTo("Pacific Time");
1889 expectedStrs
[DateFormatSymbols::TIMEZONE_LONG_STANDARD
].setTo("Pacific Standard Time");
1890 expectedStrs
[DateFormatSymbols::TIMEZONE_LONG_DAYLIGHT
].setTo("Pacific Daylight Time");
1891 expectedStrs
[DateFormatSymbols::TIMEZONE_EXEMPLAR_CITY
].setTo("Los Angeles");
1892 for(int32_t i
=0; i
<DateFormatSymbols::TIMEZONE_COUNT
; i
++){
1893 UnicodeString result
;
1894 result
= symbols
.getZoneString(expectedKey
, (DateFormatSymbols::TimeZoneTranslationType
)i
, result
,status
);
1895 if(U_FAILURE(status
)){
1896 errln("Could not retrieve display name. Error: %s", u_errorName(status
));
1899 if(expectedStrs
[i
] != result
){
1900 errln("Did not get the expected string. Expected: "+expectedStrs
[i
]+ UnicodeString(" Got: ") + result
);
1903 expectedKey
.setTo("America/Los_Angeles",0);
1904 UnicodeString
exemplarCity("Phoenix");
1905 UnicodeString result
;
1906 symbols
.setZoneString(expectedKey
,DateFormatSymbols::TIMEZONE_EXEMPLAR_CITY
, exemplarCity
, status
);
1907 if(U_FAILURE(status
)){
1908 errln("setZoneString() did not succeed. Error: %s", u_errorName(status
));
1911 result
= symbols
.getZoneString(expectedKey
, DateFormatSymbols::TIMEZONE_EXEMPLAR_CITY
, result
,status
);
1912 if(result
!= exemplarCity
){
1913 errln("setZoneString() did not succeed. Expected: " + exemplarCity
+ " Got: " + result
);
1919 void DateFormatTest::TestHost(void)
1922 Win32DateTimeTest::testLocales(this);
1926 #endif /* #if !UCONFIG_NO_FORMATTING */