]> granicus.if.org Git - icu/commitdiff
ICU-10334 C vs. J differences when in lenient mode
authorScott Russell <DTownSMR@gmail.com>
Wed, 18 Dec 2013 20:03:44 +0000 (20:03 +0000)
committerScott Russell <DTownSMR@gmail.com>
Wed, 18 Dec 2013 20:03:44 +0000 (20:03 +0000)
X-SVN-Rev: 34792

icu4c/source/i18n/smpdtfmt.cpp
icu4c/source/i18n/unicode/smpdtfmt.h
icu4c/source/i18n/unicode/udat.h
icu4c/source/test/intltest/dtfmrgts.cpp
icu4c/source/test/intltest/dtfmrgts.h

index 28fd78f982d5607ffcda0c1c46c0663065ac8a6f..30ab46082b2c5730b71ec69967bb6800483d7d5e 100644 (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
index 0ce2161efc5f0a81290fb2cbe0c960b5f0e8af2e..42f430d5d21e82ada66be8b387f93241b1a5ab3c 100644 (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
index e8f0664e5915cbf74ab152d0122091b01651dfe3..4437743f6b31333c0f7e662a48cf2c8989da8b63 100644 (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
index a72976fe92aa3264459661afa45304bce2503b11..8ffecd501dfb6bf80c482f2593bde336dc985091 100644 (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
index 21e2db015ce9c2f09dbc07ee649633965bd1cf31..1d5ed01b7c161ca15ff8450fe34fa2e1394e6f86 100644 (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 */