]> granicus.if.org Git - icu/commitdiff
ICU-20577 Restore C MeasureFormat ability to adopt non-decimal number formatter ...
authorPeter Edberg <pedberg@unicode.org>
Thu, 29 Aug 2019 07:02:17 +0000 (00:02 -0700)
committerpedberg-icu <42151464+pedberg-icu@users.noreply.github.com>
Fri, 30 Aug 2019 22:53:05 +0000 (15:53 -0700)
icu4c/source/i18n/measfmt.cpp
icu4c/source/i18n/number_longnames.cpp
icu4c/source/i18n/number_longnames.h
icu4c/source/test/intltest/measfmttest.cpp

index 7d9612d107096d42c486fec52c4052e7bd8e78d0..1949f17b13723d729c4be00fdff2c84c70588e0d 100644 (file)
@@ -685,9 +685,19 @@ UnicodeString &MeasureFormat::formatMeasure(
     }
     auto* df = dynamic_cast<const DecimalFormat*>(&nf);
     if (df == nullptr) {
-        // Don't know how to handle other types of NumberFormat
-        status = U_UNSUPPORTED_ERROR;
-        return appendTo;
+        // Handle other types of NumberFormat using the ICU 63 code, modified to
+        // get the unitPattern from LongNameHandler and handle fallback to OTHER.
+        UnicodeString formattedNumber;
+        StandardPlural::Form pluralForm = QuantityFormatter::selectPlural(
+                amtNumber, nf, **pluralRules, formattedNumber, pos, status);
+        UnicodeString pattern = number::impl::LongNameHandler::getUnitPattern(getLocale(status),
+                amtUnit, getUnitWidth(fWidth), pluralForm, status);
+        // The above  handles fallback from other widths to short, and from other plural forms to OTHER
+        if (U_FAILURE(status)) {
+            return appendTo;
+        }
+        SimpleFormatter formatter(pattern, 0, 1, status);
+        return QuantityFormatter::format(formatter, formattedNumber, appendTo, pos, status);
     }
     number::FormattedNumber result;
     if (auto* lnf = df->toNumberFormatter(status)) {
index b790ffb67e8b06b4d623bafccaefc23e660c10bf..817aa0e0d9c39d9e8acedf8ae5130bb51922078c 100644 (file)
@@ -264,6 +264,26 @@ UnicodeString LongNameHandler::getUnitDisplayName(
     return simpleFormats[DNAM_INDEX];
 }
 
+UnicodeString LongNameHandler::getUnitPattern(
+        const Locale& loc,
+        const MeasureUnit& unit,
+        UNumberUnitWidth width,
+        StandardPlural::Form pluralForm,
+        UErrorCode& status) {
+    if (U_FAILURE(status)) {
+        return ICU_Utility::makeBogusString();
+    }
+    UnicodeString simpleFormats[ARRAY_LENGTH];
+    getMeasureData(loc, unit, width, simpleFormats, status);
+    // The above already handles fallback from other widths to short
+    if (U_FAILURE(status)) {
+        return ICU_Utility::makeBogusString();
+    }
+    // Now handle fallback from other plural forms to OTHER
+    return (!(simpleFormats[pluralForm]).isBogus())? simpleFormats[pluralForm]:
+            simpleFormats[StandardPlural::Form::OTHER];
+}
+
 LongNameHandler* LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit &currency,
                                                       const PluralRules *rules,
                                                       const MicroPropsGenerator *parent,
index 38aca26f729a2236de4893e29acc0a0435c5caf7..a19425aa268af62ef19c6498b2321b4599ad2b48 100644 (file)
@@ -22,6 +22,13 @@ class LongNameHandler : public MicroPropsGenerator, public ModifierStore, public
         UNumberUnitWidth width,
         UErrorCode& status);
 
+    static UnicodeString getUnitPattern(
+        const Locale& loc,
+        const MeasureUnit& unit,
+        UNumberUnitWidth width,
+        StandardPlural::Form pluralForm,
+        UErrorCode& status);
+
     static LongNameHandler*
     forCurrencyLongNames(const Locale &loc, const CurrencyUnit &currency, const PluralRules *rules,
                          const MicroPropsGenerator *parent, UErrorCode &status);
index c4d0064e89b54df377b7c0b73136777e68057b6e..cb53d83e8d2ee14703d98c4de5d60b425a9f57d2 100644 (file)
@@ -28,6 +28,7 @@
 #include "charstr.h"
 #include "cstr.h"
 #include "unicode/reldatefmt.h"
