]> granicus.if.org Git - icu/commitdiff
ICU-11784 Fix DecimalFormat FieldPosition for Field.CURRENCY
authorCraig Cornelius <ccornelius@google.com>
Fri, 4 Sep 2015 21:58:03 +0000 (21:58 +0000)
committerCraig Cornelius <ccornelius@google.com>
Fri, 4 Sep 2015 21:58:03 +0000 (21:58 +0000)
X-SVN-Rev: 37887

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

index 804ded315c4c83c9066ac8e6d471b2d1c9c49459..3a938e9593ff70282085ea2e52932e253a930e25 100644 (file)
@@ -27,6 +27,7 @@ import com.ibm.icu.impl.Utility;
 import com.ibm.icu.lang.UCharacter;
 import com.ibm.icu.math.BigDecimal;
 import com.ibm.icu.math.MathContext;
+import com.ibm.icu.text.NumberFormat;
 import com.ibm.icu.text.PluralRules.FixedDecimal;
 import com.ibm.icu.util.Currency;
 import com.ibm.icu.util.Currency.CurrencyUsage;
@@ -866,7 +867,7 @@ public class DecimalFormat extends NumberFormat {
         number = round(number);
 
         if (Double.isInfinite(number)) {
-            int prefixLen = appendAffix(result, isNegative, true, parseAttr);
+            int prefixLen = appendAffix(result, isNegative, true, fieldPosition, parseAttr);
 
             if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
                 fieldPosition.setBeginIndex(result.length());
@@ -886,7 +887,7 @@ public class DecimalFormat extends NumberFormat {
                 fieldPosition.setEndIndex(result.length());
             }
 
-            int suffixLen = appendAffix(result, isNegative, false, parseAttr);
+            int suffixLen = appendAffix(result, isNegative, false, fieldPosition, parseAttr);
 
             addPadding(result, fieldPosition, prefixLen, suffixLen);
             return result;
@@ -1383,7 +1384,7 @@ public class DecimalFormat extends NumberFormat {
             digitList.decimalAt = 0; // Normalize
         }
 
-        int prefixLen = appendAffix(result, isNegative, true, parseAttr);
+        int prefixLen = appendAffix(result, isNegative, true, fieldPosition, parseAttr);
 
         if (useExponentialNotation) {
             subformatExponential(result, fieldPosition, parseAttr);
@@ -1391,8 +1392,7 @@ public class DecimalFormat extends NumberFormat {
             subformatFixed(result, fieldPosition, isInteger, parseAttr);
         }
 
-        int suffixLen = appendAffix(result, isNegative, false, parseAttr);
-
+        int suffixLen = appendAffix(result, isNegative, false, fieldPosition, parseAttr);
         addPadding(result, fieldPosition, prefixLen, suffixLen);
         return result;
     }
@@ -4192,8 +4192,11 @@ public class DecimalFormat extends NumberFormat {
      *            buffer to append to
      * @param isNegative
      * @param isPrefix
+     * @param fieldPosition
+     * @param parseAttr
      */
     private int appendAffix(StringBuffer buf, boolean isNegative, boolean isPrefix,
+                            FieldPosition fieldPosition,
                             boolean parseAttr) {
         if (currencyChoice != null) {
             String affixPat = null;
@@ -4209,10 +4212,13 @@ public class DecimalFormat extends NumberFormat {
         }
 
         String affix = null;
+        String pattern;
         if (isPrefix) {
             affix = isNegative ? negativePrefix : positivePrefix;
+            pattern = isNegative ? negPrefixPattern : posPrefixPattern;
         } else {
             affix = isNegative ? negativeSuffix : positiveSuffix;
+            pattern = isNegative ? negSuffixPattern : posSuffixPattern;
         }
         // [Spark/CDL] Invoke formatAffix2Attribute to add attributes for affix
         if (parseAttr) {
@@ -4225,6 +4231,34 @@ public class DecimalFormat extends NumberFormat {
             }
             formatAffix2Attribute(affix, buf.length() + offset, buf.length() + affix.length());
         }
+
+        // If kCurrencySymbol or kIntlCurrencySymbol is in the affix, check for currency symbol.
+        // Get spelled out name if "¤¤¤" is in the pattern.
+        if (fieldPosition.getFieldAttribute() == NumberFormat.Field.CURRENCY) {
+            if (affix.indexOf(symbols.getCurrencySymbol()) > -1) {
+                String aff = symbols.getCurrencySymbol();
+                int firstPos = affix.indexOf(aff);
+                int start = buf.length() + firstPos;
+                int end = start + aff.length();
+                fieldPosition.setBeginIndex(start);
+                fieldPosition.setEndIndex(end);
+            } else if (affix.indexOf(symbols.getInternationalCurrencySymbol()) > -1) {
+                String aff = symbols.getInternationalCurrencySymbol(); 
+                int firstPos = affix.indexOf(aff);
+                int start = buf.length() + firstPos;
+                int end = start + aff.length();
+                fieldPosition.setBeginIndex(start);
+                fieldPosition.setEndIndex(end);
+            } else if (pattern.indexOf("¤¤¤") > -1) {
+                // It's a plural, and we know where it is in the pattern.
+                int firstPos = pattern.indexOf("¤¤¤");
+                int start = buf.length() + firstPos;
+                int end = buf.length() + affix.length(); // This seems clunky and wrong.
+                fieldPosition.setBeginIndex(start);
+                fieldPosition.setEndIndex(end);
+            }
+        }
+
         buf.append(affix);
         return affix.length();
     }
index e170ef6670d3dc35f162b5310e7fc028321da27c..681b21aa5c3c2ca78d279bba478c5eb27cd2651e 100644 (file)
@@ -2340,6 +2340,113 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
         assertEquals("fp end", 8, fp.getEndIndex());
     }
 
+    public void TestFieldPositionCurrency() {
+        DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(Locale.US);
+        double amount = 35.47;
+        double negAmount = -34.567;
+        FieldPosition cp = new FieldPosition(NumberFormat.Field.CURRENCY);
+        
+        StringBuffer buffer0 = new StringBuffer();
+        nf.format(amount, buffer0, cp);
+        assertEquals("$35.47", "$35.47", buffer0.toString());
+        assertEquals("cp begin", 0, cp.getBeginIndex());
+        assertEquals("cp end", 1, cp.getEndIndex());
+        
+        StringBuffer buffer01 = new StringBuffer();
+        nf.format(negAmount, buffer01, cp);
+        assertEquals("-$34.57", "-$34.57", buffer01.toString());
+        assertEquals("cp begin", 1, cp.getBeginIndex());
+        assertEquals("cp end", 2, cp.getEndIndex());     
+        
+        nf.setCurrency(Currency.getInstance(Locale.FRANCE));
+        StringBuffer buffer1 = new StringBuffer();
+        nf.format(amount, buffer1, cp);
+        assertEquals("€35.47", "€35.47", buffer1.toString());
+        assertEquals("cp begin", 0, cp.getBeginIndex());
+        assertEquals("cp end", 1, cp.getEndIndex());
+
+        nf.setCurrency(Currency.getInstance(new Locale("fr", "ch", "")));
+        StringBuffer buffer2 = new StringBuffer();
+        nf.format(amount, buffer2, cp);
+        assertEquals("CHF35.47", "CHF35.47", buffer2.toString());
+        assertEquals("cp begin", 0, cp.getBeginIndex());
+        assertEquals("cp end", 3, cp.getEndIndex());
+
+        StringBuffer buffer20 = new StringBuffer();
+        nf.format(negAmount, buffer20, cp);
+        assertEquals("-CHF34.57", "-CHF34.57", buffer20.toString());
+        assertEquals("cp begin", 1, cp.getBeginIndex());
+        assertEquals("cp end", 4, cp.getEndIndex());
+        
+        nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(Locale.FRANCE);
+        StringBuffer buffer3 = new StringBuffer();
+        nf.format(amount, buffer3, cp);
+        assertEquals("35,47 €", "35,47 €", buffer3.toString());
+        assertEquals("cp begin", 6, cp.getBeginIndex());
+        assertEquals("cp end", 7, cp.getEndIndex());
+
+        StringBuffer buffer4 = new StringBuffer();
+        nf.format(negAmount, buffer4, cp);
+        assertEquals("-34,57 €", "-34,57 €", buffer4.toString());
+        assertEquals("cp begin", 7, cp.getBeginIndex());
+        assertEquals("cp end", 8, cp.getEndIndex());
+        
+        nf.setCurrency(Currency.getInstance(new Locale("fr", "ch")));
+        StringBuffer buffer5 = new StringBuffer();
+        nf.format(negAmount, buffer5, cp);
+        assertEquals("-34,57 CHF", "-34,57 CHF", buffer5.toString());
+        assertEquals("cp begin", 7, cp.getBeginIndex());
+        assertEquals("cp end", 10, cp.getEndIndex());
+        
+        NumberFormat plCurrencyFmt = NumberFormat.getInstance(new Locale("fr", "ch"), NumberFormat.PLURALCURRENCYSTYLE);
+        StringBuffer buffer6 = new StringBuffer();
+        plCurrencyFmt.format(negAmount, buffer6, cp);
+        assertEquals("-34.57 francs suisses", "-34.57 francs suisses", buffer6.toString());
+        assertEquals("cp begin", 7, cp.getBeginIndex());
+        assertEquals("cp end", 21, cp.getEndIndex());        
+        
+        // Positive value with PLURALCURRENCYSTYLE.
+        plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "ch"), NumberFormat.PLURALCURRENCYSTYLE);
+        StringBuffer buffer7 = new StringBuffer();
+        plCurrencyFmt.format(amount, buffer7, cp);
+        assertEquals("35.47スイス フラン", "35.47スイス フラン", buffer7.toString());
+        assertEquals("cp begin", 5, cp.getBeginIndex());
+        assertEquals("cp end", 12, cp.getEndIndex());
+        
+        // PLURALCURRENCYSTYLE for non-ASCII.
+        plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "de"), NumberFormat.PLURALCURRENCYSTYLE);
+        StringBuffer buffer8 = new StringBuffer();
+        plCurrencyFmt.format(negAmount, buffer8, cp);
+        assertEquals("-34.57ユーロ", "-34.57ユーロ", buffer8.toString());
+        assertEquals("cp begin", 6, cp.getBeginIndex());
+        assertEquals("cp end", 9, cp.getEndIndex());
+        
+        nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(Locale.JAPAN);
+        nf.setCurrency(Currency.getInstance(new Locale("ja", "jp")));
+        StringBuffer buffer9 = new StringBuffer();
+        nf.format(negAmount, buffer9, cp);
+        assertEquals("-¥35", "-¥35", buffer9.toString());
+        assertEquals("cp begin", 1, cp.getBeginIndex());
+        assertEquals("cp end", 2, cp.getEndIndex());
+        
+        // Negative value with PLURALCURRENCYSTYLE.
+        plCurrencyFmt = NumberFormat.getInstance(new Locale("ja", "ch"), NumberFormat.PLURALCURRENCYSTYLE);
+        StringBuffer buffer10 = new StringBuffer();
+        plCurrencyFmt.format(negAmount, buffer10, cp);
+        assertEquals("-34.57スイス フラン", "-34.57スイス フラン", buffer10.toString());
+        assertEquals("cp begin", 6, cp.getBeginIndex());
+        assertEquals("cp end", 13, cp.getEndIndex());
+        
+        // Nagative value with PLURALCURRENCYSTYLE, Arabic digits.
+        nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(new Locale("ar", "eg"));
+        plCurrencyFmt = NumberFormat.getInstance(new Locale("ar", "eg"), NumberFormat.PLURALCURRENCYSTYLE);
+        StringBuffer buffer11 = new StringBuffer();
+        plCurrencyFmt.format(negAmount, buffer11, cp);
+        assertEquals("‏-٣٤٫٥٧ جنيه مصري", "‏-٣٤٫٥٧ جنيه مصري", buffer11.toString());
+        assertEquals("cp begin", 8, cp.getBeginIndex());
+        assertEquals("cp end", 17, cp.getEndIndex());
+    }
+    
     public void TestRounding() {
         DecimalFormat nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
         if (false) { // for debugging specific value