mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-18 11:14:22 +00:00
ICU-1916 properly skip input whitespace before fields during parse
X-SVN-Rev: 9773
This commit is contained in:
parent
849251dcf2
commit
281a3ac28c
5 changed files with 123 additions and 15 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -143,6 +143,8 @@ public: // package
|
|||
virtual void TestLocaleDateFormat(void);
|
||||
|
||||
virtual void TestDateFormatCalendar(void);
|
||||
|
||||
virtual void TestSpaceParsing(void);
|
||||
};
|
||||
|
||||
#endif // _DATEFORMATTEST_
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue