mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-10334 C vs. J differences when in lenient mode
X-SVN-Rev: 34792
This commit is contained in:
parent
59dde192b7
commit
37e74533a6
5 changed files with 86 additions and 19 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue