ICU-10334 C vs. J differences when in lenient mode

X-SVN-Rev: 34792
This commit is contained in:
Scott Russell 2013-12-18 20:03:44 +00:00
parent 59dde192b7
commit 37e74533a6
5 changed files with 86 additions and 19 deletions

View file

@ -248,7 +248,7 @@ SimpleDateFormat::SimpleDateFormat(UErrorCode& status)
fOverrideList(NULL),
fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
{
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status).setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
construct(kShort, (EStyle) (kShort + kDateOffset), fLocale, status);
initializeDefaultCentury();
}
@ -267,7 +267,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
{
fDateOverride.setToBogus();
fTimeOverride.setToBogus();
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status).setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
initialize(fLocale, status);
initializeDefaultCentury();
@ -288,7 +288,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
{
fDateOverride.setTo(override);
fTimeOverride.setToBogus();
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status).setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
initialize(fLocale, status);
initializeDefaultCentury();
@ -312,7 +312,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fDateOverride.setToBogus();
fTimeOverride.setToBogus();
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status).setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
initialize(fLocale, status);
@ -335,7 +335,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fDateOverride.setTo(override);
fTimeOverride.setToBogus();
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status).setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
initializeSymbols(fLocale, initializeCalendar(NULL,fLocale,status), status);
initialize(fLocale, status);
@ -361,7 +361,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fDateOverride.setToBogus();
fTimeOverride.setToBogus();
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status).setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
initializeCalendar(NULL,fLocale,status);
initialize(fLocale, status);
@ -384,7 +384,7 @@ SimpleDateFormat::SimpleDateFormat(const UnicodeString& pattern,
fDateOverride.setToBogus();
fTimeOverride.setToBogus();
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status).setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
initializeCalendar(NULL, fLocale, status);
initialize(fLocale, status);
@ -405,7 +405,7 @@ SimpleDateFormat::SimpleDateFormat(EStyle timeStyle,
fOverrideList(NULL),
fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
{
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status).setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
construct(timeStyle, dateStyle, fLocale, status);
if(U_SUCCESS(status)) {
initializeDefaultCentury();
@ -446,7 +446,7 @@ SimpleDateFormat::SimpleDateFormat(const Locale& locale,
fDateOverride.setToBogus();
fTimeOverride.setToBogus();
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status).setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
initialize(fLocale, status);
if(U_SUCCESS(status)) {
@ -466,7 +466,7 @@ SimpleDateFormat::SimpleDateFormat(const SimpleDateFormat& other)
fCapitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
{
UErrorCode status = U_ZERO_ERROR;
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status);
setBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, true, status).setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, true, status).setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, true, status);
*this = other;
}
@ -1847,7 +1847,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition&
abutPat = -1; // End of any abutting fields
if (! matchLiterals(fPattern, i, text, pos, getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status))) {
if (! matchLiterals(fPattern, i, text, pos, getBooleanAttribute(UDAT_PARSE_ALLOW_WHITESPACE, status), getBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, status))) {
status = U_PARSE_ERROR;
goto ExitParse;
}
@ -2129,7 +2129,8 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
int32_t &patternOffset,
const UnicodeString &text,
int32_t &textOffset,
UBool lenient)
UBool whitespaceLenient,
UBool partialMatchLenient)
{
UBool inQuote = FALSE;
UnicodeString literal;
@ -2161,7 +2162,7 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
int32_t p;
int32_t t = textOffset;
if (lenient) {
if (whitespaceLenient) {
// trim leading, trailing whitespace from
// the literal text
literal.trim();
@ -2196,7 +2197,7 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
// TODO: should we require internal spaces
// in lenient mode? (There won't be any
// leading or trailing spaces)
if (!lenient && t == tStart) {
if (!whitespaceLenient && t == tStart) {
// didn't find matching whitespace:
// an error in strict mode
return FALSE;
@ -2212,7 +2213,7 @@ UBool SimpleDateFormat::matchLiterals(const UnicodeString &pattern,
if (t >= text.length() || literal.charAt(p) != text.charAt(t)) {
// Ran out of text, or found a non-matching character:
// OK in lenient mode, an error in strict mode.
if (lenient) {
if (partialMatchLenient) {
if (t == textOffset && text.charAt(t) == 0x2e &&
isAfterNonNumericField(pattern, patternOffset)) {
// Lenient mode and the literal input text begins with a "." and

View file

@ -1340,12 +1340,14 @@ private:
* @param text the text being parsed
* @param textOffset the starting offset into the text. On output
* will be set to the offset of the character after the match
* @param lenient <code>TRUE</code> if the parse is lenient, <code>FALSE</code> otherwise.
* @param whitespaceLenient <code>TRUE</code> if whitespace parse is lenient, <code>FALSE</code> otherwise.
* @param partialMatchLenient <code>TRUE</code> if partial match parse is lenient, <code>FALSE</code> otherwise.
*
* @return <code>TRUE</code> if the literal text could be matched, <code>FALSE</code> otherwise.
*/
static UBool matchLiterals(const UnicodeString &pattern, int32_t &patternOffset,
const UnicodeString &text, int32_t &textOffset, UBool lenient);
const UnicodeString &text, int32_t &textOffset,
UBool whitespaceLenient, UBool partialMatchLenient);
/**
* Private member function that converts the parsed date strings into

View file

@ -851,6 +851,11 @@ typedef enum UDateFormatBooleanAttribute {
* @internal ICU technology preview
*/
UDAT_PARSE_ALLOW_NUMERIC,
/**
* indicates tolerance of a partial literal match
* @draft ICU 53
*/
UDAT_PARSE_PARTIAL_MATCH,
/**
* count boolean date format constants
* @internal ICU technology preview

View file

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2012, International Business Machines Corporation and
* Copyright (c) 1997-2013, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
@ -57,6 +57,7 @@ DateFormatRegressionTest::runIndexedTest( int32_t index, UBool exec, const char*
CASE(26,Test5554)
CASE(27,Test9237)
CASE(28,TestParsing)
CASE(29,TestT10334)
default: name = ""; break;
}
}
@ -1525,6 +1526,63 @@ void DateFormatRegressionTest::TestParsing(void) {
delete cal;
}
void DateFormatRegressionTest::TestT10334(void) {
UErrorCode status = U_ZERO_ERROR;
UnicodeString pattern("'--: 'EEE-WW-MMMM-yyyy");
UnicodeString text("--mon-02-march-2011");
SimpleDateFormat format(pattern, status);
format.setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, FALSE, status);
format.parse(text, status);
if (!U_FAILURE(status)) {
errln("parse partial match did NOT fail in strict mode", u_errorName(status));
}
status = U_ZERO_ERROR;
format.setBooleanAttribute(UDAT_PARSE_PARTIAL_MATCH, TRUE, status);
format.parse(text, status);
if (U_FAILURE(status)) {
errln("parse partial match failure in lenient mode", u_errorName(status));
}
status = U_ZERO_ERROR;
pattern = UnicodeString("YYYY MM dd");
text = UnicodeString("2013 12 10");
format.applyPattern(pattern);
UDate referenceDate = format.parse(text, status);
FieldPosition fp(0);
UnicodeString formattedString("");
pattern = UnicodeString("YYYY LL dd ee cc qq QQ");
format.applyPattern(pattern);
format.format(referenceDate, formattedString, fp, status);
logln("ref date: " + formattedString);
char patternArray[] = "YYYY LLL dd eee ccc qqq QQQ";
pattern = UnicodeString(patternArray);
text = UnicodeString("2013 12 10 03 3 04 04");
status = U_ZERO_ERROR;
format.setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, TRUE, status);
format.applyPattern(pattern);
ParsePosition pp(0);
format.parse(text, pp);
int32_t errorIdx = pp.getErrorIndex();
if (errorIdx != -1) {
char buffer[256];
_snprintf(buffer, 256, "numeric parse error at[%d] on pattern char[%s]", errorIdx, &patternArray[errorIdx]);
errln(buffer);
}
status = U_ZERO_ERROR;
format.setBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, FALSE, status);
format.parse(text, status);
if (!U_FAILURE(status)) {
errln("numeric parse did NOT fail in strict mode", u_errorName(status));
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */
//eof

View file

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2012, International Business Machines Corporation and
* Copyright (c) 1997-2013, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
@ -53,6 +53,7 @@ public:
void Test5554(void);
void Test9237(void);
void TestParsing(void);
void TestT10334(void);
};
#endif /* #if !UCONFIG_NO_FORMATTING */