ICU-12351 Add missing field position data in DecimalFormat
X-SVN-Rev: 38544
This commit is contained in:
parent
34dc0a8069
commit
16557dbe12
@ -843,6 +843,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
}
|
||||
|
||||
result.append(symbols.getNaN());
|
||||
// TODO: Combine setting a single FieldPosition or adding to an AttributedCharacterIterator
|
||||
// into a function like recordAttribute(FieldAttribute, begin, end).
|
||||
|
||||
// [Spark/CDL] Add attribute for NaN here.
|
||||
// result.append(symbols.getNaN());
|
||||
if (parseAttr) {
|
||||
@ -1429,10 +1432,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
// [Spark/CDL] Record the integer start index.
|
||||
int intBegin = result.length();
|
||||
// Record field information for caller.
|
||||
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
|
||||
fieldPosition.setBeginIndex(result.length());
|
||||
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
|
||||
fieldPosition.setBeginIndex(result.length());
|
||||
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD ||
|
||||
fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
|
||||
fieldPosition.setBeginIndex(intBegin);
|
||||
}
|
||||
long fractionalDigits = 0;
|
||||
int fractionalDigitsCount = 0;
|
||||
@ -1484,17 +1486,22 @@ public class DecimalFormat extends NumberFormat {
|
||||
if (isGroupingPosition(i)) {
|
||||
result.append(grouping);
|
||||
// [Spark/CDL] Add grouping separator attribute here.
|
||||
// Set only for the first instance.
|
||||
// Length of grouping separator is 1.
|
||||
if (fieldPosition.getFieldAttribute() == Field.GROUPING_SEPARATOR &&
|
||||
fieldPosition.getBeginIndex() == 0 && fieldPosition.getEndIndex() == 0) {
|
||||
fieldPosition.setBeginIndex(result.length()-1);
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
}
|
||||
if (parseAttr) {
|
||||
// Length of grouping separator is 1.
|
||||
addAttribute(Field.GROUPING_SEPARATOR, result.length() - 1, result.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Record field information for caller.
|
||||
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD) {
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
|
||||
if (fieldPosition.getField() == NumberFormat.INTEGER_FIELD ||
|
||||
fieldPosition.getFieldAttribute() == NumberFormat.Field.INTEGER) {
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
}
|
||||
|
||||
@ -1640,7 +1647,6 @@ public class DecimalFormat extends NumberFormat {
|
||||
fieldPosition.setBeginIndex(-1);
|
||||
}
|
||||
|
||||
|
||||
// [Spark/CDL]
|
||||
// the begin index of integer part
|
||||
// the end index of integer part
|
||||
@ -1716,7 +1722,13 @@ public class DecimalFormat extends NumberFormat {
|
||||
intEnd = result.length();
|
||||
addAttribute(Field.INTEGER, intBegin, result.length());
|
||||
}
|
||||
if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
|
||||
fieldPosition.setBeginIndex(result.length());
|
||||
}
|
||||
result.append(decimal);
|
||||
if (fieldPosition.getFieldAttribute() == Field.DECIMAL_SEPARATOR) {
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
}
|
||||
// [Spark/CDL] Add attribute for decimal separator
|
||||
fracBegin = result.length();
|
||||
if (parseAttr) {
|
||||
@ -1777,7 +1789,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
((UFieldPosition) fieldPosition).setFractionDigits(fractionalDigitsCount, fractionalDigits);
|
||||
}
|
||||
|
||||
// [Spark/CDL] Calcuate the end index of integer part and fractional
|
||||
// [Spark/CDL] Calculate the end index of integer part and fractional
|
||||
// part if they are not properly processed yet.
|
||||
if (parseAttr) {
|
||||
if (intEnd < 0) {
|
||||
@ -1791,7 +1803,14 @@ public class DecimalFormat extends NumberFormat {
|
||||
// The exponent is output using the pattern-specified minimum exponent
|
||||
// digits. There is no maximum limit to the exponent digits, since truncating
|
||||
// the exponent would result in an unacceptable inaccuracy.
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SYMBOL) {
|
||||
fieldPosition.setBeginIndex(result.length());
|
||||
}
|
||||
|
||||
result.append(symbols.getExponentSeparator());
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SYMBOL) {
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
}
|
||||
// [Spark/CDL] For exponent symbol, add an attribute.
|
||||
if (parseAttr) {
|
||||
addAttribute(Field.EXPONENT_SYMBOL, result.length() -
|
||||
@ -1806,7 +1825,13 @@ public class DecimalFormat extends NumberFormat {
|
||||
boolean negativeExponent = exponent < 0;
|
||||
if (negativeExponent) {
|
||||
exponent = -exponent;
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
|
||||
fieldPosition.setBeginIndex(result.length());
|
||||
}
|
||||
result.append(symbols.getMinusString());
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
}
|
||||
// [Spark/CDL] If exponent has sign, then add an exponent sign
|
||||
// attribute.
|
||||
if (parseAttr) {
|
||||
@ -1814,7 +1839,13 @@ public class DecimalFormat extends NumberFormat {
|
||||
addAttribute(Field.EXPONENT_SIGN, result.length() - 1, result.length());
|
||||
}
|
||||
} else if (exponentSignAlwaysShown) {
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
|
||||
fieldPosition.setBeginIndex(result.length());
|
||||
}
|
||||
result.append(symbols.getPlusString());
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT_SIGN) {
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
}
|
||||
// [Spark/CDL] Add an plus sign attribute.
|
||||
if (parseAttr) {
|
||||
// Length of exponent sign is 1.
|
||||
@ -1837,6 +1868,10 @@ public class DecimalFormat extends NumberFormat {
|
||||
: digits[0]);
|
||||
}
|
||||
// [Spark/CDL] Add attribute for exponent part.
|
||||
if (fieldPosition.getFieldAttribute() == Field.EXPONENT) {
|
||||
fieldPosition.setBeginIndex(expBegin);
|
||||
fieldPosition.setEndIndex(result.length());
|
||||
}
|
||||
if (parseAttr) {
|
||||
addAttribute(Field.EXPONENT, expBegin, result.length());
|
||||
}
|
||||
@ -4240,7 +4275,31 @@ public class DecimalFormat extends NumberFormat {
|
||||
}
|
||||
}
|
||||
|
||||
// If kCurrencySymbol or kIntlCurrencySymbol is in the affix, check for currency symbol.
|
||||
// Look for SIGN, PERCENT, PERMILLE in the formatted affix.
|
||||
if (fieldPosition.getFieldAttribute() == NumberFormat.Field.SIGN) {
|
||||
String sign = isNegative ? symbols.getMinusString() : symbols.getPlusString();
|
||||
int firstPos = affix.indexOf(sign);
|
||||
if (firstPos > -1) {
|
||||
int startPos = buf.length() + firstPos;
|
||||
fieldPosition.setBeginIndex(startPos);
|
||||
fieldPosition.setEndIndex(startPos + sign.length());
|
||||
}
|
||||
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.PERCENT) {
|
||||
int firstPos = affix.indexOf(symbols.getPercent());
|
||||
if (firstPos > -1) {
|
||||
int startPos = buf.length() + firstPos;
|
||||
fieldPosition.setBeginIndex(startPos);
|
||||
fieldPosition.setEndIndex(startPos + 1);
|
||||
}
|
||||
} else if (fieldPosition.getFieldAttribute() == NumberFormat.Field.PERMILLE) {
|
||||
int firstPos = affix.indexOf(symbols.getPerMill());
|
||||
if (firstPos > -1) {
|
||||
int startPos = buf.length() + firstPos;
|
||||
fieldPosition.setBeginIndex(startPos);
|
||||
fieldPosition.setEndIndex(startPos + 1);
|
||||
}
|
||||
} else
|
||||
// If CurrencySymbol or InternationalCurrencySymbol 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) {
|
||||
@ -4251,7 +4310,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
fieldPosition.setBeginIndex(start);
|
||||
fieldPosition.setEndIndex(end);
|
||||
} else if (affix.indexOf(symbols.getInternationalCurrencySymbol()) > -1) {
|
||||
String aff = symbols.getInternationalCurrencySymbol();
|
||||
String aff = symbols.getInternationalCurrencySymbol();
|
||||
int firstPos = affix.indexOf(aff);
|
||||
int start = buf.length() + firstPos;
|
||||
int end = start + aff.length();
|
||||
|
@ -16,6 +16,7 @@ import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.FieldPosition;
|
||||
import java.text.Format;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.ArrayList;
|
||||
@ -4509,4 +4510,192 @@ public class NumberFormatTest extends com.ibm.icu.dev.test.TestFmwk {
|
||||
|
||||
assertEquals("ICU and JDK placement of decimal in exponent", jdk, icu);
|
||||
}
|
||||
private void checkFormatWithField(String testInfo, Format format, Object object,
|
||||
String expected, Format.Field field, int begin, int end) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
FieldPosition pos = new FieldPosition(field);
|
||||
format.format(object, buffer, pos);
|
||||
|
||||
assertEquals("Test " + testInfo + ": incorrect formatted text", expected, buffer.toString());
|
||||
|
||||
if (begin != pos.getBeginIndex() || end != pos.getEndIndex()) {
|
||||
assertEquals("Index mismatch", field + " " + begin + ".." + end,
|
||||
pos.getFieldAttribute() + " " + pos.getBeginIndex() + ".." + pos.getEndIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public void TestMissingFieldPositionsCurrency() {
|
||||
DecimalFormat formatter = (DecimalFormat) NumberFormat.getCurrencyInstance(ULocale.US);
|
||||
Number number = new Double(92314587.66);
|
||||
String result = "$92,314,587.66";
|
||||
|
||||
checkFormatWithField("currency", formatter, number, result,
|
||||
NumberFormat.Field.CURRENCY, 0, 1);
|
||||
checkFormatWithField("integer", formatter, number, result,
|
||||
NumberFormat.Field.INTEGER, 1, 11);
|
||||
checkFormatWithField("grouping separator", formatter, number, result,
|
||||
NumberFormat.Field.GROUPING_SEPARATOR, 3, 4);
|
||||
checkFormatWithField("decimal separator", formatter, number, result,
|
||||
NumberFormat.Field.DECIMAL_SEPARATOR, 11, 12);
|
||||
checkFormatWithField("fraction", formatter, number, result,
|
||||
NumberFormat.Field.FRACTION, 12, 14);
|
||||
}
|
||||
|
||||
public void TestMissingFieldPositionsNegativeDouble() {
|
||||
// test for exponential fields with double
|
||||
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
|
||||
Number number = new Double(-12345678.90123);
|
||||
DecimalFormat formatter = new DecimalFormat("0.#####E+00", us_symbols);
|
||||
String numFmtted = formatter.format(number);
|
||||
|
||||
checkFormatWithField("sign", formatter, number, numFmtted,
|
||||
NumberFormat.Field.SIGN, 0, 1);
|
||||
checkFormatWithField("integer", formatter, number, numFmtted,
|
||||
NumberFormat.Field.INTEGER, 1, 2);
|
||||
checkFormatWithField("decimal separator", formatter, number, numFmtted,
|
||||
NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3);
|
||||
checkFormatWithField("exponent symbol", formatter, number, numFmtted,
|
||||
NumberFormat.Field.EXPONENT_SYMBOL, 8, 9);
|
||||
checkFormatWithField("exponent sign", formatter, number, numFmtted,
|
||||
NumberFormat.Field.EXPONENT_SIGN, 9, 10);
|
||||
checkFormatWithField("exponent", formatter, number, numFmtted,
|
||||
NumberFormat.Field.EXPONENT, 10, 12);
|
||||
}
|
||||
|
||||
public void TestMissingFieldPositionsPerCent() {
|
||||
// Check PERCENT
|
||||
DecimalFormat percentFormat = (DecimalFormat) NumberFormat.getPercentInstance(ULocale.US);
|
||||
Number number = new Double(-0.986);
|
||||
String numberFormatted = percentFormat.format(number);
|
||||
checkFormatWithField("sign", percentFormat, number, numberFormatted,
|
||||
NumberFormat.Field.SIGN, 0, 1);
|
||||
checkFormatWithField("integer", percentFormat, number, numberFormatted,
|
||||
NumberFormat.Field.INTEGER, 1, 3);
|
||||
checkFormatWithField("percent", percentFormat, number, numberFormatted,
|
||||
NumberFormat.Field.PERCENT, 3, 4);
|
||||
}
|
||||
|
||||
public void TestMissingFieldPositionsPerCentPattern() {
|
||||
// Check PERCENT with more digits
|
||||
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
|
||||
DecimalFormat fmtPercent = new DecimalFormat("0.#####%", us_symbols);
|
||||
Number number = new Double(-0.986);
|
||||
String numFmtted = fmtPercent.format(number);
|
||||
|
||||
checkFormatWithField("sign", fmtPercent, number, numFmtted,
|
||||
NumberFormat.Field.SIGN, 0, 1);
|
||||
checkFormatWithField("integer", fmtPercent, number, numFmtted,
|
||||
NumberFormat.Field.INTEGER, 1, 3);
|
||||
checkFormatWithField("decimal separator", fmtPercent, number, numFmtted,
|
||||
NumberFormat.Field.DECIMAL_SEPARATOR, 3, 4);
|
||||
checkFormatWithField("fraction", fmtPercent, number, numFmtted,
|
||||
NumberFormat.Field.FRACTION, 4, 5);
|
||||
checkFormatWithField("percent", fmtPercent, number, numFmtted,
|
||||
NumberFormat.Field.PERCENT, 5, 6);
|
||||
}
|
||||
|
||||
public void TestMissingFieldPositionsPerMille() {
|
||||
// Check PERMILLE
|
||||
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
|
||||
DecimalFormat fmtPerMille = new DecimalFormat("0.######‰", us_symbols);
|
||||
Number numberPermille = new Double(-0.98654);
|
||||
String numFmtted = fmtPerMille.format(numberPermille);
|
||||
|
||||
checkFormatWithField("sign", fmtPerMille, numberPermille, numFmtted,
|
||||
NumberFormat.Field.SIGN, 0, 1);
|
||||
checkFormatWithField("integer", fmtPerMille, numberPermille, numFmtted,
|
||||
NumberFormat.Field.INTEGER, 1, 4);
|
||||
checkFormatWithField("decimal separator", fmtPerMille, numberPermille, numFmtted,
|
||||
NumberFormat.Field.DECIMAL_SEPARATOR, 4, 5);
|
||||
checkFormatWithField("fraction", fmtPerMille, numberPermille, numFmtted,
|
||||
NumberFormat.Field.FRACTION, 5, 7);
|
||||
checkFormatWithField("permille", fmtPerMille, numberPermille, numFmtted,
|
||||
NumberFormat.Field.PERMILLE, 7, 8);
|
||||
}
|
||||
|
||||
public void TestMissingFieldPositionsNegativeBigInt() {
|
||||
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
|
||||
DecimalFormat formatter = new DecimalFormat("0.#####E+0", us_symbols);
|
||||
Number number = new BigDecimal("-123456789987654321");
|
||||
String bigDecFmtted = formatter.format(number);
|
||||
|
||||
checkFormatWithField("sign", formatter, number, bigDecFmtted,
|
||||
NumberFormat.Field.SIGN, 0, 1);
|
||||
checkFormatWithField("integer", formatter, number, bigDecFmtted,
|
||||
NumberFormat.Field.INTEGER, 1, 2);
|
||||
checkFormatWithField("decimal separator", formatter, number, bigDecFmtted,
|
||||
NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3);
|
||||
checkFormatWithField("exponent symbol", formatter, number, bigDecFmtted,
|
||||
NumberFormat.Field.EXPONENT_SYMBOL, 8, 9);
|
||||
checkFormatWithField("exponent sign", formatter, number, bigDecFmtted,
|
||||
NumberFormat.Field.EXPONENT_SIGN, 9, 10);
|
||||
checkFormatWithField("exponent", formatter, number, bigDecFmtted,
|
||||
NumberFormat.Field.EXPONENT, 10, 12);
|
||||
}
|
||||
|
||||
public void TestMissingFieldPositionsNegativeLong() {
|
||||
Number number = new Long("-123456789987654321");
|
||||
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
|
||||
DecimalFormat formatter = new DecimalFormat("0.#####E+0", us_symbols);
|
||||
String longFmtted = formatter.format(number);
|
||||
|
||||
checkFormatWithField("sign", formatter, number, longFmtted,
|
||||
NumberFormat.Field.SIGN, 0, 1);
|
||||
checkFormatWithField("integer", formatter, number, longFmtted,
|
||||
NumberFormat.Field.INTEGER, 1, 2);
|
||||
checkFormatWithField("decimal separator", formatter, number, longFmtted,
|
||||
NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3);
|
||||
checkFormatWithField("exponent symbol", formatter, number, longFmtted,
|
||||
NumberFormat.Field.EXPONENT_SYMBOL, 8, 9);
|
||||
checkFormatWithField("exponent sign", formatter, number, longFmtted,
|
||||
NumberFormat.Field.EXPONENT_SIGN, 9, 10);
|
||||
checkFormatWithField("exponent", formatter, number, longFmtted,
|
||||
NumberFormat.Field.EXPONENT, 10, 12);
|
||||
}
|
||||
|
||||
public void TestMissingFieldPositionsPositiveBigDec() {
|
||||
// Check complex positive;negative pattern.
|
||||
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
|
||||
DecimalFormat fmtPosNegSign = new DecimalFormat("+0.####E+00;-0.#######E+0", us_symbols);
|
||||
Number positiveExp = new Double("9876543210");
|
||||
String posExpFormatted = fmtPosNegSign.format(positiveExp);
|
||||
|
||||
checkFormatWithField("sign", fmtPosNegSign, positiveExp, posExpFormatted,
|
||||
NumberFormat.Field.SIGN, 0, 1);
|
||||
checkFormatWithField("integer", fmtPosNegSign, positiveExp, posExpFormatted,
|
||||
NumberFormat.Field.INTEGER, 1, 2);
|
||||
checkFormatWithField("decimal separator", fmtPosNegSign, positiveExp, posExpFormatted,
|
||||
NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3);
|
||||
checkFormatWithField("fraction", fmtPosNegSign, positiveExp, posExpFormatted,
|
||||
NumberFormat.Field.FRACTION, 3, 7);
|
||||
checkFormatWithField("exponent symbol", fmtPosNegSign, positiveExp, posExpFormatted,
|
||||
NumberFormat.Field.EXPONENT_SYMBOL, 7, 8);
|
||||
checkFormatWithField("exponent sign", fmtPosNegSign, positiveExp, posExpFormatted,
|
||||
NumberFormat.Field.EXPONENT_SIGN, 8, 9);
|
||||
checkFormatWithField("exponent", fmtPosNegSign, positiveExp, posExpFormatted,
|
||||
NumberFormat.Field.EXPONENT, 9, 11);
|
||||
}
|
||||
|
||||
public void TestMissingFieldPositionsNegativeBigDec() {
|
||||
// Check complex positive;negative pattern.
|
||||
DecimalFormatSymbols us_symbols = new DecimalFormatSymbols(ULocale.US);
|
||||
DecimalFormat fmtPosNegSign = new DecimalFormat("+0.####E+00;-0.#######E+0", us_symbols);
|
||||
Number negativeExp = new BigDecimal("-0.000000987654321083");
|
||||
String negExpFormatted = fmtPosNegSign.format(negativeExp);
|
||||
|
||||
checkFormatWithField("sign", fmtPosNegSign, negativeExp, negExpFormatted,
|
||||
NumberFormat.Field.SIGN, 0, 1);
|
||||
checkFormatWithField("integer", fmtPosNegSign, negativeExp, negExpFormatted,
|
||||
NumberFormat.Field.INTEGER, 1, 2);
|
||||
checkFormatWithField("decimal separator", fmtPosNegSign, negativeExp, negExpFormatted,
|
||||
NumberFormat.Field.DECIMAL_SEPARATOR, 2, 3);
|
||||
checkFormatWithField("fraction", fmtPosNegSign, negativeExp, negExpFormatted,
|
||||
NumberFormat.Field.FRACTION, 3, 7);
|
||||
checkFormatWithField("exponent symbol", fmtPosNegSign, negativeExp, negExpFormatted,
|
||||
NumberFormat.Field.EXPONENT_SYMBOL, 7, 8);
|
||||
checkFormatWithField("exponent sign", fmtPosNegSign, negativeExp, negExpFormatted,
|
||||
NumberFormat.Field.EXPONENT_SIGN, 8, 9);
|
||||
checkFormatWithField("exponent", fmtPosNegSign, negativeExp, negExpFormatted,
|
||||
NumberFormat.Field.EXPONENT, 9, 11);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user