]> granicus.if.org Git - icu/commitdiff
ICU-9242 Fix format parsing in ICU4C calendar code
authorMichael Ow <mow@svn.icu-project.org>
Wed, 9 May 2012 21:00:40 +0000 (21:00 +0000)
committerMichael Ow <mow@svn.icu-project.org>
Wed, 9 May 2012 21:00:40 +0000 (21:00 +0000)
X-SVN-Rev: 31805

icu4c/source/i18n/calendar.cpp
icu4c/source/test/intltest/dtfmrgts.cpp
icu4c/source/test/intltest/dtfmrgts.h

index a5200899064738a7e16a84ba22df015a6ed11320..225ca2a5b96c08eb70a28b61c10ffe1c478c0b58 100644 (file)
@@ -2542,6 +2542,7 @@ UCalendarDateFields Calendar::newerField(UCalendarDateFields defaultField, UCale
 
 UCalendarDateFields Calendar::resolveFields(const UFieldResolutionTable* precedenceTable) {
     int32_t bestField = UCAL_FIELD_COUNT;
+    int32_t tempBestField;
     for (int32_t g=0; precedenceTable[g][0][0] != -1 && (bestField == UCAL_FIELD_COUNT); ++g) {
         int32_t bestStamp = kUnset;
         for (int32_t l=0; precedenceTable[g][l][0] != -1; ++l) {
@@ -2559,14 +2560,26 @@ UCalendarDateFields Calendar::resolveFields(const UFieldResolutionTable* precede
             }
             // Record new maximum stamp & field no.
             if (lineStamp > bestStamp) {
-                bestStamp = lineStamp;
-                bestField = precedenceTable[g][l][0]; // First field refers to entire line
+                tempBestField = precedenceTable[g][l][0]; // First field refers to entire line
+                if (tempBestField >= kResolveRemap) {
+                    tempBestField &= (kResolveRemap-1);
+                    // This check is needed to resolve some issues with UCAL_YEAR precedence mapping
+                    if (tempBestField != UCAL_DATE || (fStamp[UCAL_WEEK_OF_MONTH] < fStamp[tempBestField])) {
+                        bestField = tempBestField;
+                    }
+                } else {
+                    bestField = tempBestField;
+                }
+
+                if (bestField == tempBestField) {
+                    bestStamp = lineStamp;
+                }
             }
 linesInGroup:
             ;
         }
     }
-    return (UCalendarDateFields)( (bestField>=kResolveRemap)?(bestField&(kResolveRemap-1)):bestField  );
+    return (UCalendarDateFields)bestField;
 }
 
 const UFieldResolutionTable Calendar::kDatePrecedence[] =
index 1f12b65e28e3346640d0c300ce4dee772abf53f9..6ebce2816362a6d7ca55a3af276e2f723f68bb0f 100644 (file)
@@ -56,6 +56,7 @@ DateFormatRegressionTest::runIndexedTest( int32_t index, UBool exec, const char*
         CASE(25,Test1684)
         CASE(26,Test5554)
         CASE(27,Test9237)
+        CASE(28,TestParsing)
         default: name = ""; break;
     }
 }
@@ -1496,6 +1497,34 @@ void DateFormatRegressionTest::Test9237(void)
     }
 }
 
+void DateFormatRegressionTest::TestParsing(void) {
+    UErrorCode status = U_ZERO_ERROR;
+    UnicodeString pattern("EEE-WW-MMMM-yyyy");
+    UnicodeString text("mon-02-march-2011");
+    int32_t expectedDay = 7;
+
+    SimpleDateFormat format(pattern, status);
+    if (U_FAILURE(status)) {
+        dataerrln("Unable to create SimpleDateFormat - %s", u_errorName(status));
+        return;
+    }
+
+    Calendar *cal = new GregorianCalendar(status);
+    if (cal == NULL || U_FAILURE(status)) {
+        errln("Unable to create calendar - %s", u_errorName(status));
+        return;
+    }
+
+    ParsePosition pos(0);
+    format.parse(text, *cal, pos);
+
+    if (cal->get(UCAL_DAY_OF_MONTH, status) != expectedDay) {
+        errln("Parsing failed: day of month should be '7' with pattern: \"" + pattern + "\" for text: \"" + text + "\"");
+    }
+
+    delete cal;
+}
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
 
 //eof
index be08953989c71f6209edcb4ea82ae4e833010cf1..21e2db015ce9c2f09dbc07ee649633965bd1cf31 100644 (file)
@@ -52,6 +52,7 @@ public:
     void Test1684(void);
     void Test5554(void);
     void Test9237(void);
+    void TestParsing(void);
  };
 
 #endif /* #if !UCONFIG_NO_FORMATTING */