]> granicus.if.org Git - icu/commitdiff
ICU-10268 MeasureFormat to format currencies correctly.
authorTravis Keep <keep94@gmail.com>
Fri, 10 Jan 2014 18:53:53 +0000 (18:53 +0000)
committerTravis Keep <keep94@gmail.com>
Fri, 10 Jan 2014 18:53:53 +0000 (18:53 +0000)
X-SVN-Rev: 34860

icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/MeasureUnitTest.java

index 85bee39a52de5729f3ccaf43e7a3b868ee0abd14..d8cb676cdf25585bd498aece4085e1178e793ebb 100644 (file)
@@ -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);
index e09aec1a5bf102c7dd5bda19b6da7f369c694356..cb1902ac9dd7bb51088b23098f84e6cdfdfb99de 100644 (file)
@@ -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);