+#include "unicode/rbnf.h"
 
 struct ExpectedResult {
     const Measure *measures;
@@ -1699,6 +1700,10 @@ void MeasureFormatTest::TestExamplesInDocs() {
 
 void MeasureFormatTest::TestFormatPeriodEn() {
     UErrorCode status = U_ZERO_ERROR;
+    Measure t_1y[] = {Measure((double)1, MeasureUnit::createYear(status), status)};
+    Measure t_5M[] = {Measure((double)5, MeasureUnit::createMonth(status), status)};
+    Measure t_4d[] = {Measure((double)4, MeasureUnit::createDay(status), status)};
+    Measure t_2h[] = {Measure((double)2, MeasureUnit::createHour(status), status)};
     Measure t_19m[] = {Measure((double)19, MeasureUnit::createMinute(status), status)};
     Measure t_1h_23_5s[] = {
             Measure((double)1.0, MeasureUnit::createHour(status), status),
@@ -1867,6 +1872,20 @@ void MeasureFormatTest::TestFormatPeriodEn() {
             {t_6h_56_92m, UPRV_LENGTHOF(t_6h_56_92m), "6:56.92"},
             {t_3h_5h, UPRV_LENGTHOF(t_3h_5h), "3 \\u0998\\u0983, 5 \\u0998\\u0983"}};
 
+    ExpectedResult fullDataSpellout[] = {
+            {t_1y, UPRV_LENGTHOF(t_1y), "one year"},
+            {t_5M, UPRV_LENGTHOF(t_5M), "five months"},
+            {t_4d, UPRV_LENGTHOF(t_4d), "four days"},
+            {t_2h, UPRV_LENGTHOF(t_2h), "two hours"},
+            {t_19m, UPRV_LENGTHOF(t_19m), "nineteen minutes"}};
+
+    ExpectedResult fullDataSpelloutFr[] = {
+            {t_1y, UPRV_LENGTHOF(t_1y), "un\\u00A0an"},
+            {t_5M, UPRV_LENGTHOF(t_5M), "cinq\\u00A0mois"},
+            {t_4d, UPRV_LENGTHOF(t_4d), "quatre\\u00A0jours"},
+            {t_2h, UPRV_LENGTHOF(t_2h), "deux\\u00A0heures"},
+            {t_19m, UPRV_LENGTHOF(t_19m), "dix-neuf minutes"}};
+
     Locale en(Locale::getEnglish());
     LocalPointer<NumberFormat> nf(NumberFormat::createInstance(en, status));
     if (U_FAILURE(status)) {
@@ -1947,6 +1966,30 @@ void MeasureFormatTest::TestFormatPeriodEn() {
         return;
     }
     verifyFormat("bn-u-nu-latn NUMERIC", mf, numericDataBnLatn, UPRV_LENGTHOF(numericDataBnLatn));
+
+    status = U_ZERO_ERROR;
+    LocalPointer<RuleBasedNumberFormat> rbnf(new RuleBasedNumberFormat(URBNF_SPELLOUT, en, status));
+    if (U_FAILURE(status)) {
+        dataerrln("Error creating rbnf en object - %s", u_errorName(status));
+        return;
+    }
+    mf = MeasureFormat(en, UMEASFMT_WIDTH_WIDE, rbnf->clone(), status);
+    if (!assertSuccess("Error creating measure format en WIDE with rbnf", status)) {
+        return;
+    }
+    verifyFormat("en WIDE rbnf", mf, fullDataSpellout, UPRV_LENGTHOF(fullDataSpellout));
+
+    Locale fr(Locale::getFrench());
+    LocalPointer<RuleBasedNumberFormat> rbnffr(new RuleBasedNumberFormat(URBNF_SPELLOUT, fr, status));
+    if (U_FAILURE(status)) {
+        dataerrln("Error creating rbnf fr object - %s", u_errorName(status));
+        return;
+    }
+    mf = MeasureFormat(fr, UMEASFMT_WIDTH_WIDE, rbnffr->clone(), status);
+    if (!assertSuccess("Error creating measure format fr WIDE with rbnf", status)) {
+        return;
+    }
+    verifyFormat("fr WIDE rbnf", mf, fullDataSpelloutFr, UPRV_LENGTHOF(fullDataSpellout));
 }
 
 void MeasureFormatTest::Test10219FractionalPlurals() {