diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp
index 28fd78f982d..30ab46082b2 100644
--- a/icu4c/source/i18n/smpdtfmt.cpp
+++ b/icu4c/source/i18n/smpdtfmt.cpp
@@ -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
diff --git a/icu4c/source/i18n/unicode/smpdtfmt.h b/icu4c/source/i18n/unicode/smpdtfmt.h
index 0ce2161efc5..42f430d5d21 100644
--- a/icu4c/source/i18n/unicode/smpdtfmt.h
+++ b/icu4c/source/i18n/unicode/smpdtfmt.h
@@ -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 TRUE
if the parse is lenient, FALSE
otherwise.
+ * @param whitespaceLenient TRUE
if whitespace parse is lenient, FALSE
otherwise.
+ * @param partialMatchLenient TRUE
if partial match parse is lenient, FALSE
otherwise.
*
* @return TRUE
if the literal text could be matched, FALSE
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
diff --git a/icu4c/source/i18n/unicode/udat.h b/icu4c/source/i18n/unicode/udat.h
index e8f0664e591..4437743f6b3 100644
--- a/icu4c/source/i18n/unicode/udat.h
+++ b/icu4c/source/i18n/unicode/udat.h
@@ -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
diff --git a/icu4c/source/test/intltest/dtfmrgts.cpp b/icu4c/source/test/intltest/dtfmrgts.cpp
index a72976fe92a..8ffecd501df 100644
--- a/icu4c/source/test/intltest/dtfmrgts.cpp
+++ b/icu4c/source/test/intltest/dtfmrgts.cpp
@@ -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
diff --git a/icu4c/source/test/intltest/dtfmrgts.h b/icu4c/source/test/intltest/dtfmrgts.h
index 21e2db015ce..1d5ed01b7c1 100644
--- a/icu4c/source/test/intltest/dtfmrgts.h
+++ b/icu4c/source/test/intltest/dtfmrgts.h
@@ -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 */