]> git.saurik.com Git - apple/icu.git/commitdiff
ICU-400.38.tar.gz mac-os-x-1062 v400.38
authorApple <opensource@apple.com>
Wed, 16 Sep 2009 17:43:53 +0000 (17:43 +0000)
committerApple <opensource@apple.com>
Wed, 16 Sep 2009 17:43:53 +0000 (17:43 +0000)
icuSources/i18n/decfmtst.cpp
icuSources/i18n/decfmtst.h
icuSources/i18n/decimfmt.cpp
icuSources/i18n/smpdtfmt.cpp
icuSources/test/intltest/dtfmttst.cpp
icuSources/test/intltest/dtfmttst.h
icuSources/test/intltest/numfmtst.cpp

index 573dcbf912cd1e3e57a31f6062e2858395dc13b3..6452936d355d9cfd9e3b29af64e21fca40029294 100644 (file)
@@ -45,6 +45,10 @@ static const UChar gOtherGroupingSeparatorsPattern[] = {
                // [       \     SPACE     '      NBSP  \u066C  \u2000     -    \u200A  \u2018  \u2019  \u202F  \u205F  \u3000  \uFF07     ]
         0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000};
 
+static const UChar gDashEquivalentsPattern[] = {
+    // [       \      -     HYPHEN  F_DASH  N_DASH   MINUS     ]
+    0x005B, 0x005C, 0x002D, 0x2010, 0x2012, 0x2013, 0x2212, 0x005D, 0x0000};
+
 static const UChar gStrictDotEquivalentsPattern[] = {
                // [      .     \u2024  \uFE52  \uFF0E  \uFF61    ]
         0x005B, 0x002E, 0x2024, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000};
@@ -57,6 +61,10 @@ static const UChar gStrictOtherGroupingSeparatorsPattern[] = {
                // [       \     SPACE     '      NBSP  \u066C  \u2000     -    \u200A  \u2018  \u2019  \u202F  \u205F  \u3000  \uFF07     ]
         0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000};
 
+static const UChar gStrictDashEquivalentsPattern[] = {
+    // [       \      -      MINUS     ]
+    0x005B, 0x005C, 0x002D, 0x2212, 0x005D, 0x0000};
+
 
 DecimalFormatStaticSets *DecimalFormatStaticSets::gStaticSets = NULL;
 
@@ -64,18 +72,23 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
 : fDotEquivalents(NULL),
   fCommaEquivalents(NULL),
   fOtherGroupingSeparators(NULL),
+  fDashEquivalents(NULL),
   fStrictDotEquivalents(NULL),
   fStrictCommaEquivalents(NULL),
   fStrictOtherGroupingSeparators(NULL),
+  fStrictDashEquivalents(NULL),
   fDefaultGroupingSeparators(NULL),
   fStrictDefaultGroupingSeparators(NULL)
 {
     fDotEquivalents                = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1),                *status);
     fCommaEquivalents              = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1),              *status);
     fOtherGroupingSeparators       = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1),       *status);
+    fDashEquivalents               = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1),               *status);
+    
     fStrictDotEquivalents          = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1),          *status);
     fStrictCommaEquivalents        = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1),        *status);
     fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), *status);
+    fStrictDashEquivalents         = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1),         *status);
 
 
     fDefaultGroupingSeparators = new UnicodeSet(*fDotEquivalents);
@@ -87,8 +100,8 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
     fStrictDefaultGroupingSeparators->addAll(*fStrictOtherGroupingSeparators);
 
     // Check for null pointers
