mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-08 06:53:45 +00:00
ICU-10268 MeasureFormat to format currencies correctly.
X-SVN-Rev: 34860
This commit is contained in:
parent
2b6a24aebc
commit
b2f94a75a8
2 changed files with 80 additions and 11 deletions
|
@ -32,6 +32,7 @@ import com.ibm.icu.impl.DontCareFieldPosition;
|
|||
import com.ibm.icu.impl.ICUResourceBundle;
|
||||
import com.ibm.icu.impl.SimpleCache;
|
||||
import com.ibm.icu.util.Currency;
|
||||
import com.ibm.icu.util.CurrencyAmount;
|
||||
import com.ibm.icu.util.Measure;
|
||||
import com.ibm.icu.util.MeasureUnit;
|
||||
import com.ibm.icu.util.TimeZone;
|
||||
|
@ -110,6 +111,8 @@ public class MeasureFormat extends UFormat {
|
|||
private final transient Map<MeasureUnit, EnumMap<FormatWidth, Map<String, PatternData>>> unitToStyleToCountToFormat;
|
||||
|
||||
private final transient NumericFormatters numericFormatters;
|
||||
|
||||
private final transient ImmutableNumberFormat currencyFormat;
|
||||
|
||||
private static final SimpleCache<ULocale,Map<MeasureUnit, EnumMap<FormatWidth, Map<String, PatternData>>>> localeToUnitToStyleToCountToFormat
|
||||
= new SimpleCache<ULocale,Map<MeasureUnit, EnumMap<FormatWidth, Map<String, PatternData>>>>();
|
||||
|
@ -137,7 +140,7 @@ public class MeasureFormat extends UFormat {
|
|||
* @draft ICU 53
|
||||
* @provisional
|
||||
*/
|
||||
// Be sure to update the toFormatWidth and fromFormatWidth() functions
|
||||
// Be sure to update MeasureUnitTest.TestSerialFormatWidthEnum
|
||||
// when adding an enum value.
|
||||
public enum FormatWidth {
|
||||
|
||||
|
@ -147,7 +150,7 @@ public class MeasureFormat extends UFormat {
|
|||
* @draft ICU 53
|
||||
* @provisional
|
||||
*/
|
||||
WIDE("units", ListFormatter.Style.DURATION),
|
||||
WIDE("units", ListFormatter.Style.DURATION, NumberFormat.PLURALCURRENCYSTYLE),
|
||||
|
||||
/**
|
||||
* Abbreviate when possible.
|
||||
|
@ -155,7 +158,7 @@ public class MeasureFormat extends UFormat {
|
|||
* @draft ICU 53
|
||||
* @provisional
|
||||
*/
|
||||
SHORT("unitsShort", ListFormatter.Style.DURATION_SHORT),
|
||||
SHORT("unitsShort", ListFormatter.Style.DURATION_SHORT, NumberFormat.ISOCURRENCYSTYLE),
|
||||
|
||||
/**
|
||||
* Brief. Use only a symbol for the unit when possible.
|
||||
|
@ -163,7 +166,7 @@ public class MeasureFormat extends UFormat {
|
|||
* @draft ICU 53
|
||||
* @provisional
|
||||
*/
|
||||
NARROW("unitsNarrow", ListFormatter.Style.DURATION_SHORT),
|
||||
NARROW("unitsNarrow", ListFormatter.Style.DURATION_SHORT, NumberFormat.CURRENCYSTYLE),
|
||||
|
||||
/**
|
||||
* Identical to NARROW except when formatMeasures is called with
|
||||
|
@ -173,22 +176,28 @@ public class MeasureFormat extends UFormat {
|
|||
* @draft ICU 53
|
||||
* @provisional
|
||||
*/
|
||||
NUMERIC("unitsNarrow", ListFormatter.Style.DURATION_SHORT);
|
||||
NUMERIC("unitsNarrow", ListFormatter.Style.DURATION_SHORT, NumberFormat.CURRENCYSTYLE);
|
||||
|
||||
// Be sure to update the toFormatWidth and fromFormatWidth() functions
|
||||
// when adding an enum value.
|
||||
|
||||
final String resourceKey;
|
||||
private final ListFormatter.Style listFormatterStyle;
|
||||
private final int currencyStyle;
|
||||
|
||||
private FormatWidth(String resourceKey, ListFormatter.Style style) {
|
||||
private FormatWidth(String resourceKey, ListFormatter.Style style, int currencyStyle) {
|
||||
this.resourceKey = resourceKey;
|
||||
this.listFormatterStyle = style;
|
||||
this.currencyStyle = currencyStyle;
|
||||
}
|
||||
|
||||
ListFormatter.Style getListFormatterStyle() {
|
||||
return listFormatterStyle;
|
||||
}
|
||||
|
||||
int getCurrencyStyle() {
|
||||
return currencyStyle;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,13 +239,16 @@ public class MeasureFormat extends UFormat {
|
|||
localeToNumericDurationFormatters.put(locale, formatters);
|
||||
}
|
||||
}
|
||||
|
||||
return new MeasureFormat(
|
||||
locale,
|
||||
formatWidth,
|
||||
new ImmutableNumberFormat(format),
|
||||
rules,
|
||||
unitToStyleToCountToFormat,
|
||||
formatters);
|
||||
formatters,
|
||||
new ImmutableNumberFormat(
|
||||
NumberFormat.getInstance(locale, formatWidth.getCurrencyStyle())));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -463,7 +475,8 @@ public class MeasureFormat extends UFormat {
|
|||
new ImmutableNumberFormat(format),
|
||||
this.rules,
|
||||
this.unitToStyleToCountToFormat,
|
||||
this.numericFormatters);
|
||||
this.numericFormatters,
|
||||
this.currencyFormat);
|
||||
}
|
||||
|
||||
private MeasureFormat(
|
||||
|
@ -472,13 +485,15 @@ public class MeasureFormat extends UFormat {
|
|||
ImmutableNumberFormat format,
|
||||
PluralRules rules,
|
||||
Map<MeasureUnit, EnumMap<FormatWidth, Map<String, PatternData>>> unitToStyleToCountToFormat,
|
||||
NumericFormatters formatters) {
|
||||
NumericFormatters formatters,
|
||||
ImmutableNumberFormat currencyFormat) {
|
||||
setLocale(locale, locale);
|
||||
this.formatWidth = formatWidth;
|
||||
this.numberFormat = format;
|
||||
this.rules = rules;
|
||||
this.unitToStyleToCountToFormat = unitToStyleToCountToFormat;
|
||||
this.numericFormatters = formatters;
|
||||
this.currencyFormat = currencyFormat;
|
||||
}
|
||||
|
||||
MeasureFormat() {
|
||||
|
@ -488,6 +503,7 @@ public class MeasureFormat extends UFormat {
|
|||
this.rules = null;
|
||||
this.unitToStyleToCountToFormat = null;
|
||||
this.numericFormatters = null;
|
||||
this.currencyFormat = null;
|
||||
}
|
||||
|
||||
static class NumericFormatters {
|
||||
|
@ -608,8 +624,20 @@ public class MeasureFormat extends UFormat {
|
|||
|
||||
private <T extends Appendable> T formatMeasure(
|
||||
Measure measure, T appendable, FieldPosition fieldPosition) {
|
||||
if (measure.getUnit() instanceof Currency) {
|
||||
try {
|
||||
appendable.append(
|
||||
currencyFormat.format(
|
||||
new CurrencyAmount(measure.getNumber(), (Currency) measure.getUnit()),
|
||||
new StringBuffer(),
|
||||
fieldPosition));
|
||||
return appendable;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
Number n = measure.getNumber();
|
||||
MeasureUnit unit = measure.getUnit();
|
||||
MeasureUnit unit = measure.getUnit();
|
||||
UFieldPosition fpos = new UFieldPosition(fieldPosition.getFieldAttribute(), fieldPosition.getField());
|
||||
StringBuffer formattedNumber = numberFormat.format(n, new StringBuffer(), fpos);
|
||||
String keyword = rules.select(new PluralRules.FixedDecimal(n.doubleValue(), fpos.getCountVisibleFractionDigits(), fpos.getFractionDigits()));
|
||||
|
@ -650,6 +678,11 @@ public class MeasureFormat extends UFormat {
|
|||
Number n, StringBuffer buffer, FieldPosition pos) {
|
||||
return nf.format(n, buffer, pos);
|
||||
}
|
||||
|
||||
public synchronized StringBuffer format(
|
||||
CurrencyAmount n, StringBuffer buffer, FieldPosition pos) {
|
||||
return nf.format(n, buffer, pos);
|
||||
}
|
||||
|
||||
public synchronized String format(Number number) {
|
||||
return nf.format(number);
|
||||
|
|
|
@ -122,6 +122,13 @@ public class MeasureUnitTest extends TestFmwk {
|
|||
{_0h_0m_17s, "0:00:17"},
|
||||
{_6h_56_92m, "6:56.92"},
|
||||
{_3h_5h, "3h, 5h"}};
|
||||
Object[][] fullDataDe = {
|
||||
{_1m_59_9996s, "1 Minute und 59.9996 Sekunden"},
|
||||
{_19m, "19 Minuten"},
|
||||
{_1h_23_5s, "1 Stunde und 23.5 Sekunden"},
|
||||
{_1h_23_5m, "1 Stunde und 23.5 Minuten"},
|
||||
{_1h_0m_23s, "1 Stunde, 0 Minuten und 23 Sekunden"},
|
||||
{_2y_5M_3w_4d, "2 Jahre, 5 Monate, 3 Wochen und 4 Tage"}};
|
||||
|
||||
NumberFormat nf = NumberFormat.getNumberInstance(ULocale.ENGLISH);
|
||||
nf.setMaximumFractionDigits(4);
|
||||
|
@ -130,7 +137,9 @@ public class MeasureUnitTest extends TestFmwk {
|
|||
mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT, nf);
|
||||
verifyFormatPeriod("en SHORT", mf, abbrevData);
|
||||
mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NUMERIC, nf);
|
||||
verifyFormatPeriod("en NUMERIC", mf, numericData);
|
||||
verifyFormatPeriod("en NUMERIC", mf, numericData);
|
||||
mf = MeasureFormat.getInstance(ULocale.GERMAN, FormatWidth.WIDE, nf);
|
||||
verifyFormatPeriod("de FULL", mf, fullDataDe);
|
||||
}
|
||||
|
||||
|
||||
|
@ -215,6 +224,33 @@ public class MeasureUnitTest extends TestFmwk {
|
|||
"1 G",
|
||||
mf.format(new Measure(1, MeasureUnit.G_FORCE)));
|
||||
}
|
||||
|
||||
public void testCurrencies() {
|
||||
Measure USD_1 = new Measure(1.0, Currency.getInstance("USD"));
|
||||
Measure USD_2 = new Measure(2.0, Currency.getInstance("USD"));
|
||||
Measure USD_NEG_1 = new Measure(-1.0, Currency.getInstance("USD"));
|
||||
MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE);
|
||||
assertEquals("Wide currency", "-1.00 US dollars", mf.format(USD_NEG_1));
|
||||
assertEquals("Wide currency", "1.00 US dollars", mf.format(USD_1));
|
||||
assertEquals("Wide currency", "2.00 US dollars", mf.format(USD_2));
|
||||
mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.SHORT);
|
||||
assertEquals("short currency", "-USD1.00", mf.format(USD_NEG_1));
|
||||
assertEquals("short currency", "USD1.00", mf.format(USD_1));
|
||||
assertEquals("short currency", "USD2.00", mf.format(USD_2));
|
||||
mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NARROW);
|
||||
assertEquals("narrow currency", "-$1.00", mf.format(USD_NEG_1));
|
||||
assertEquals("narrow currency", "$1.00", mf.format(USD_1));
|
||||
assertEquals("narrow currency", "$2.00", mf.format(USD_2));
|
||||
mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.NUMERIC);
|
||||
assertEquals("numeric currency", "-$1.00", mf.format(USD_NEG_1));
|
||||
assertEquals("numeric currency", "$1.00", mf.format(USD_1));
|
||||
assertEquals("numeric currency", "$2.00", mf.format(USD_2));
|
||||
|
||||
mf = MeasureFormat.getInstance(ULocale.JAPAN, FormatWidth.WIDE);
|
||||
assertEquals("Wide currency", "-1.00 \u7C73\u30C9\u30EB", mf.format(USD_NEG_1));
|
||||
assertEquals("Wide currency", "1.00 \u7C73\u30C9\u30EB", mf.format(USD_1));
|
||||
assertEquals("Wide currency", "2.00 \u7C73\u30C9\u30EB", mf.format(USD_2));
|
||||
}
|
||||
|
||||
public void testExamples() {
|
||||
MeasureFormat fmtFr = MeasureFormat.getInstance(ULocale.FRENCH, FormatWidth.SHORT);
|
||||
|
|
Loading…
Add table
Reference in a new issue