From: Craig Cornelius Date: Fri, 4 Sep 2015 21:58:03 +0000 (+0000) Subject: ICU-11784 Fix DecimalFormat FieldPosition for Field.CURRENCY X-Git-Tag: milestone-59-0-1~930 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2dfa67638530793958ddfb8a2b58dba9eff1e6df;p=icu ICU-11784 Fix DecimalFormat FieldPosition for Field.CURRENCY X-SVN-Rev: 37887 --- diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java index 804ded315c4..3a938e9593f 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/DecimalFormat.java @@ -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(); } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java index e170ef6670d..681b21aa5c3 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/NumberFormatTest.java @@ -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