ICU-1916 properly skip input whitespace before fields during parse

X-SVN-Rev: 9773
This commit is contained in:
Alan Liu 2002-08-22 21:55:51 +00:00
parent 849251dcf2
commit 281a3ac28c
5 changed files with 123 additions and 15 deletions

View file

@ -1082,20 +1082,22 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
}
patternCharIndex = (EField)(patternCharPtr - DateFormatSymbols::getPatternUChars());
pos.setIndex(start);
Calendar::EDateFields field = fgPatternIndexToCalendarField[patternCharIndex];
// If there are any spaces here, skip over them. If we hit the end
// of the string, then fail.
for (;;) {
if (pos.getIndex() >= text.length())
if (start >= text.length()) {
return -start;
UChar c = text[pos.getIndex()];
if (c != 0x0020 /*' '*/ && c != 0x0009 /*'\t'*/)
}
UChar32 c = text.char32At(start);
if (!u_isUWhiteSpace(c)) {
break;
pos.setIndex(pos.getIndex() + 1);
}
start += UTF_CHAR_LENGTH(c);
}
pos.setIndex(start);
// We handle a few special cases here where we need to parse
// a number value. We handle further, more generic cases below. We need

View file

@ -38,6 +38,7 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam
TESTCASE(15,TestLocaleDateFormat);
TESTCASE(16,TestWallyWedel);
TESTCASE(17,TestDateFormatCalendar);
TESTCASE(18,TestSpaceParsing);
default: name = ""; break;
}
}
@ -1000,4 +1001,60 @@ void DateFormatTest::TestDateFormatCalendar() {
delete cal;
}
/**
* Test DateFormat's parsing of space characters. See jitterbug 1916.
*/
void DateFormatTest::TestSpaceParsing() {
const char* PARSE_FAILURE = "parse failure";
const char* DATA[] = {
// pattern, input, expexted output (in quotes)
"MMMM d yy", " 04 05 06", PARSE_FAILURE, // MMMM wants Apr/April
"MMMM d yy", "04 05 06", PARSE_FAILURE,
"MM d yy", " 04 05 06", "\"2006 04 05\"",
"MM d yy", "04 05 06", "\"2006 04 05\"",
"MMMM d yy", " Apr 05 06", "\"2006 04 05\"",
"MMMM d yy", "Apr 05 06", "\"2006 04 05\"",
};
const int32_t DATA_len = sizeof(DATA)/sizeof(DATA[0]);
UErrorCode ec = U_ZERO_ERROR;
Locale en("en");
SimpleDateFormat sdfObj("", en, ec);
if (U_FAILURE(ec)) {
errln("FAIL: SimpleDateFormat constructor");
return;
}
int32_t i;
for (i=0; i<DATA_len; i+=3) {
sdfObj.applyPattern(DATA[i]);
ParsePosition pp(0);
UDate udDate = sdfObj.parse(DATA[i+1], pp);
UnicodeString output;
if (pp.getErrorIndex() == -1) {
ec = U_ZERO_ERROR;
SimpleDateFormat formatter("yyyy MM dd", en, ec);
if (U_FAILURE(ec)) {
errln("FAIL: SimpleDateFormat constructor");
return;
}
FieldPosition fp(0);
formatter.format(udDate, output, fp);
output.insert(0, (UChar)34);
output.append((UChar)34);
} else {
output = UnicodeString(PARSE_FAILURE, "");
}
UnicodeString exp(DATA[i+2], "");
if (output == exp) {
logln((UnicodeString)"Ok: Parse of \"" + DATA[i+1] + "\" with \"" +
DATA[i] + "\" => " + output);
} else {
errln((UnicodeString)"FAIL: Parse of \"" + DATA[i+1] + "\" with \"" +
DATA[i] + "\" => " +
output + ", expected " + exp);
}
}
}
//eof

View file

@ -143,6 +143,8 @@ public: // package
virtual void TestLocaleDateFormat(void);
virtual void TestDateFormatCalendar(void);
virtual void TestSpaceParsing(void);
};
#endif // _DATEFORMATTEST_

View file

@ -4,8 +4,8 @@
* others. All Rights Reserved. *
*******************************************************************************
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/dev/test/format/DateFormatTest.java,v $
* $Date: 2002/04/09 23:33:13 $
* $Revision: 1.8 $
* $Date: 2002/08/22 21:55:51 $
* $Revision: 1.9 $
*
*****************************************************************************************
*/
@ -836,4 +836,47 @@ public class DateFormatTest extends com.ibm.icu.dev.test.TestFmwk {
errln("FAIL: Parsed result: " + str + ", exp 4/5/2001 5:45 PM");
}
}
/**
* Test DateFormat's parsing of space characters. See jitterbug 1916.
*/
public void TestSpaceParsing() {
String PARSE_FAILURE = "parse failure";
String DATA[] = {
// pattern, input, expexted output (in quotes)
"MMMM d yy", " 04 05 06", PARSE_FAILURE, // MMMM wants Apr/April
"MMMM d yy", "04 05 06", PARSE_FAILURE,
"MM d yy", " 04 05 06", "\"2006 04 05\"",
"MM d yy", "04 05 06", "\"2006 04 05\"",
"MMMM d yy", " Apr 05 06", "\"2006 04 05\"",
"MMMM d yy", "Apr 05 06", "\"2006 04 05\"",
};
Locale en = new Locale("en", "", "");
SimpleDateFormat sdfObj = new SimpleDateFormat("", en);
int i;
for (i=0; i<DATA.length; i+=3) {
sdfObj.applyPattern(DATA[i]);
ParsePosition pp = new ParsePosition(0);
Date udDate = sdfObj.parse(DATA[i+1], pp);
String output;
if (pp.getErrorIndex() == -1) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy MM dd", en);
output = "\"" + formatter.format(udDate) + "\"";
} else {
output = PARSE_FAILURE;
}
String exp = DATA[i+2];
if (output.equals(exp)) {
logln("Ok: Parse of \"" + DATA[i+1] + "\" with \"" +
DATA[i] + "\" => " + output);
} else {
errln("FAIL: Parse of \"" + DATA[i+1] + "\" with \"" +
DATA[i] + "\" => " +
output + ", expected " + exp);
}
}
}
}

View file

@ -5,8 +5,8 @@
*******************************************************************************
*
* $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/text/SimpleDateFormat.java,v $
* $Date: 2002/03/20 05:11:16 $
* $Revision: 1.13 $
* $Date: 2002/08/22 21:55:29 $
* $Revision: 1.14 $
*
*****************************************************************************************
*/
@ -18,6 +18,7 @@ import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.SimpleTimeZone;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.lang.UCharacter;
import java.io.IOException;
import java.io.ObjectInputStream;
@ -1007,18 +1008,21 @@ public class SimpleDateFormat extends DateFormat {
if ((patternCharIndex=formatData.patternChars.indexOf(ch)) == -1)
return -start;
pos.setIndex(start);
int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
// If there are any spaces here, skip over them. If we hit the end
// of the string, then fail.
for (;;) {
if (pos.getIndex() >= text.length()) return -start;
char c = text.charAt(pos.getIndex());
if (c != ' ' && c != '\t') break;
pos.setIndex(pos.getIndex()+1);
if (start >= text.length()) {
return -start;
}
int c = UTF16.charAt(text, start);
if (!UCharacter.isUWhiteSpace(c)) {
break;
}
start += UTF16.getCharCount(c);
}
pos.setIndex(start);
// We handle a few special cases here where we need to parse
// a number value. We handle further, more generic cases below. We need