ICU-20577 Restore C MeasureFormat ability to adopt non-decimal number formatter (#789)

This commit is contained in:
Peter Edberg 2019-08-29 00:02:17 -07:00 committed by pedberg-icu
parent 7237fc58b4
commit 0801dd0bdd
4 changed files with 83 additions and 3 deletions

View 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)) {

View 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,

View 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);

View 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() {