diff --git a/icu4c/source/i18n/numparse_validators.cpp b/icu4c/source/i18n/numparse_validators.cpp index 12d3465c4ef..98637eeca02 100644 --- a/icu4c/source/i18n/numparse_validators.cpp +++ b/icu4c/source/i18n/numparse_validators.cpp @@ -46,8 +46,9 @@ RequireDecimalSeparatorValidator::RequireDecimalSeparatorValidator(bool patternH } void RequireDecimalSeparatorValidator::postProcess(ParsedNumber& result) const { + bool parseIsInfNaN = 0 != (result.flags & FLAG_INFINITY) || 0 != (result.flags & FLAG_NAN); bool parseHasDecimalSeparator = 0 != (result.flags & FLAG_HAS_DECIMAL_SEPARATOR); - if (parseHasDecimalSeparator != fPatternHasDecimalSeparator) { + if (!parseIsInfNaN && parseHasDecimalSeparator != fPatternHasDecimalSeparator) { result.flags |= FLAG_FAIL; } } diff --git a/icu4c/source/test/intltest/numfmtst.cpp b/icu4c/source/test/intltest/numfmtst.cpp index c855e3e2927..2c54a696c48 100644 --- a/icu4c/source/test/intltest/numfmtst.cpp +++ b/icu4c/source/test/intltest/numfmtst.cpp @@ -227,6 +227,7 @@ void NumberFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &n TESTCASE_AUTO(Test11649_DecFmtCurrencies); TESTCASE_AUTO(Test13148_ParseGroupingSeparators); TESTCASE_AUTO(Test12753_PatternDecimalPoint); + TESTCASE_AUTO(Test22303_PatternDecimalPoint_InfNaN); TESTCASE_AUTO(Test11647_PatternCurrencySymbols); TESTCASE_AUTO(Test11913_BigDecimal); TESTCASE_AUTO(Test11020_RoundingInScientificNotation); @@ -9423,9 +9424,26 @@ void NumberFormatTest::Test12753_PatternDecimalPoint() { df.parse(u"123",result, status); assertEquals("Parsing integer succeeded even though setDecimalPatternMatchRequired was set", U_INVALID_FORMAT_ERROR, status); - } +} - void NumberFormatTest::Test11647_PatternCurrencySymbols() { +void NumberFormatTest::Test22303_PatternDecimalPoint_InfNaN() { + UErrorCode status = U_ZERO_ERROR; + DecimalFormatSymbols symbols(Locale::getUS(), status); + symbols.setSymbol(DecimalFormatSymbols::kInfinitySymbol, u"infinity", false); + symbols.setSymbol(DecimalFormatSymbols::kNaNSymbol, u"notanumber", false); + DecimalFormat df(u"0.00", symbols, status); + if (!assertSuccess("", status)) return; + df.setDecimalPatternMatchRequired(true); + Formattable result; + df.parse(u"infinity", result, status); + assertEquals("Should parse to +INF even though decimal is required", INFINITY, result.getDouble()); + df.parse(u"notanumber", result, status); + assertEquals("Should parse to NaN even though decimal is required", NAN, result.getDouble()); + df.parse("-infinity", result, status); + assertEquals("Should parse to -INF even though decimal is required", -INFINITY, result.getDouble()); +} + +void NumberFormatTest::Test11647_PatternCurrencySymbols() { UErrorCode status = U_ZERO_ERROR; DecimalFormat df(status); df.applyPattern(u"¤¤¤¤#", status); diff --git a/icu4c/source/test/intltest/numfmtst.h b/icu4c/source/test/intltest/numfmtst.h index 10dd3386d4c..634536fff7c 100644 --- a/icu4c/source/test/intltest/numfmtst.h +++ b/icu4c/source/test/intltest/numfmtst.h @@ -283,6 +283,7 @@ class NumberFormatTest: public CalendarTimeZoneTest { void Test11649_DecFmtCurrencies(); void Test13148_ParseGroupingSeparators(); void Test12753_PatternDecimalPoint(); + void Test22303_PatternDecimalPoint_InfNaN(); void Test11647_PatternCurrencySymbols(); void Test11913_BigDecimal(); void Test11020_RoundingInScientificNotation(); diff --git a/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/NumberFormatTest.java b/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/NumberFormatTest.java index 606afb45cc5..8b61dadc405 100644 --- a/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/NumberFormatTest.java +++ b/icu4j/main/common_tests/src/test/java/com/ibm/icu/dev/test/format/NumberFormatTest.java @@ -5511,6 +5511,22 @@ public class NumberFormatTest extends CoreTestFmwk { } } + @Test + public void Test22303() throws ParseException { + ULocale locale = new ULocale("en-US"); + DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale); + symbols.setInfinity("infinity"); + symbols.setNaN("notanumber"); + DecimalFormat df = new DecimalFormat("0.00", symbols); + df.setDecimalPatternMatchRequired(true); + Number result = df.parse("infinity"); + assertEquals("Should parse to +INF even though decimal is required", Double.POSITIVE_INFINITY, result); + result = df.parse("notanumber"); + assertEquals("Should parse to NaN even though decimal is required", Double.NaN, result); + result = df.parse("-infinity"); + assertEquals("Should parse to -INF even though decimal is required", Double.NEGATIVE_INFINITY, result); + } + @Test public void Test12962() { String pat = "**0.00"; diff --git a/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/parse/RequireDecimalSeparatorValidator.java b/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/parse/RequireDecimalSeparatorValidator.java index d9301b25209..13c8ed921c5 100644 --- a/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/parse/RequireDecimalSeparatorValidator.java +++ b/icu4j/main/core/src/main/java/com/ibm/icu/impl/number/parse/RequireDecimalSeparatorValidator.java @@ -23,8 +23,9 @@ public class RequireDecimalSeparatorValidator extends ValidationMatcher { @Override public void postProcess(ParsedNumber result) { + boolean parseIsInfNaN = 0 != (result.flags & ParsedNumber.FLAG_INFINITY) || 0 != (result.flags & ParsedNumber.FLAG_NAN); boolean parseHasDecimalSeparator = 0 != (result.flags & ParsedNumber.FLAG_HAS_DECIMAL_SEPARATOR); - if (parseHasDecimalSeparator != patternHasDecimalSeparator) { + if (!parseIsInfNaN && parseHasDecimalSeparator != patternHasDecimalSeparator) { result.flags |= ParsedNumber.FLAG_FAIL; } }