-    if (fDotEquivalents == NULL || fCommaEquivalents == NULL || fOtherGroupingSeparators == NULL ||
-               fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL ||
+    if (fDotEquivalents == NULL || fCommaEquivalents == NULL || fOtherGroupingSeparators == NULL || fDashEquivalents == NULL ||
+               fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL || fStrictDashEquivalents == NULL ||
                fDefaultGroupingSeparators == NULL || fStrictOtherGroupingSeparators == NULL) {
         goto ExitConstrDeleteAll;
     }
@@ -97,9 +110,11 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
     fDotEquivalents->freeze();
     fCommaEquivalents->freeze();
     fOtherGroupingSeparators->freeze();
+    fDashEquivalents->freeze();
     fStrictDotEquivalents->freeze();
     fStrictCommaEquivalents->freeze();
     fStrictOtherGroupingSeparators->freeze();
+    fStrictDashEquivalents->freeze();
     fDefaultGroupingSeparators->freeze();
     fStrictDefaultGroupingSeparators->freeze();
        
@@ -109,9 +124,11 @@ ExitConstrDeleteAll: // Remove fPropSets and fRuleSets and return error
     delete fDotEquivalents; fDotEquivalents = NULL;
     delete fCommaEquivalents; fCommaEquivalents = NULL;
     delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL;
+    delete fDashEquivalents; fDashEquivalents = NULL;
     delete fStrictDotEquivalents; fStrictDotEquivalents = NULL;
     delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL;
     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
+    delete fStrictDashEquivalents; fStrictDashEquivalents = NULL;
     delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL;
     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
 
@@ -123,9 +140,11 @@ DecimalFormatStaticSets::~DecimalFormatStaticSets() {
     delete fDotEquivalents; fDotEquivalents = NULL;
     delete fCommaEquivalents; fCommaEquivalents = NULL;
     delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL;
+    delete fDashEquivalents; fDashEquivalents = NULL;
     delete fStrictDotEquivalents; fStrictDotEquivalents = NULL;
     delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL;
     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
+    delete fStrictDashEquivalents; fStrictDashEquivalents = NULL;
     delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL;
     delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
 }
index 8c3d851cff6f123948bc1f14b6e6e92cda896235..79d15838a34340e3d2ca22ffd5f84186eccd1c05 100644 (file)
@@ -37,10 +37,12 @@ public:
     UnicodeSet *fDotEquivalents;
     UnicodeSet *fCommaEquivalents;
     UnicodeSet *fOtherGroupingSeparators;
+    UnicodeSet *fDashEquivalents;
 
     UnicodeSet *fStrictDotEquivalents;
     UnicodeSet *fStrictCommaEquivalents;
     UnicodeSet *fStrictOtherGroupingSeparators;
+    UnicodeSet *fStrictDashEquivalents;
 
     UnicodeSet *fDefaultGroupingSeparators;
     UnicodeSet *fStrictDefaultGroupingSeparators;
index 288a685c94766918c2e7206f38bcb935089112cb..4f51c10ee7c9f9046728a1f2c658b5379020c1f4 100644 (file)
@@ -1580,7 +1580,7 @@ UBool DecimalFormat::subparse(const UnicodeString& text, ParsePosition& parsePos
                                
                 position += U16_LENGTH(ch);
             }
-            else if (matchSymbol(text, position, groupingStringLength, *groupingString, groupingSet, ch) && isGroupingUsed())
+            else if (groupingStringLength > 0 && matchSymbol(text, position, groupingStringLength, *groupingString, groupingSet, ch) && isGroupingUsed())
             {
 #if CHECK_FOR_MISPLACED_GROUPING
                 if (sawDecimal) {
@@ -1888,10 +1888,29 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
                                           const UnicodeString& input,
                                           int32_t pos,
                                           UBool strict) {
+    UErrorCode status = U_ZERO_ERROR;
     int32_t start = pos;
+    UChar32 affixChar = affix.char32At(0);
+    int32_t affixLength = affix.length();
+    int32_t inputLength = input.length();
+    int32_t affixCharLength = U16_LENGTH(affixChar);
+    UnicodeSet *affixSet;
        
+    DecimalFormatStaticSets::initSets(&status);
+    
        if (strict) {
-               for (int32_t i=0; i<affix.length(); ) {
+        affixSet = DecimalFormatStaticSets::gStaticSets->fStrictDashEquivalents;
+        
+        // If the affix is exactly one character long and that character
+        // is in the dash set and the very next input character is also
+        // in the dash set, return a match.
+        if (affixCharLength == affixLength && affixSet->contains(affixChar))  {
+            if (affixSet->contains(input.char32At(pos))) {
+                return 1;
+            }
+        }
+        
+               for (int32_t i=0; i<affixLength; ) {
                        UChar32 c = affix.char32At(i);
                        int32_t len = U16_LENGTH(c);
                        if (uprv_isRuleWhiteSpace(c)) {
@@ -1902,12 +1921,12 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
                                // match of the run of RULE whitespace in the pattern,
                                // then match any extra characters.
                                UBool literalMatch = FALSE;
-                               while (pos < input.length() &&
+                               while (pos < inputLength &&
                                           input.char32At(pos) == c) {
                                        literalMatch = TRUE;
                                        i += len;
                                        pos += len;
-                                       if (i == affix.length()) {
+                                       if (i == affixLength) {
                                                break;
                                        }
                                        c = affix.char32At(i);
@@ -1934,7 +1953,7 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
                                // is also in the affix.
                                i = skipUWhiteSpace(affix, i);
                        } else {
-                               if (pos < input.length() &&
+                               if (pos < inputLength &&
                                        input.char32At(pos) == c) {
                                        i += len;
                                        pos += len;
@@ -1944,9 +1963,17 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
                        }
                }
        } else {
-               int32_t affixLength = affix.length();
-               int32_t inputLength = input.length();
                UBool match = FALSE;
+        
+        affixSet = DecimalFormatStaticSets::gStaticSets->fDashEquivalents;
+        
+        if (affixCharLength == affixLength && affixSet->contains(affixChar))  {
+            pos = skipUWhiteSpace(input, pos);
+            
+            if (affixSet->contains(input.char32At(pos))) {
+                return pos - start + 1;
+            }
+        }
                
                for (int32_t i = 0; i < affixLength; )
                {
index 7f98827fa245326d9fdd6766042cae3506efda0c..5b93dc4912a342f67e97017d9a83e9352d68097c 100644 (file)
@@ -2133,7 +2133,13 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC
             // in strict mode, these can only
             // be a number if count <= 2
             if (!lenient && gotNumber && count > 2) {
-                return -1;
+                // We have a string pattern in strict mode
+                // but the input parsed as a number. Ignore
+                // the fact that the input parsed as a number
+                // and try to match it as a string. (Some
+                // locales have numbers for the month names.)
+                gotNumber = FALSE;
+                pos.setIndex(start);
             }
             
             break;
index 65345fc085cffbc34a83fbf0bb6eb711bf5e0d46..78b073396804b68d557c0f52ea88897fa9e13983 100644 (file)
@@ -77,7 +77,9 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam
         /*
         TESTCASE(37,TestRelativeError);
         TESTCASE(38,TestRelativeOther);
-        */
+        TESTCASE(39,TestNumberAsStringParsing);
+         */
+        TESTCASE(37,TestNumberAsStringParsing);
         default: name = ""; break;
     }
 }
@@ -2964,6 +2966,32 @@ void DateFormatTest::TestRelativeOther(void)
 }
 */
 
+void DateFormatTest::TestNumberAsStringParsing()
+{
+    UErrorCode status = U_ZERO_ERROR;
+    UnicodeString dateString("2009 7 2 08:14:16");
+    UnicodeString datePattern("y MMMM d HH:mm:ss");
+    SimpleDateFormat *formatter = new SimpleDateFormat(datePattern, Locale(""), status);
+    UDate date1 = 0;
+    
+    formatter->setLenient(FALSE);
+    date1 = formatter->parse(dateString, status);
+    
+    if (U_FAILURE(status)) {
+        errln("FAIL: Could not parse \"2009 7 2 08:14:16\" with pattern \"y MMMM d HH:mm:ss\"");
+    } else {
+        UnicodeString formatted;
+        
+        formatter->format(date1, formatted);
+        
+        if (formatted != dateString) {
+            errln("FAIL: parsed string did not match input.");
+        }
+    }
+    
+    delete formatter;
+}
+
 
 
 #endif /* #if !UCONFIG_NO_FORMATTING */
index 091c459786e9bfc0d73f865f81dd4eb55788a0ff..cf49009338632baa299951fb3f70c5162bb8c0cb 100644 (file)
@@ -1,6 +1,6 @@
 /********************************************************************
  * COPYRIGHT: 
- * Copyright (c) 1997-2007, International Business Machines Corporation and
+ * Copyright (c) 1997-2009, International Business Machines Corporation and
  * others. All Rights Reserved.
  ********************************************************************/
 
@@ -136,7 +136,11 @@ public:
     virtual void TestDateFormatZone146(void);
 
     void TestTimeZoneStringsAPI(void);
+
+#if ICU_4_2_1
+    void TestGMTParsing(void);
+#endif
+
 public: // package
     /**
      * Test the formatting of dates in different locales.
@@ -159,6 +163,14 @@ public: // package
 
     void TestGenericTimeZoneOrder(void);
 
+#if ICU_4_2_1
+    void Test6338(void);
+
+    void Test6726(void);
+
+    void Test6880(void);
+#endif
+
 public:
     /**
      * Test host-specific formatting.
@@ -185,17 +197,31 @@ public:
     
     void TestHostClone(void);
 
+#if ICU_4_2_1
+    void TestTimeZoneDisplayName(void);
+
+    void TestRoundtripWithCalendar(void);
+#endif
+
 public:
     /***
      * Test Relative Dates
      */
      void TestRelative(void);
-     void TestTimeZoneDisplayName(void);
+#if !ICU_4_2_1
+    void TestTimeZoneDisplayName(void);
+#endif
 /*   void TestRelativeError(void);
      void TestRelativeOther(void);
 */
 
- private:
+public:
+    /**
+     * Test parsing a number as a string
+     */
+    void TestNumberAsStringParsing(void);
+    
+private:
       void TestRelative(int daysdelta, 
                                   const Locale& loc,
                                   const char *expectChars);
index 4371c668a223c160bb2453f8bd0a6071eb60480d..1ac9e1bee095db3ee37b662a7652f967be106295 100644 (file)
@@ -818,6 +818,12 @@ static const char *lenientAffixTestCases[] = {
        "( 1 )"
 };
 
+static const char *lenientMinusTestCases[] = {
+    "-5",
+    "\\u22125",
+    "\\u20105"
+};
+
 static const char *lenientCurrencyTestCases[] = {
        "$1,000",
        "$ 1,000",
@@ -898,8 +904,44 @@ NumberFormatTest::TestLenientParse(void)
        
     delete format;
        
-    Locale locale("en_US");
-    NumberFormat *cFormat = NumberFormat::createCurrencyInstance(locale, status);
+    Locale en_US("en_US");
+    Locale sv_SE("sv_SE");
+    
+    NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, status);
+    
+    mFormat->setParseStrict(FALSE);
+    for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) {
+        UnicodeString testCase = ctou(lenientMinusTestCases[t]);
+        
+        mFormat->parse(testCase, n, status);
+        logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
+        
+        if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
+            errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
+            status = U_ZERO_ERROR;
+        }
+    }
+    
+    delete mFormat;
+    
+    mFormat = NumberFormat::createInstance(en_US, status);
+    
+    mFormat->setParseStrict(FALSE);
+    for (int32_t t = 0; t < ARRAY_SIZE(lenientMinusTestCases); t += 1) {
+        UnicodeString testCase = ctou(lenientMinusTestCases[t]);
+        
+        mFormat->parse(testCase, n, status);
+        logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());
+        
+        if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
+            errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t] + (UnicodeString) "\"");
+            status = U_ZERO_ERROR;
+        }
+    }
+    
+    delete mFormat;
+    
+    NumberFormat *cFormat = NumberFormat::createCurrencyInstance(en_US, status);
        
     cFormat->setParseStrict(FALSE);
     for (int32_t t = 0; t < ARRAY_SIZE (lenientCurrencyTestCases); t += 1) {
@@ -932,7 +974,7 @@ NumberFormatTest::TestLenientParse(void)
        
     delete cFormat;
        
-    NumberFormat *pFormat = NumberFormat::createPercentInstance(locale, status);
+    NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);
        
     pFormat->setParseStrict(FALSE);
     for (int32_t t = 0; t < ARRAY_SIZE (lenientPercentTestCases); t += 1) {
@@ -965,7 +1007,7 @@ NumberFormatTest::TestLenientParse(void)
        
        // Test cases that should fail with a strict parse and pass with a
        // lenient parse.
-       NumberFormat *nFormat = NumberFormat::createInstance(locale, status);
+       NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);
        
        // first, make sure that they fail with a strict parse
        for (int32_t t = 0; t < ARRAY_SIZE(strictFailureTestCases); t += 1) {