ICU-13177 Pointing DecimalFormat.java and CompactDecimalFormat.java at the new API. All tests are passing.
X-SVN-Rev: 40313
This commit is contained in:
parent
8cf6752ecb
commit
ca30fb66ec
@ -259,8 +259,8 @@ $**####,##0 1234 $***1\u00a0234 K
|
||||
// In J ICU adds padding as if 'EUR' is only 2 chars (2 * 0xa4)
|
||||
\u00a4\u00a4 **####0.00 433.0 EUR *433,00 JK
|
||||
// In J ICU adds padding as if 'EUR' is only 2 chars (2 * 0xa4)
|
||||
// S fails this one because the test code bypasses CurrencyUsage
|
||||
\u00a4\u00a4 **#######0 433.0 EUR *433,00 JKS
|
||||
// S and Q fail this one because the test code bypasses CurrencyUsage
|
||||
\u00a4\u00a4 **#######0 433.0 EUR *433,00 JKSQ
|
||||
|
||||
test padding and currencies
|
||||
begin
|
||||
@ -338,8 +338,8 @@ minIntegerDigits maxIntegerDigits minFractionDigits maxFractionDigits output bre
|
||||
// JDK gives E0 instead of allowing for unlimited precision
|
||||
// S obeys the maximum integer digits and returns .299792458E9
|
||||
0 0 0 0 2.99792458E8 KS
|
||||
// JDK and S give .299792E9
|
||||
0 1 0 5 2.9979E8 KS
|
||||
// JDK and S give .299792E9; Q gives 2.99792E8
|
||||
0 1 0 5 2.9979E8 KSQ
|
||||
// JDK gives 300E6
|
||||
0 3 0 0 299.792458E6 K
|
||||
// JDK gives 299.8E6 (maybe maxInt + maxFrac instead of minInt + maxFrac)?
|
||||
@ -356,12 +356,13 @@ minIntegerDigits maxIntegerDigits minFractionDigits maxFractionDigits output bre
|
||||
// JDK gives E0
|
||||
// S obeys the maximum integer digits
|
||||
0 0 1 0 2.99792458E8 KS
|
||||
// JDK gives .2998E9
|
||||
0 0 0 4 2.998E8 KS
|
||||
// JDK and S give .2998E9
|
||||
0 0 0 4 2.998E8 KSQ
|
||||
// S correctly formats this as 29.979246E7.
|
||||
// JDK uses 8 + 6 for significant digits instead of 2 + 6
|
||||
// J and C return 2.9979246E8.
|
||||
2 8 1 6 29.979246E7 CJK
|
||||
// TODO: Merge trunk
|
||||
2 8 1 6 29.979246E7 CJKQ
|
||||
// Treat max int digits > 8 as being the same as min int digits.
|
||||
// This behavior is not spelled out in the specification.
|
||||
// JDK fails here because it tries to use 9 + 6 = 15 sig digits.
|
||||
@ -405,12 +406,12 @@ begin
|
||||
format maxIntegerDigits output breaks
|
||||
123 1 3
|
||||
0 0 0
|
||||
// S ignores max integer if it is less than zero and prints "123"
|
||||
123 -2147483648 0 S
|
||||
// S and Q ignore max integer if it is less than zero and prints "123"
|
||||
123 -2147483648 0 SQ
|
||||
12345 1 5
|
||||
12345 -2147483648 0 S
|
||||
12345 -2147483648 0 SQ
|
||||
5.3 1 5.3
|
||||
5.3 -2147483648 .3 S
|
||||
5.3 -2147483648 .3 SQ
|
||||
|
||||
test patterns with zero
|
||||
set locale en
|
||||
@ -489,8 +490,9 @@ output grouping breaks grouping2 minGroupingDigits
|
||||
1,2345,6789 4
|
||||
1,23,45,6789 4 K 2
|
||||
1,23,45,6789 4 K 2 2
|
||||
// Q only supports minGrouping<=2
|
||||
123,456789 6 6 3
|
||||
123456789 6 JK 6 4
|
||||
123456789 6 JKQ 6 4
|
||||
|
||||
test multiplier setters
|
||||
set locale en_US
|
||||
@ -498,8 +500,10 @@ begin
|
||||
format multiplier output breaks
|
||||
23 -12 -276
|
||||
23 -1 -23
|
||||
// ICU4J and JDK throw exception on zero multiplier. ICU4C does not.
|
||||
23 0 23 JKS
|
||||
// ICU4J and JDK throw exception on zero multiplier.
|
||||
// ICU4C and S print 23.
|
||||
// Q multiplies by zero and prints 0.
|
||||
23 0 0 CJKS
|
||||
23 1 23
|
||||
23 12 276
|
||||
-23 12 -276
|
||||
@ -513,8 +517,9 @@ begin
|
||||
format output breaks
|
||||
-0.35 -0.25 K
|
||||
0.35 0.25 K
|
||||
0.39 0.5 K
|
||||
0.62 0.5 K
|
||||
// Q doesn't support mixing minFrac with roundingIncrement (prints 0.50).
|
||||
0.39 0.5 KQ
|
||||
0.62 0.5 KQ
|
||||
0.63 0.75 K
|
||||
|
||||
test padding setters
|
||||
@ -539,20 +544,19 @@ output breaks useScientific
|
||||
|
||||
test rounding mode setters
|
||||
set locale en_US
|
||||
set pattern 0.#
|
||||
set roundingIncrement 0.5
|
||||
set pattern 0.5
|
||||
begin
|
||||
format roundingMode output breaks
|
||||
1.24 halfUp 1 K
|
||||
1.24 halfUp 1.0 K
|
||||
1.25 halfUp 1.5 K
|
||||
1.25 halfDown 1 K
|
||||
1.25 halfDown 1.0 K
|
||||
1.26 halfDown 1.5 K
|
||||
1.25 halfEven 1 K
|
||||
1.25 halfEven 1.0 K
|
||||
-1.01 up -1.5 K
|
||||
-1.49 down -1 K
|
||||
-1.49 down -1.0 K
|
||||
1.01 up 1.5 K
|
||||
1.49 down 1 K
|
||||
-1.01 ceiling -1
|
||||
1.49 down 1.0 K
|
||||
-1.01 ceiling -1.0
|
||||
-1.49 floor -1.5
|
||||
|
||||
test currency usage setters
|
||||
@ -584,7 +588,7 @@ set locale en
|
||||
set currency USD
|
||||
begin
|
||||
pattern format output breaks
|
||||
# 123 123 S
|
||||
# 123 123 SQ
|
||||
// Currency rounding should always override the pattern.
|
||||
// K prints the currency in ISO format for some reason.
|
||||
\u00a4# 123 $123.00 K
|
||||
@ -659,7 +663,8 @@ begin
|
||||
format output breaks
|
||||
Inf [\u221e]
|
||||
-Inf (\u221e) K
|
||||
NaN NaN K
|
||||
// Q prints the affixes
|
||||
NaN NaN KQ
|
||||
|
||||
test nan and infinity with multiplication
|
||||
set locale en
|
||||
@ -680,10 +685,11 @@ Inf beforePrefix $$$\u221e$ K
|
||||
Inf afterPrefix $$$ \u221e$ K
|
||||
Inf beforeSuffix $$$\u221e $ K
|
||||
Inf afterSuffix $$$\u221e$ K
|
||||
NaN beforePrefix NaN K
|
||||
NaN afterPrefix NaN K
|
||||
NaN beforeSuffix NaN K
|
||||
NaN afterSuffix NaN K
|
||||
// Q gets $$$NaN$
|
||||
NaN beforePrefix NaN KQ
|
||||
NaN afterPrefix NaN KQ
|
||||
NaN beforeSuffix NaN KQ
|
||||
NaN afterSuffix NaN KQ
|
||||
|
||||
test apply formerly localized patterns
|
||||
begin
|
||||
@ -1540,8 +1546,9 @@ set maxSigDigits 2
|
||||
begin
|
||||
format output breaks
|
||||
// C and J get "1"
|
||||
// Q gets "1.0"
|
||||
// K gets "1.1" (??)
|
||||
0.975 0.98 CJK
|
||||
0.975 0.98 CJKQ
|
||||
|
||||
test lenient parse currency match
|
||||
// This test is for #13112
|
||||
|
@ -222,6 +222,13 @@ public class AffixPatternUtils {
|
||||
return output.length() - startLength;
|
||||
}
|
||||
|
||||
/** Version of {@link #escape} that returns a String. */
|
||||
public static String escape(CharSequence input) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
escape(input, sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the unescape state machine. Replaces the unquoted characters "-", "+", "%", and "‰"
|
||||
* with their localized equivalents. Replaces "¤", "¤¤", and "¤¤¤" with the three argument
|
||||
|
@ -184,6 +184,9 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
|
||||
|
||||
@Override
|
||||
public void multiplyBy(BigDecimal multiplicand) {
|
||||
if (isInfinite() || isZero() || isNaN()) {
|
||||
return;
|
||||
}
|
||||
BigDecimal temp = toBigDecimal();
|
||||
temp = temp.multiply(multiplicand);
|
||||
setToBigDecimal(temp);
|
||||
@ -519,7 +522,7 @@ public abstract class FormatQuantityBCD implements FormatQuantity {
|
||||
* @param n The value to consume.
|
||||
*/
|
||||
@Override
|
||||
public void setToBigDecimal(BigDecimal n) {
|
||||
public void setToBigDecimal(BigDecimal n) {
|
||||
setBcdToZero();
|
||||
flags = 0;
|
||||
if (n.signum() == -1) {
|
||||
|
@ -46,6 +46,9 @@ public interface Modifier {
|
||||
* Gets the prefix string associated with this modifier, defined as the string that will be
|
||||
* inserted at leftIndex when {@link #apply} is called.
|
||||
*
|
||||
* <p>TODO: Change this to appendPrefixTo(), or remove it entirely and do something different at
|
||||
* the call sites.
|
||||
*
|
||||
* @return The prefix string. Will not be null.
|
||||
*/
|
||||
public String getPrefix();
|
||||
@ -54,6 +57,9 @@ public interface Modifier {
|
||||
* Gets the prefix string associated with this modifier, defined as the string that will be
|
||||
* inserted at rightIndex when {@link #apply} is called.
|
||||
*
|
||||
* <p>TODO: Change this to appendPrefixTo(), or remove it entirely and do something different at
|
||||
* the call sites.
|
||||
*
|
||||
* @return The suffix string. Will not be null.
|
||||
*/
|
||||
public String getSuffix();
|
||||
@ -102,8 +108,8 @@ public interface Modifier {
|
||||
/**
|
||||
* A starter implementation with defaults for some of the basic methods.
|
||||
*
|
||||
* <p>Implements {@link PositiveNegativeModifier} only so that instances of this class can be used when
|
||||
* a {@link PositiveNegativeModifier} is required.
|
||||
* <p>Implements {@link PositiveNegativeModifier} only so that instances of this class can be used
|
||||
* when a {@link PositiveNegativeModifier} is required.
|
||||
*/
|
||||
public abstract static class BaseModifier extends Format.BeforeFormat
|
||||
implements Modifier, PositiveNegativeModifier {
|
||||
|
@ -8,6 +8,8 @@ import com.ibm.icu.impl.number.formatters.PaddingFormat;
|
||||
import com.ibm.icu.impl.number.formatters.PaddingFormat.PadPosition;
|
||||
import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
|
||||
import newapi.impl.AffixPatternProvider;
|
||||
|
||||
/**
|
||||
* Handles parsing and creation of the compact pattern string representation of a decimal format.
|
||||
*/
|
||||
@ -507,7 +509,8 @@ public class PatternString {
|
||||
if (!ignoreRounding) {
|
||||
properties.setMinimumFractionDigits(minFrac);
|
||||
properties.setMaximumFractionDigits(positive.maximumFractionDigits);
|
||||
properties.setRoundingIncrement(positive.rounding.toBigDecimal());
|
||||
properties.setRoundingIncrement(
|
||||
positive.rounding.toBigDecimal().setScale(positive.minimumFractionDigits));
|
||||
} else {
|
||||
properties.setMinimumFractionDigits(Properties.DEFAULT_MINIMUM_FRACTION_DIGITS);
|
||||
properties.setMaximumFractionDigits(Properties.DEFAULT_MAXIMUM_FRACTION_DIGITS);
|
||||
@ -557,8 +560,8 @@ public class PatternString {
|
||||
}
|
||||
|
||||
// Compute the affix patterns (required for both padding and affixes)
|
||||
String posPrefix = ppr.getString(LdmlPatternInfo.PatternParseResult.POS_PREFIX);
|
||||
String posSuffix = ppr.getString(LdmlPatternInfo.PatternParseResult.POS_SUFFIX);
|
||||
String posPrefix = ppr.getString(AffixPatternProvider.Flags.PREFIX);
|
||||
String posSuffix = ppr.getString(0);
|
||||
|
||||
// Padding settings
|
||||
if (positive.paddingEndpoints != 0) {
|
||||
@ -568,7 +571,7 @@ public class PatternString {
|
||||
+ AffixPatternUtils.unescapedLength(posPrefix)
|
||||
+ AffixPatternUtils.unescapedLength(posSuffix);
|
||||
properties.setFormatWidth(paddingWidth);
|
||||
String rawPaddingString = ppr.getString(LdmlPatternInfo.PatternParseResult.POS_PADDING);
|
||||
String rawPaddingString = ppr.getString(AffixPatternProvider.Flags.PADDING);
|
||||
if (rawPaddingString.length() == 1) {
|
||||
properties.setPadString(rawPaddingString);
|
||||
} else if (rawPaddingString.length() == 2) {
|
||||
@ -594,8 +597,11 @@ public class PatternString {
|
||||
properties.setPositivePrefixPattern(posPrefix);
|
||||
properties.setPositiveSuffixPattern(posSuffix);
|
||||
if (negative != null) {
|
||||
properties.setNegativePrefixPattern(ppr.getString(LdmlPatternInfo.PatternParseResult.NEG_PREFIX));
|
||||
properties.setNegativeSuffixPattern(ppr.getString(LdmlPatternInfo.PatternParseResult.NEG_SUFFIX));
|
||||
properties.setNegativePrefixPattern(
|
||||
ppr.getString(
|
||||
AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN | AffixPatternProvider.Flags.PREFIX));
|
||||
properties.setNegativeSuffixPattern(
|
||||
ppr.getString(AffixPatternProvider.Flags.NEGATIVE_SUBPATTERN));
|
||||
} else {
|
||||
properties.setNegativePrefixPattern(null);
|
||||
properties.setNegativeSuffixPattern(null);
|
||||
|
@ -32,7 +32,6 @@ import com.ibm.icu.impl.number.rounders.MagnitudeRounder;
|
||||
import com.ibm.icu.impl.number.rounders.SignificantDigitsRounder;
|
||||
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
|
||||
import com.ibm.icu.text.CurrencyPluralInfo;
|
||||
import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
|
||||
import com.ibm.icu.text.MeasureFormat.FormatWidth;
|
||||
import com.ibm.icu.text.PluralRules;
|
||||
import com.ibm.icu.util.Currency;
|
||||
@ -121,7 +120,6 @@ public class Properties
|
||||
private transient RoundingMode roundingMode;
|
||||
private transient int secondaryGroupingSize;
|
||||
private transient boolean signAlwaysShown;
|
||||
private transient SignificantDigitsMode significantDigitsMode;
|
||||
|
||||
/*--------------------------------------------------------------------------------------------+/
|
||||
/| IMPORTANT! |/
|
||||
@ -182,7 +180,6 @@ public class Properties
|
||||
roundingMode = DEFAULT_ROUNDING_MODE;
|
||||
secondaryGroupingSize = DEFAULT_SECONDARY_GROUPING_SIZE;
|
||||
signAlwaysShown = DEFAULT_SIGN_ALWAYS_SHOWN;
|
||||
significantDigitsMode = DEFAULT_SIGNIFICANT_DIGITS_MODE;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -232,7 +229,6 @@ public class Properties
|
||||
roundingMode = other.roundingMode;
|
||||
secondaryGroupingSize = other.secondaryGroupingSize;
|
||||
signAlwaysShown = other.signAlwaysShown;
|
||||
significantDigitsMode = other.significantDigitsMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -283,7 +279,6 @@ public class Properties
|
||||
eq = eq && _equalsHelper(roundingMode, other.roundingMode);
|
||||
eq = eq && _equalsHelper(secondaryGroupingSize, other.secondaryGroupingSize);
|
||||
eq = eq && _equalsHelper(signAlwaysShown, other.signAlwaysShown);
|
||||
eq = eq && _equalsHelper(significantDigitsMode, other.significantDigitsMode);
|
||||
return eq;
|
||||
}
|
||||
|
||||
@ -348,7 +343,6 @@ public class Properties
|
||||
hashCode ^= _hashCodeHelper(roundingMode);
|
||||
hashCode ^= _hashCodeHelper(secondaryGroupingSize);
|
||||
hashCode ^= _hashCodeHelper(signAlwaysShown);
|
||||
hashCode ^= _hashCodeHelper(significantDigitsMode);
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@ -627,11 +621,6 @@ public class Properties
|
||||
return signAlwaysShown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SignificantDigitsMode getSignificantDigitsMode() {
|
||||
return significantDigitsMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return _hashCode();
|
||||
@ -960,12 +949,6 @@ public class Properties
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties setSignificantDigitsMode(SignificantDigitsMode significantDigitsMode) {
|
||||
this.significantDigitsMode = significantDigitsMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
@ -24,7 +24,6 @@ import com.ibm.icu.impl.number.modifiers.PositiveNegativeAffixModifier;
|
||||
import com.ibm.icu.impl.number.rounders.SignificantDigitsRounder;
|
||||
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
|
||||
import com.ibm.icu.text.CompactDecimalFormat.CompactType;
|
||||
import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
|
||||
import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
import com.ibm.icu.text.NumberFormat;
|
||||
import com.ibm.icu.text.NumberingSystem;
|
||||
@ -104,8 +103,6 @@ public class CompactDecimalFormat extends Format.BeforeFormat {
|
||||
|
||||
private static final int DEFAULT_MIN_SIG = 1;
|
||||
private static final int DEFAULT_MAX_SIG = 2;
|
||||
private static final SignificantDigitsMode DEFAULT_SIG_MODE =
|
||||
SignificantDigitsMode.OVERRIDE_MAXIMUM_FRACTION;
|
||||
|
||||
private static final ThreadLocal<Properties> threadLocalProperties =
|
||||
new ThreadLocal<Properties>() {
|
||||
@ -127,12 +124,10 @@ public class CompactDecimalFormat extends Format.BeforeFormat {
|
||||
if (rounder == null) {
|
||||
int _minSig = properties.getMinimumSignificantDigits();
|
||||
int _maxSig = properties.getMaximumSignificantDigits();
|
||||
SignificantDigitsMode _mode = properties.getSignificantDigitsMode();
|
||||
Properties rprops = threadLocalProperties.get().clear();
|
||||
// Settings needing possible override:
|
||||
rprops.setMinimumSignificantDigits(_minSig > 0 ? _minSig : DEFAULT_MIN_SIG);
|
||||
rprops.setMaximumSignificantDigits(_maxSig > 0 ? _maxSig : DEFAULT_MAX_SIG);
|
||||
rprops.setSignificantDigitsMode(_mode != null ? _mode : DEFAULT_SIG_MODE);
|
||||
// TODO: Should copyFrom() be used instead? It requires a cast.
|
||||
// Settings to copy verbatim:
|
||||
rprops.setRoundingMode(properties.getRoundingMode());
|
||||
|
@ -17,16 +17,36 @@ public class SimpleModifier extends Modifier.BaseModifier {
|
||||
private final Field field;
|
||||
private final boolean strong;
|
||||
|
||||
private final int prefixLength;
|
||||
private final int suffixOffset;
|
||||
private final int suffixLength;
|
||||
|
||||
private static final int ARG_NUM_LIMIT = 0x100;
|
||||
|
||||
/** Creates a modifier that uses the SimpleFormatter string formats. */
|
||||
public SimpleModifier(String compiledPattern, Field field, boolean strong) {
|
||||
this.compiledPattern = (compiledPattern == null) ? "\u0001\u0000" : compiledPattern;
|
||||
this.field = field;
|
||||
this.strong = strong;
|
||||
|
||||
assert SimpleFormatterImpl.getArgumentLimit(compiledPattern) == 1;
|
||||
if (compiledPattern.charAt(1) != '\u0000') {
|
||||
prefixLength = compiledPattern.charAt(1) - ARG_NUM_LIMIT;
|
||||
suffixOffset = 3 + prefixLength;
|
||||
} else {
|
||||
prefixLength = 0;
|
||||
suffixOffset = 2;
|
||||
}
|
||||
if (3 + prefixLength < compiledPattern.length()) {
|
||||
suffixLength = compiledPattern.charAt(suffixOffset) - ARG_NUM_LIMIT;
|
||||
} else {
|
||||
suffixLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
|
||||
return formatAsPrefixSuffix(compiledPattern, output, leftIndex, rightIndex, field);
|
||||
return formatAsPrefixSuffix(output, leftIndex, rightIndex, field);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -36,14 +56,18 @@ public class SimpleModifier extends Modifier.BaseModifier {
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
// TODO: Implement this when MeasureFormat is ready.
|
||||
throw new UnsupportedOperationException();
|
||||
if (prefixLength == 0) {
|
||||
return "";
|
||||
}
|
||||
return compiledPattern.substring(2, 2 + prefixLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSuffix() {
|
||||
// TODO: Implement this when MeasureFormat is ready.
|
||||
throw new UnsupportedOperationException();
|
||||
if (suffixLength == 0) {
|
||||
return "";
|
||||
}
|
||||
return compiledPattern.substring(1 + suffixOffset, 1 + suffixOffset + suffixLength);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,38 +81,26 @@ public class SimpleModifier extends Modifier.BaseModifier {
|
||||
*
|
||||
* <p>This is well-defined only for patterns with exactly one argument.
|
||||
*
|
||||
* @param compiledPattern Compiled form of a pattern string.
|
||||
* @param result The StringBuilder containing the value argument.
|
||||
* @param startIndex The left index of the value within the string builder.
|
||||
* @param endIndex The right index of the value within the string builder.
|
||||
* @return The number of characters (UTF-16 code points) that were added to the StringBuilder.
|
||||
*/
|
||||
public static int formatAsPrefixSuffix(
|
||||
String compiledPattern,
|
||||
NumberStringBuilder result,
|
||||
int startIndex,
|
||||
int endIndex,
|
||||
Field field) {
|
||||
public int formatAsPrefixSuffix(
|
||||
NumberStringBuilder result, int startIndex, int endIndex, Field field) {
|
||||
assert SimpleFormatterImpl.getArgumentLimit(compiledPattern) == 1;
|
||||
int ARG_NUM_LIMIT = 0x100;
|
||||
int length = 0, offset = 2;
|
||||
if (compiledPattern.charAt(1) != '\u0000') {
|
||||
int prefixLength = compiledPattern.charAt(1) - ARG_NUM_LIMIT;
|
||||
if (result != null) {
|
||||
result.insert(startIndex, compiledPattern, 2, 2 + prefixLength, field);
|
||||
}
|
||||
length += prefixLength;
|
||||
offset = 3 + prefixLength;
|
||||
if (prefixLength > 0) {
|
||||
result.insert(startIndex, compiledPattern, 2, 2 + prefixLength, field);
|
||||
}
|
||||
if (offset < compiledPattern.length()) {
|
||||
int suffixLength = compiledPattern.charAt(offset) - ARG_NUM_LIMIT;
|
||||
if (result != null) {
|
||||
result.insert(
|
||||
endIndex + length, compiledPattern, offset + 1, offset + suffixLength + 1, field);
|
||||
}
|
||||
length += suffixLength;
|
||||
if (suffixLength > 0) {
|
||||
result.insert(
|
||||
endIndex + prefixLength,
|
||||
compiledPattern,
|
||||
1 + suffixOffset,
|
||||
1 + suffixOffset + suffixLength,
|
||||
field);
|
||||
}
|
||||
return length;
|
||||
return prefixLength + suffixLength;
|
||||
}
|
||||
|
||||
/** TODO: Move this to a test file somewhere, once we figure out what to do with the method. */
|
||||
@ -108,8 +120,8 @@ public class SimpleModifier extends Modifier.BaseModifier {
|
||||
SimpleFormatterImpl.compileToStringMinMaxArguments(pattern, new StringBuilder(), 1, 1);
|
||||
NumberStringBuilder output = new NumberStringBuilder();
|
||||
output.append((String) outputs[j][0], null);
|
||||
formatAsPrefixSuffix(
|
||||
compiledPattern, output, (Integer) outputs[j][1], (Integer) outputs[j][2], null);
|
||||
new SimpleModifier(compiledPattern, null, false)
|
||||
.apply(output, (Integer) outputs[j][1], (Integer) outputs[j][2]);
|
||||
String expected = expecteds[j][i];
|
||||
String actual = output.toString();
|
||||
assert expected.equals(actual);
|
||||
|
@ -7,7 +7,6 @@ import java.math.RoundingMode;
|
||||
import com.ibm.icu.impl.number.FormatQuantity;
|
||||
import com.ibm.icu.impl.number.Properties;
|
||||
import com.ibm.icu.impl.number.Rounder;
|
||||
import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
|
||||
|
||||
public class SignificantDigitsRounder extends Rounder {
|
||||
|
||||
@ -65,28 +64,13 @@ public class SignificantDigitsRounder extends Rounder {
|
||||
* @return The property bag, for chaining.
|
||||
*/
|
||||
public IProperties setMaximumSignificantDigits(int maximumSignificantDigits);
|
||||
|
||||
static SignificantDigitsMode DEFAULT_SIGNIFICANT_DIGITS_MODE = null;
|
||||
|
||||
/** @see #setSignificantDigitsMode */
|
||||
public SignificantDigitsMode getSignificantDigitsMode();
|
||||
|
||||
/**
|
||||
* Sets the strategy used when reconciling significant digits versus integer and fraction
|
||||
* lengths.
|
||||
*
|
||||
* @param significantDigitsMode One of the options from {@link SignificantDigitsMode}.
|
||||
* @return The property bag, for chaining.
|
||||
*/
|
||||
public IProperties setSignificantDigitsMode(SignificantDigitsMode significantDigitsMode);
|
||||
}
|
||||
|
||||
public static boolean useSignificantDigits(IProperties properties) {
|
||||
return properties.getMinimumSignificantDigits()
|
||||
!= IProperties.DEFAULT_MINIMUM_SIGNIFICANT_DIGITS
|
||||
|| properties.getMaximumSignificantDigits()
|
||||
!= IProperties.DEFAULT_MAXIMUM_SIGNIFICANT_DIGITS
|
||||
|| properties.getSignificantDigitsMode() != IProperties.DEFAULT_SIGNIFICANT_DIGITS_MODE;
|
||||
!= IProperties.DEFAULT_MAXIMUM_SIGNIFICANT_DIGITS;
|
||||
}
|
||||
|
||||
public static SignificantDigitsRounder getInstance(IProperties properties) {
|
||||
@ -95,7 +79,6 @@ public class SignificantDigitsRounder extends Rounder {
|
||||
|
||||
private final int minSig;
|
||||
private final int maxSig;
|
||||
private final SignificantDigitsMode mode;
|
||||
|
||||
private SignificantDigitsRounder(IProperties properties) {
|
||||
super(properties);
|
||||
@ -103,8 +86,6 @@ public class SignificantDigitsRounder extends Rounder {
|
||||
int _maxSig = properties.getMaximumSignificantDigits();
|
||||
minSig = _minSig < 1 ? 1 : _minSig > 1000 ? 1000 : _minSig;
|
||||
maxSig = _maxSig < 0 ? 1000 : _maxSig < minSig ? minSig : _maxSig > 1000 ? 1000 : _maxSig;
|
||||
SignificantDigitsMode _mode = properties.getSignificantDigitsMode();
|
||||
mode = _mode == null ? SignificantDigitsMode.OVERRIDE_MAXIMUM_FRACTION : _mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -123,47 +104,7 @@ public class SignificantDigitsRounder extends Rounder {
|
||||
magMaxSig = effectiveMag - maxSig;
|
||||
|
||||
// Step 1: pick the rounding magnitude and apply.
|
||||
int roundingMagnitude;
|
||||
switch (mode) {
|
||||
case OVERRIDE_MAXIMUM_FRACTION:
|
||||
// Always round to maxSig.
|
||||
// Of the six possible orders:
|
||||
// Case 1: minSig, maxSig, minFrac, maxFrac -- maxSig wins
|
||||
// Case 2: minSig, minFrac, maxSig, maxFrac -- maxSig wins
|
||||
// Case 3: minSig, minFrac, maxFrac, maxSig -- maxSig wins
|
||||
// Case 4: minFrac, minSig, maxSig, maxFrac -- maxSig wins
|
||||
// Case 5: minFrac, minSig, maxFrac, maxSig -- maxSig wins
|
||||
// Case 6: minFrac, maxFrac, minSig, maxSig -- maxSig wins
|
||||
roundingMagnitude = magMaxSig;
|
||||
break;
|
||||
case RESPECT_MAXIMUM_FRACTION:
|
||||
// Round to the strongest of maxFrac, maxInt, and maxSig.
|
||||
// Of the six possible orders:
|
||||
// Case 1: minSig, maxSig, minFrac, maxFrac -- maxSig wins
|
||||
// Case 2: minSig, minFrac, maxSig, maxFrac -- maxSig wins
|
||||
// Case 3: minSig, minFrac, maxFrac, maxSig -- maxFrac wins --> differs from default
|
||||
// Case 4: minFrac, minSig, maxSig, maxFrac -- maxSig wins
|
||||
// Case 5: minFrac, minSig, maxFrac, maxSig -- maxFrac wins --> differs from default
|
||||
// Case 6: minFrac, maxFrac, minSig, maxSig -- maxFrac wins --> differs from default
|
||||
//
|
||||
// Math.max() picks the rounding magnitude farthest to the left (most significant).
|
||||
// Math.min() picks the rounding magnitude farthest to the right (least significant).
|
||||
roundingMagnitude = Math.max(-maxFrac, magMaxSig);
|
||||
break;
|
||||
case ENSURE_MINIMUM_SIGNIFICANT:
|
||||
// Round to the strongest of maxFrac and maxSig, and always ensure minSig.
|
||||
// Of the six possible orders:
|
||||
// Case 1: minSig, maxSig, minFrac, maxFrac -- maxSig wins
|
||||
// Case 2: minSig, minFrac, maxSig, maxFrac -- maxSig wins
|
||||
// Case 3: minSig, minFrac, maxFrac, maxSig -- maxFrac wins --> differs from default
|
||||
// Case 4: minFrac, minSig, maxSig, maxFrac -- maxSig wins
|
||||
// Case 5: minFrac, minSig, maxFrac, maxSig -- maxFrac wins --> differs from default
|
||||
// Case 6: minFrac, maxFrac, minSig, maxSig -- minSig wins --> differs from default
|
||||
roundingMagnitude = Math.min(magMinSig, Math.max(-maxFrac, magMaxSig));
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
int roundingMagnitude = magMaxSig;
|
||||
input.roundToMagnitude(roundingMagnitude, mathContext);
|
||||
|
||||
// In case magnitude changed:
|
||||
@ -177,23 +118,8 @@ public class SignificantDigitsRounder extends Rounder {
|
||||
magMaxSig = effectiveMag - maxSig;
|
||||
|
||||
// Step 2: pick the number of visible digits.
|
||||
switch (mode) {
|
||||
case OVERRIDE_MAXIMUM_FRACTION:
|
||||
// Ensure minSig is always displayed.
|
||||
input.setIntegerLength(minInt, maxInt);
|
||||
input.setFractionLength(Math.max(minFrac, -magMinSig), Integer.MAX_VALUE);
|
||||
break;
|
||||
case RESPECT_MAXIMUM_FRACTION:
|
||||
// Ensure minSig is displayed, unless doing so is in violation of maxFrac.
|
||||
input.setIntegerLength(minInt, maxInt);
|
||||
input.setFractionLength(Math.min(maxFrac, Math.max(minFrac, -magMinSig)), maxFrac);
|
||||
break;
|
||||
case ENSURE_MINIMUM_SIGNIFICANT:
|
||||
// Follow minInt/minFrac, but ensure all digits are allowed to be visible.
|
||||
input.setIntegerLength(minInt, maxInt);
|
||||
input.setFractionLength(minFrac, Integer.MAX_VALUE);
|
||||
break;
|
||||
}
|
||||
input.setIntegerLength(minInt, maxInt);
|
||||
input.setFractionLength(Math.max(minFrac, -magMinSig), Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -201,6 +127,5 @@ public class SignificantDigitsRounder extends Rounder {
|
||||
super.export(properties);
|
||||
properties.setMinimumSignificantDigits(minSig);
|
||||
properties.setMaximumSignificantDigits(maxSig);
|
||||
properties.setSignificantDigitsMode(mode);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ package com.ibm.icu.text;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.ibm.icu.impl.number.PatternString;
|
||||
import com.ibm.icu.impl.number.Properties;
|
||||
import com.ibm.icu.util.CurrencyAmount;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
@ -121,17 +120,13 @@ public class CompactDecimalFormat extends DecimalFormat {
|
||||
* @param style the compact style
|
||||
*/
|
||||
CompactDecimalFormat(ULocale locale, CompactStyle style) {
|
||||
// Use the locale's default pattern
|
||||
String pattern = getPattern(locale, 0);
|
||||
// Minimal properties: let the non-shim code path do most of the logic for us.
|
||||
symbols = DecimalFormatSymbols.getInstance(locale);
|
||||
properties = new Properties();
|
||||
properties.setCompactStyle(style);
|
||||
properties.setGroupingSize(-2); // do not forward grouping information
|
||||
properties.setMinimumGroupingDigits(2);
|
||||
exportedProperties = new Properties();
|
||||
setPropertiesFromPattern(pattern, PatternString.IGNORE_ROUNDING_ALWAYS);
|
||||
if (style == CompactStyle.SHORT) {
|
||||
// TODO: This was setGroupingUsed(false) in ICU 58. Is it okay that I changed it for ICU 59?
|
||||
properties.setMinimumGroupingDigits(2);
|
||||
}
|
||||
refreshFormatter();
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,6 @@ import java.text.FieldPosition;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
|
||||
import com.ibm.icu.impl.number.Endpoint;
|
||||
import com.ibm.icu.impl.number.Format.SingularFormat;
|
||||
import com.ibm.icu.impl.number.FormatQuantity4;
|
||||
import com.ibm.icu.impl.number.Parse;
|
||||
import com.ibm.icu.impl.number.PatternString;
|
||||
import com.ibm.icu.impl.number.Properties;
|
||||
@ -33,6 +30,12 @@ import com.ibm.icu.util.CurrencyAmount;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
import com.ibm.icu.util.ULocale.Category;
|
||||
|
||||
import newapi.NumberFormatter.LocalizedNumberFormatter;
|
||||
import newapi.NumberFormatter.NumberFormatterResult;
|
||||
import newapi.impl.MacroProps;
|
||||
import newapi.impl.NumberFormatterImpl;
|
||||
import newapi.impl.NumberPropertyMapper;
|
||||
|
||||
/**
|
||||
* {@icuenhanced java.text.DecimalFormat}.{@icu _usage_} <code>DecimalFormat</code> is the primary
|
||||
* concrete subclass of {@link NumberFormat}. It has a variety of features designed to make it
|
||||
@ -107,9 +110,8 @@ import com.ibm.icu.util.ULocale.Category;
|
||||
* digits are shown. This is most common in scientific notation.
|
||||
* </ol>
|
||||
*
|
||||
* <p>It is possible to specify both a magnitude and a number of significant digits. If used
|
||||
* together, the <em>significant digits mode</em> determines how conflicts between fraction digits
|
||||
* and signiciant digits are resolved. For more information, see {@link #setSignificantDigitsMode}.
|
||||
* <p>It is not possible to specify more than one rounding strategy. For example, setting a rounding
|
||||
* increment in conjunction with significant digits results in undefined behavior.
|
||||
*
|
||||
* <p>It is also possible to specify the <em>rounding mode</em> to use. The default rounding mode is
|
||||
* "half even", which rounds numbers to their closest increment, with ties broken in favor of
|
||||
@ -265,7 +267,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* #format} method uses the formatter directly without needing to synchronize. Volatile because
|
||||
* threads may read and write at the same time.
|
||||
*/
|
||||
transient volatile SingularFormat formatter;
|
||||
transient volatile LocalizedNumberFormatter formatter;
|
||||
|
||||
/**
|
||||
* The effective properties as exported from the formatter object. Volatile because threads may
|
||||
@ -683,9 +685,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
*/
|
||||
@Override
|
||||
public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
|
||||
FormatQuantity4 fq = new FormatQuantity4(number);
|
||||
formatter.format(fq, result, fieldPosition);
|
||||
fq.populateUFieldPosition(fieldPosition);
|
||||
NumberFormatterResult output = formatter.format(number);
|
||||
output.populateFieldPosition(fieldPosition, result.length());
|
||||
output.appendTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -696,9 +698,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
*/
|
||||
@Override
|
||||
public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
|
||||
FormatQuantity4 fq = new FormatQuantity4(number);
|
||||
formatter.format(fq, result, fieldPosition);
|
||||
fq.populateUFieldPosition(fieldPosition);
|
||||
NumberFormatterResult output = formatter.format(number);
|
||||
output.populateFieldPosition(fieldPosition, result.length());
|
||||
output.appendTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -709,9 +711,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
*/
|
||||
@Override
|
||||
public StringBuffer format(BigInteger number, StringBuffer result, FieldPosition fieldPosition) {
|
||||
FormatQuantity4 fq = new FormatQuantity4(number);
|
||||
formatter.format(fq, result, fieldPosition);
|
||||
fq.populateUFieldPosition(fieldPosition);
|
||||
NumberFormatterResult output = formatter.format(number);
|
||||
output.populateFieldPosition(fieldPosition, result.length());
|
||||
output.appendTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -723,9 +725,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
@Override
|
||||
public StringBuffer format(
|
||||
java.math.BigDecimal number, StringBuffer result, FieldPosition fieldPosition) {
|
||||
FormatQuantity4 fq = new FormatQuantity4(number);
|
||||
formatter.format(fq, result, fieldPosition);
|
||||
fq.populateUFieldPosition(fieldPosition);
|
||||
NumberFormatterResult output = formatter.format(number);
|
||||
output.populateFieldPosition(fieldPosition, result.length());
|
||||
output.appendTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -736,9 +738,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
*/
|
||||
@Override
|
||||
public StringBuffer format(BigDecimal number, StringBuffer result, FieldPosition fieldPosition) {
|
||||
FormatQuantity4 fq = new FormatQuantity4(number.toBigDecimal());
|
||||
formatter.format(fq, result, fieldPosition);
|
||||
fq.populateUFieldPosition(fieldPosition);
|
||||
NumberFormatterResult output = formatter.format(number);
|
||||
output.populateFieldPosition(fieldPosition, result.length());
|
||||
output.appendTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -751,9 +753,8 @@ public class DecimalFormat extends NumberFormat {
|
||||
public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
|
||||
if (!(obj instanceof Number)) throw new IllegalArgumentException();
|
||||
Number number = (Number) obj;
|
||||
FormatQuantity4 fq = new FormatQuantity4(number);
|
||||
AttributedCharacterIterator result = formatter.formatToCharacterIterator(fq);
|
||||
return result;
|
||||
NumberFormatterResult output = formatter.format(number);
|
||||
return output.toAttributedCharacterIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -763,27 +764,9 @@ public class DecimalFormat extends NumberFormat {
|
||||
*/
|
||||
@Override
|
||||
public StringBuffer format(CurrencyAmount currAmt, StringBuffer toAppendTo, FieldPosition pos) {
|
||||
// TODO: This is ugly (although not as ugly as it was in ICU 58).
|
||||
// Currency should be a free parameter, not in property bag. Fix in ICU 60.
|
||||
Properties cprops = threadLocalProperties.get();
|
||||
SingularFormat fmt = null;
|
||||
synchronized (this) {
|
||||
// Use the pre-compiled formatter if possible. Otherwise, copy the properties
|
||||
// and build our own formatter.
|
||||
// TODO: Consider using a static format path here.
|
||||
if (currAmt.getCurrency().equals(properties.getCurrency())) {
|
||||
fmt = formatter;
|
||||
} else {
|
||||
cprops.copyFrom(properties);
|
||||
}
|
||||
}
|
||||
if (fmt == null) {
|
||||
cprops.setCurrency(currAmt.getCurrency());
|
||||
fmt = Endpoint.fromBTA(cprops, symbols);
|
||||
}
|
||||
FormatQuantity4 fq = new FormatQuantity4(currAmt.getNumber());
|
||||
fmt.format(fq, toAppendTo, pos);
|
||||
fq.populateUFieldPosition(pos);
|
||||
NumberFormatterResult output = formatter.format(currAmt);
|
||||
output.populateFieldPosition(pos, toAppendTo.length());
|
||||
output.appendTo(toAppendTo);
|
||||
return toAppendTo;
|
||||
}
|
||||
|
||||
@ -815,8 +798,11 @@ public class DecimalFormat extends NumberFormat {
|
||||
@Override
|
||||
public CurrencyAmount parseCurrency(CharSequence text, ParsePosition parsePosition) {
|
||||
try {
|
||||
// TODO(sffc): Make this thread-safe
|
||||
CurrencyAmount result = Parse.parseCurrency(text, parsePosition, properties, symbols);
|
||||
Properties pprops = threadLocalProperties.get();
|
||||
synchronized (this) {
|
||||
pprops.copyFrom(properties);
|
||||
}
|
||||
CurrencyAmount result = Parse.parseCurrency(text, parsePosition, pprops, symbols);
|
||||
if (result == null) return null;
|
||||
Number number = result.getNumber();
|
||||
// Backwards compatibility: return com.ibm.icu.math.BigDecimal
|
||||
@ -872,8 +858,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized String getPositivePrefix() {
|
||||
String result = exportedProperties.getPositivePrefix();
|
||||
return (result == null) ? "" : result;
|
||||
return formatter.format(1).getPrefix();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -910,8 +895,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized String getNegativePrefix() {
|
||||
String result = exportedProperties.getNegativePrefix();
|
||||
return (result == null) ? "" : result;
|
||||
return formatter.format(-1).getPrefix();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -948,8 +932,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized String getPositiveSuffix() {
|
||||
String result = exportedProperties.getPositiveSuffix();
|
||||
return (result == null) ? "" : result;
|
||||
return formatter.format(1).getSuffix();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -986,8 +969,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized String getNegativeSuffix() {
|
||||
String result = exportedProperties.getNegativeSuffix();
|
||||
return (result == null) ? "" : result;
|
||||
return formatter.format(-1).getSuffix();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1516,7 +1498,6 @@ public class DecimalFormat extends NumberFormat {
|
||||
} else {
|
||||
properties.setMinimumSignificantDigits(Properties.DEFAULT_MINIMUM_SIGNIFICANT_DIGITS);
|
||||
properties.setMaximumSignificantDigits(Properties.DEFAULT_MAXIMUM_SIGNIFICANT_DIGITS);
|
||||
properties.setSignificantDigitsMode(null);
|
||||
}
|
||||
refreshFormatter();
|
||||
}
|
||||
@ -1545,7 +1526,6 @@ public class DecimalFormat extends NumberFormat {
|
||||
* and then you set maxInt=3, then minInt will be changed to 3.
|
||||
*
|
||||
* @param value The minimum number of significant digits to display.
|
||||
* @see #setSignificantDigitsMode
|
||||
* @category Rounding
|
||||
* @stable ICU 3.0
|
||||
*/
|
||||
@ -1588,7 +1568,6 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @see #setRoundingMode
|
||||
* @see #setRoundingIncrement
|
||||
* @see #setMaximumFractionDigits
|
||||
* @see #setSignificantDigitsMode
|
||||
* @category Rounding
|
||||
* @stable ICU 3.0
|
||||
*/
|
||||
@ -1601,60 +1580,6 @@ public class DecimalFormat extends NumberFormat {
|
||||
refreshFormatter();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@icu} Returns the current significant digits mode.
|
||||
*
|
||||
* @see #setSignificantDigitsMode
|
||||
* @category Rounding
|
||||
* @internal
|
||||
* @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
|
||||
*/
|
||||
@Deprecated
|
||||
public synchronized SignificantDigitsMode getSignificantDigitsMode() {
|
||||
return exportedProperties.getSignificantDigitsMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@icu} <strong>Rounding and Digit Limits:</strong> Sets the strategy used for resolving
|
||||
* minimum/maximum significant digits when minimum/maximum integer and/or fraction digits are
|
||||
* specified. There are three modes:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Mode A: OVERRIDE_MAXIMUM_FRACTION. This is the default. Settings in maximum fraction are
|
||||
* ignored.
|
||||
* <li>Mode B: RESPECT_MAXIMUM_FRACTION. Round to maximum fraction even if doing so will prevent
|
||||
* minimum significant from being respected.
|
||||
* <li>Mode C: ENSURE_MINIMUM_SIGNIFICANT. Respect maximum fraction, but always ensure that
|
||||
* minimum significant digits are shown.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The following table illustrates the difference. Below, minFrac=1, maxFrac=2, minSig=3, and
|
||||
* maxSig=4:
|
||||
*
|
||||
* <pre>
|
||||
* Mode A | Mode B | Mode C
|
||||
* ---------+----------+----------
|
||||
* 12340.0 | 12340.0 | 12340.0
|
||||
* 1234.0 | 1234.0 | 1234.0
|
||||
* 123.4 | 123.4 | 123.4
|
||||
* 12.34 | 12.34 | 12.34
|
||||
* 1.234 | 1.23 | 1.23
|
||||
* 0.1234 | 0.12 | 0.123
|
||||
* 0.01234 | 0.01 | 0.0123
|
||||
* 0.001234 | 0.00 | 0.00123
|
||||
* </pre>
|
||||
*
|
||||
* @param mode The significant digits mode to use.
|
||||
* @category Rounding
|
||||
* @internal
|
||||
* @deprecated ICU 59: This API is a technical preview. It may change in an upcoming release.
|
||||
*/
|
||||
@Deprecated
|
||||
public synchronized void setSignificantDigitsMode(SignificantDigitsMode mode) {
|
||||
properties.setSignificantDigitsMode(mode);
|
||||
refreshFormatter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum number of characters in formatted output.
|
||||
*
|
||||
@ -1663,7 +1588,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized int getFormatWidth() {
|
||||
return exportedProperties.getFormatWidth();
|
||||
return properties.getFormatWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1699,7 +1624,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized char getPadCharacter() {
|
||||
CharSequence paddingString = exportedProperties.getPadString();
|
||||
CharSequence paddingString = properties.getPadString();
|
||||
if (paddingString == null) {
|
||||
return '.'; // TODO: Is this the correct behavior?
|
||||
} else {
|
||||
@ -1732,7 +1657,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized int getPadPosition() {
|
||||
PadPosition loc = exportedProperties.getPadPosition();
|
||||
PadPosition loc = properties.getPadPosition();
|
||||
return (loc == null) ? PAD_BEFORE_PREFIX : loc.toOld();
|
||||
}
|
||||
|
||||
@ -1800,7 +1725,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized byte getMinimumExponentDigits() {
|
||||
return (byte) exportedProperties.getMinimumExponentDigits();
|
||||
return (byte) properties.getMinimumExponentDigits();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1828,7 +1753,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized boolean isExponentSignAlwaysShown() {
|
||||
return exportedProperties.getExponentSignAlwaysShown();
|
||||
return properties.getExponentSignAlwaysShown();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1898,7 +1823,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized int getGroupingSize() {
|
||||
return exportedProperties.getGroupingSize();
|
||||
return properties.getGroupingSize();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1930,7 +1855,12 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized int getSecondaryGroupingSize() {
|
||||
return exportedProperties.getSecondaryGroupingSize();
|
||||
int grouping1 = properties.getGroupingSize();
|
||||
int grouping2 = properties.getSecondaryGroupingSize();
|
||||
if (grouping1 == grouping2 || grouping2 < 0) {
|
||||
return 0;
|
||||
}
|
||||
return properties.getSecondaryGroupingSize();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1991,7 +1921,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
* @stable ICU 2.0
|
||||
*/
|
||||
public synchronized boolean isDecimalSeparatorAlwaysShown() {
|
||||
return exportedProperties.getDecimalSeparatorAlwaysShown();
|
||||
return properties.getDecimalSeparatorAlwaysShown();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2471,9 +2401,7 @@ public class DecimalFormat extends NumberFormat {
|
||||
*/
|
||||
@Deprecated
|
||||
public IFixedDecimal getFixedDecimal(double number) {
|
||||
FormatQuantity4 fq = new FormatQuantity4(number);
|
||||
formatter.format(fq);
|
||||
return fq;
|
||||
return formatter.format(number).getFixedDecimal();
|
||||
}
|
||||
|
||||
private static final ThreadLocal<Properties> threadLocalProperties =
|
||||
@ -2491,9 +2419,18 @@ public class DecimalFormat extends NumberFormat {
|
||||
// The only time when this happens is during legacy deserialization.
|
||||
return;
|
||||
}
|
||||
formatter = Endpoint.fromBTA(properties, symbols);
|
||||
exportedProperties.clear();
|
||||
formatter.export(exportedProperties);
|
||||
MacroProps macros = NumberPropertyMapper.oldToNew(properties, symbols, exportedProperties);
|
||||
ULocale locale = this.getLocale(ULocale.ACTUAL_LOCALE);
|
||||
if (locale == null) {
|
||||
// Constructor
|
||||
locale = symbols.getLocale(ULocale.ACTUAL_LOCALE);
|
||||
}
|
||||
if (locale == null) {
|
||||
// Deserialization
|
||||
locale = symbols.getULocale();
|
||||
}
|
||||
assert locale != null;
|
||||
formatter = NumberFormatterImpl.fromMacros(macros).locale(locale);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2561,46 +2498,6 @@ public class DecimalFormat extends NumberFormat {
|
||||
public void set(Properties props);
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum containing the choices for significant digits modes.
|
||||
*
|
||||
* @see #setSignificantDigitsMode
|
||||
* @internal
|
||||
* @deprecated ICU 59: This API is technical preview. It may change in an upcoming release.
|
||||
*/
|
||||
@Deprecated
|
||||
public static enum SignificantDigitsMode {
|
||||
/**
|
||||
* Respect significant digits counts, ignoring the fraction length.
|
||||
*
|
||||
* @see DecimalFormat#setSignificantDigitsMode
|
||||
* @internal
|
||||
* @deprecated ICU 59: This API is technical preview. It may change in an upcoming release.
|
||||
*/
|
||||
@Deprecated
|
||||
OVERRIDE_MAXIMUM_FRACTION,
|
||||
|
||||
/**
|
||||
* Respect the fraction length, overriding significant digits counts if necessary.
|
||||
*
|
||||
* @see DecimalFormat#setSignificantDigitsMode
|
||||
* @internal
|
||||
* @deprecated ICU 59: This API is technical preview. It may change in an upcoming release.
|
||||
*/
|
||||
@Deprecated
|
||||
RESPECT_MAXIMUM_FRACTION,
|
||||
|
||||
/**
|
||||
* Respect minimum significant digits, overriding fraction length if necessary.
|
||||
*
|
||||
* @see DecimalFormat#setSignificantDigitsMode
|
||||
* @internal
|
||||
* @deprecated ICU 59: This API is technical preview. It may change in an upcoming release.
|
||||
*/
|
||||
@Deprecated
|
||||
ENSURE_MINIMUM_SIGNIFICANT
|
||||
}
|
||||
|
||||
/**
|
||||
* {@icu} Constant for {@link #getPadPosition()} and {@link #setPadPosition(int)} to specify pad
|
||||
* characters inserted before the prefix.
|
||||
|
@ -259,8 +259,8 @@ $**####,##0 1234 $***1\u00a0234 K
|
||||
// In J ICU adds padding as if 'EUR' is only 2 chars (2 * 0xa4)
|
||||
\u00a4\u00a4 **####0.00 433.0 EUR *433,00 JK
|
||||
// In J ICU adds padding as if 'EUR' is only 2 chars (2 * 0xa4)
|
||||
// S fails this one because the test code bypasses CurrencyUsage
|
||||
\u00a4\u00a4 **#######0 433.0 EUR *433,00 JKS
|
||||
// S and Q fail this one because the test code bypasses CurrencyUsage
|
||||
\u00a4\u00a4 **#######0 433.0 EUR *433,00 JKSQ
|
||||
|
||||
test padding and currencies
|
||||
begin
|
||||
@ -338,8 +338,8 @@ minIntegerDigits maxIntegerDigits minFractionDigits maxFractionDigits output bre
|
||||
// JDK gives E0 instead of allowing for unlimited precision
|
||||
// S obeys the maximum integer digits and returns .299792458E9
|
||||
0 0 0 0 2.99792458E8 KS
|
||||
// JDK and S give .299792E9
|
||||
0 1 0 5 2.9979E8 KS
|
||||
// JDK and S give .299792E9; Q gives 2.99792E8
|
||||
0 1 0 5 2.9979E8 KSQ
|
||||
// JDK gives 300E6
|
||||
0 3 0 0 299.792458E6 K
|
||||
// JDK gives 299.8E6 (maybe maxInt + maxFrac instead of minInt + maxFrac)?
|
||||
@ -356,12 +356,13 @@ minIntegerDigits maxIntegerDigits minFractionDigits maxFractionDigits output bre
|
||||
// JDK gives E0
|
||||
// S obeys the maximum integer digits
|
||||
0 0 1 0 2.99792458E8 KS
|
||||
// JDK gives .2998E9
|
||||
0 0 0 4 2.998E8 KS
|
||||
// JDK and S give .2998E9
|
||||
0 0 0 4 2.998E8 KSQ
|
||||
// S correctly formats this as 29.979246E7.
|
||||
// JDK uses 8 + 6 for significant digits instead of 2 + 6
|
||||
// J and C return 2.9979246E8.
|
||||
2 8 1 6 29.979246E7 CJK
|
||||
// TODO: Merge trunk
|
||||
2 8 1 6 29.979246E7 CJKQ
|
||||
// Treat max int digits > 8 as being the same as min int digits.
|
||||
// This behavior is not spelled out in the specification.
|
||||
// JDK fails here because it tries to use 9 + 6 = 15 sig digits.
|
||||
@ -405,12 +406,12 @@ begin
|
||||
format maxIntegerDigits output breaks
|
||||
123 1 3
|
||||
0 0 0
|
||||
// S ignores max integer if it is less than zero and prints "123"
|
||||
123 -2147483648 0 S
|
||||
// S and Q ignore max integer if it is less than zero and prints "123"
|
||||
123 -2147483648 0 SQ
|
||||
12345 1 5
|
||||
12345 -2147483648 0 S
|
||||
12345 -2147483648 0 SQ
|
||||
5.3 1 5.3
|
||||
5.3 -2147483648 .3 S
|
||||
5.3 -2147483648 .3 SQ
|
||||
|
||||
test patterns with zero
|
||||
set locale en
|
||||
@ -489,8 +490,9 @@ output grouping breaks grouping2 minGroupingDigits
|
||||
1,2345,6789 4
|
||||
1,23,45,6789 4 K 2
|
||||
1,23,45,6789 4 K 2 2
|
||||
// Q only supports minGrouping<=2
|
||||
123,456789 6 6 3
|
||||
123456789 6 JK 6 4
|
||||
123456789 6 JKQ 6 4
|
||||
|
||||
test multiplier setters
|
||||
set locale en_US
|
||||
@ -498,8 +500,10 @@ begin
|
||||
format multiplier output breaks
|
||||
23 -12 -276
|
||||
23 -1 -23
|
||||
// ICU4J and JDK throw exception on zero multiplier. ICU4C does not.
|
||||
23 0 23 JKS
|
||||
// ICU4J and JDK throw exception on zero multiplier.
|
||||
// ICU4C and S print 23.
|
||||
// Q multiplies by zero and prints 0.
|
||||
23 0 0 CJKS
|
||||
23 1 23
|
||||
23 12 276
|
||||
-23 12 -276
|
||||
@ -513,8 +517,9 @@ begin
|
||||
format output breaks
|
||||
-0.35 -0.25 K
|
||||
0.35 0.25 K
|
||||
0.39 0.5 K
|
||||
0.62 0.5 K
|
||||
// Q doesn't support mixing minFrac with roundingIncrement (prints 0.50).
|
||||
0.39 0.5 KQ
|
||||
0.62 0.5 KQ
|
||||
0.63 0.75 K
|
||||
|
||||
test padding setters
|
||||
@ -539,20 +544,19 @@ output breaks useScientific
|
||||
|
||||
test rounding mode setters
|
||||
set locale en_US
|
||||
set pattern 0.#
|
||||
set roundingIncrement 0.5
|
||||
set pattern 0.5
|
||||
begin
|
||||
format roundingMode output breaks
|
||||
1.24 halfUp 1 K
|
||||
1.24 halfUp 1.0 K
|
||||
1.25 halfUp 1.5 K
|
||||
1.25 halfDown 1 K
|
||||
1.25 halfDown 1.0 K
|
||||
1.26 halfDown 1.5 K
|
||||
1.25 halfEven 1 K
|
||||
1.25 halfEven 1.0 K
|
||||
-1.01 up -1.5 K
|
||||
-1.49 down -1 K
|
||||
-1.49 down -1.0 K
|
||||
1.01 up 1.5 K
|
||||
1.49 down 1 K
|
||||
-1.01 ceiling -1
|
||||
1.49 down 1.0 K
|
||||
-1.01 ceiling -1.0
|
||||
-1.49 floor -1.5
|
||||
|
||||
test currency usage setters
|
||||
@ -584,7 +588,7 @@ set locale en
|
||||
set currency USD
|
||||
begin
|
||||
pattern format output breaks
|
||||
# 123 123 S
|
||||
# 123 123 SQ
|
||||
// Currency rounding should always override the pattern.
|
||||
// K prints the currency in ISO format for some reason.
|
||||
\u00a4# 123 $123.00 K
|
||||
@ -659,7 +663,8 @@ begin
|
||||
format output breaks
|
||||
Inf [\u221e]
|
||||
-Inf (\u221e) K
|
||||
NaN NaN K
|
||||
// Q prints the affixes
|
||||
NaN NaN KQ
|
||||
|
||||
test nan and infinity with multiplication
|
||||
set locale en
|
||||
@ -680,10 +685,11 @@ Inf beforePrefix $$$\u221e$ K
|
||||
Inf afterPrefix $$$ \u221e$ K
|
||||
Inf beforeSuffix $$$\u221e $ K
|
||||
Inf afterSuffix $$$\u221e$ K
|
||||
NaN beforePrefix NaN K
|
||||
NaN afterPrefix NaN K
|
||||
NaN beforeSuffix NaN K
|
||||
NaN afterSuffix NaN K
|
||||
// Q gets $$$NaN$
|
||||
NaN beforePrefix NaN KQ
|
||||
NaN afterPrefix NaN KQ
|
||||
NaN beforeSuffix NaN KQ
|
||||
NaN afterSuffix NaN KQ
|
||||
|
||||
test apply formerly localized patterns
|
||||
begin
|
||||
@ -1540,8 +1546,9 @@ set maxSigDigits 2
|
||||
begin
|
||||
format output breaks
|
||||
// C and J get "1"
|
||||
// Q gets "1.0"
|
||||
// K gets "1.1" (??)
|
||||
0.975 0.98 CJK
|
||||
0.975 0.98 CJKQ
|
||||
|
||||
test lenient parse currency match
|
||||
// This test is for #13112
|
||||
|
@ -102,7 +102,7 @@ public class CompactDecimalFormatTest extends TestFmwk {
|
||||
{1234567890123f, "1,2 билиона"},
|
||||
{12345678901234f, "12 билиона"},
|
||||
{123456789012345f, "120 билиона"},
|
||||
{1234567890123456f, "1.200 билиона"},
|
||||
{1234567890123456f, "1200 билиона"},
|
||||
};
|
||||
|
||||
Object[][] SerbianTestDataLongNegative = {
|
||||
@ -125,7 +125,7 @@ public class CompactDecimalFormatTest extends TestFmwk {
|
||||
{-1234567890123f, "-1,2 билиона"},
|
||||
{-12345678901234f, "-12 билиона"},
|
||||
{-123456789012345f, "-120 билиона"},
|
||||
{-1234567890123456f, "-1.200 билиона"},
|
||||
{-1234567890123456f, "-1200 билиона"},
|
||||
};
|
||||
|
||||
Object[][] JapaneseTestData = {
|
||||
@ -363,10 +363,10 @@ public class CompactDecimalFormatTest extends TestFmwk {
|
||||
// and rounded to the unit for compact formats with three or more zeros.
|
||||
CompactDecimalFormat cdf =
|
||||
CompactDecimalFormat.getInstance(ULocale.ENGLISH, CompactStyle.SHORT);
|
||||
assertEquals("Default significant digits", "120K", cdf.format(123456));
|
||||
assertEquals("Default significant digits", "123K", cdf.format(123456));
|
||||
assertEquals("Default significant digits", "12K", cdf.format(12345));
|
||||
assertEquals("Default significant digits", "1.2K", cdf.format(1234));
|
||||
assertEquals("Default significant digits", "120", cdf.format(123));
|
||||
assertEquals("Default significant digits", "123", cdf.format(123));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -636,8 +636,9 @@ public class CompactDecimalFormatTest extends TestFmwk {
|
||||
public void TestDigitDisplay() {
|
||||
CompactDecimalFormat cdf = CompactDecimalFormat.getInstance(ULocale.US, CompactStyle.SHORT);
|
||||
cdf.setMinimumSignificantDigits(2);
|
||||
cdf.setMaximumSignificantDigits(3);
|
||||
String actual = cdf.format(70123.45678);
|
||||
assertEquals("Should not display any extra fraction digits", "70K", actual);
|
||||
assertEquals("Should not display any extra fraction digits", "70.1K", actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -667,7 +668,7 @@ public class CompactDecimalFormatTest extends TestFmwk {
|
||||
props.setCompactCustomData(customData);
|
||||
}
|
||||
});
|
||||
assertEquals("Below custom range", "120", cdf.format(123));
|
||||
assertEquals("Below custom range", "123", cdf.format(123));
|
||||
assertEquals("Plural form one", "1 qwerty", cdf.format(1000));
|
||||
assertEquals("Plural form other", "1.2 dvorak", cdf.format(1234));
|
||||
assertEquals("Above custom range", "12 dvorak", cdf.format(12345));
|
||||
|
@ -59,8 +59,7 @@ public class IntlTestDecimalFormatAPI extends com.ibm.icu.dev.test.TestFmwk
|
||||
String pat = ",##0.0000";
|
||||
DecimalFormat dec = new DecimalFormat(pat);
|
||||
dec.setRoundingMode(BigDecimal.ROUND_HALF_UP);
|
||||
double roundinginc = 0.0001;
|
||||
dec.setRoundingIncrement(roundinginc);
|
||||
dec.setRoundingIncrement(new java.math.BigDecimal("0.0001"));
|
||||
String str = dec.format(number);
|
||||
if (!str.equals(expected)) {
|
||||
errln("Fail: " + number + " x \"" + pat + "\" = \"" +
|
||||
|
@ -278,7 +278,7 @@ public class IntlTestDecimalFormatAPIC extends com.ibm.icu.dev.test.TestFmwk {
|
||||
}
|
||||
|
||||
//for +2.55 with RoundingIncrement=1.0
|
||||
pat.setRoundingIncrement(1.0);
|
||||
pat.setRoundingIncrement(java.math.BigDecimal.ONE);
|
||||
resultStr = pat.format(Roundingnumber);
|
||||
message = "round(" + Roundingnumber
|
||||
+ "," + mode + ",FALSE) with RoundingIncrement=1.0==>";
|
||||
|
@ -124,7 +124,7 @@ public class IntlTestDecimalFormatSymbolsC extends com.ibm.icu.dev.test.TestFmwk
|
||||
sym.setPercent('P');
|
||||
verify(34.5, "00 %", sym, "3450 P");
|
||||
sym.setCurrencySymbol("D");
|
||||
verify(34.5, "\u00a4##.##", sym, "D34.50");
|
||||
verify(34.5, "\u00a4##.##", sym, "D 34.50");
|
||||
sym.setGroupingSeparator('|');
|
||||
verify(3456.5, "0,000.##", sym, "3|456S5");
|
||||
}
|
||||
|
@ -1660,9 +1660,9 @@ public class MeasureUnitTest extends TestFmwk {
|
||||
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));
|
||||
assertEquals("short currency", "-USD 1.00", mf.format(USD_NEG_1));
|
||||
assertEquals("short currency", "USD 1.00", mf.format(USD_1));
|
||||
assertEquals("short currency", "USD 2.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));
|
||||
@ -1673,13 +1673,13 @@ public class MeasureUnitTest extends TestFmwk {
|
||||
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));
|
||||
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));
|
||||
|
||||
Measure CAD_1 = new Measure(1.0, Currency.getInstance("CAD"));
|
||||
mf = MeasureFormat.getInstance(ULocale.CANADA, FormatWidth.SHORT);
|
||||
assertEquals("short currency", "CAD1.00", mf.format(CAD_1));
|
||||
assertEquals("short currency", "CAD 1.00", mf.format(CAD_1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1997,7 +1997,10 @@ public class MeasureUnitTest extends TestFmwk {
|
||||
}
|
||||
}
|
||||
for (String type : MeasureUnit.getAvailableTypes()) {
|
||||
if (type.equals("currency") || type.equals("compound") || type.equals("coordinate")) {
|
||||
if (type.equals("currency")
|
||||
|| type.equals("compound")
|
||||
|| type.equals("coordinate")
|
||||
|| type.equals("dimensionless")) {
|
||||
continue;
|
||||
}
|
||||
for (MeasureUnit unit : MeasureUnit.getAvailable(type)) {
|
||||
|
@ -7,6 +7,7 @@ import java.math.RoundingMode;
|
||||
import java.text.ParseException;
|
||||
import java.text.ParsePosition;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ibm.icu.dev.test.TestUtil;
|
||||
@ -29,6 +30,11 @@ import com.ibm.icu.text.DecimalFormat_ICU58;
|
||||
import com.ibm.icu.util.CurrencyAmount;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
||||
import newapi.NumberFormatter.LocalizedNumberFormatter;
|
||||
import newapi.impl.MacroProps;
|
||||
import newapi.impl.NumberFormatterImpl;
|
||||
import newapi.impl.NumberPropertyMapper;
|
||||
|
||||
public class NumberFormatDataDrivenTest {
|
||||
|
||||
private static ULocale EN = new ULocale("en");
|
||||
@ -431,7 +437,7 @@ public class NumberFormatDataDrivenTest {
|
||||
}
|
||||
};
|
||||
|
||||
private DataDrivenNumberFormatTestUtility.CodeUnderTest Shane =
|
||||
private DataDrivenNumberFormatTestUtility.CodeUnderTest ICU59 =
|
||||
new DataDrivenNumberFormatTestUtility.CodeUnderTest() {
|
||||
|
||||
@Override
|
||||
@ -667,117 +673,154 @@ public class NumberFormatDataDrivenTest {
|
||||
public String select(DataDrivenNumberFormatTestData tuple) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
private void propertiesFromTuple(
|
||||
DataDrivenNumberFormatTestData tuple, Properties properties) {
|
||||
if (tuple.minIntegerDigits != null) {
|
||||
properties.setMinimumIntegerDigits(tuple.minIntegerDigits);
|
||||
}
|
||||
if (tuple.maxIntegerDigits != null) {
|
||||
properties.setMaximumIntegerDigits(tuple.maxIntegerDigits);
|
||||
}
|
||||
if (tuple.minFractionDigits != null) {
|
||||
properties.setMinimumFractionDigits(tuple.minFractionDigits);
|
||||
}
|
||||
if (tuple.maxFractionDigits != null) {
|
||||
properties.setMaximumFractionDigits(tuple.maxFractionDigits);
|
||||
}
|
||||
if (tuple.currency != null) {
|
||||
properties.setCurrency(tuple.currency);
|
||||
}
|
||||
if (tuple.minGroupingDigits != null) {
|
||||
properties.setMinimumGroupingDigits(tuple.minGroupingDigits);
|
||||
}
|
||||
if (tuple.useSigDigits != null) {
|
||||
// TODO
|
||||
}
|
||||
if (tuple.minSigDigits != null) {
|
||||
properties.setMinimumSignificantDigits(tuple.minSigDigits);
|
||||
}
|
||||
if (tuple.maxSigDigits != null) {
|
||||
properties.setMaximumSignificantDigits(tuple.maxSigDigits);
|
||||
}
|
||||
if (tuple.useGrouping != null && tuple.useGrouping == 0) {
|
||||
properties.setGroupingSize(-1);
|
||||
properties.setSecondaryGroupingSize(-1);
|
||||
}
|
||||
if (tuple.multiplier != null) {
|
||||
properties.setMultiplier(new BigDecimal(tuple.multiplier));
|
||||
}
|
||||
if (tuple.roundingIncrement != null) {
|
||||
properties.setRoundingIncrement(new BigDecimal(tuple.roundingIncrement.toString()));
|
||||
}
|
||||
if (tuple.formatWidth != null) {
|
||||
properties.setFormatWidth(tuple.formatWidth);
|
||||
}
|
||||
if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) {
|
||||
properties.setPadString(tuple.padCharacter.toString());
|
||||
}
|
||||
if (tuple.useScientific != null) {
|
||||
properties.setMinimumExponentDigits(
|
||||
tuple.useScientific != 0 ? 1 : Properties.DEFAULT_MINIMUM_EXPONENT_DIGITS);
|
||||
}
|
||||
if (tuple.grouping != null) {
|
||||
properties.setGroupingSize(tuple.grouping);
|
||||
}
|
||||
if (tuple.grouping2 != null) {
|
||||
properties.setSecondaryGroupingSize(tuple.grouping2);
|
||||
}
|
||||
if (tuple.roundingMode != null) {
|
||||
properties.setRoundingMode(RoundingMode.valueOf(tuple.roundingMode));
|
||||
}
|
||||
if (tuple.currencyUsage != null) {
|
||||
properties.setCurrencyUsage(tuple.currencyUsage);
|
||||
}
|
||||
if (tuple.minimumExponentDigits != null) {
|
||||
properties.setMinimumExponentDigits(tuple.minimumExponentDigits.byteValue());
|
||||
}
|
||||
if (tuple.exponentSignAlwaysShown != null) {
|
||||
properties.setExponentSignAlwaysShown(tuple.exponentSignAlwaysShown != 0);
|
||||
}
|
||||
if (tuple.decimalSeparatorAlwaysShown != null) {
|
||||
properties.setDecimalSeparatorAlwaysShown(tuple.decimalSeparatorAlwaysShown != 0);
|
||||
}
|
||||
if (tuple.padPosition != null) {
|
||||
properties.setPadPosition(PadPosition.fromOld(tuple.padPosition));
|
||||
}
|
||||
if (tuple.positivePrefix != null) {
|
||||
properties.setPositivePrefix(tuple.positivePrefix);
|
||||
}
|
||||
if (tuple.positiveSuffix != null) {
|
||||
properties.setPositiveSuffix(tuple.positiveSuffix);
|
||||
}
|
||||
if (tuple.negativePrefix != null) {
|
||||
properties.setNegativePrefix(tuple.negativePrefix);
|
||||
}
|
||||
if (tuple.negativeSuffix != null) {
|
||||
properties.setNegativeSuffix(tuple.negativeSuffix);
|
||||
}
|
||||
if (tuple.localizedPattern != null) {
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(tuple.locale);
|
||||
String converted =
|
||||
PatternString.convertLocalized(tuple.localizedPattern, symbols, false);
|
||||
PatternString.parseToExistingProperties(converted, properties);
|
||||
}
|
||||
if (tuple.lenient != null) {
|
||||
properties.setParseMode(tuple.lenient == 0 ? ParseMode.STRICT : ParseMode.LENIENT);
|
||||
}
|
||||
if (tuple.parseIntegerOnly != null) {
|
||||
properties.setParseIntegerOnly(tuple.parseIntegerOnly != 0);
|
||||
}
|
||||
if (tuple.parseCaseSensitive != null) {
|
||||
properties.setParseCaseSensitive(tuple.parseCaseSensitive != 0);
|
||||
}
|
||||
if (tuple.decimalPatternMatchRequired != null) {
|
||||
properties.setDecimalPatternMatchRequired(tuple.decimalPatternMatchRequired != 0);
|
||||
}
|
||||
if (tuple.parseNoExponent != null) {
|
||||
properties.setParseNoExponent(tuple.parseNoExponent != 0);
|
||||
static void propertiesFromTuple(DataDrivenNumberFormatTestData tuple, Properties properties) {
|
||||
if (tuple.minIntegerDigits != null) {
|
||||
properties.setMinimumIntegerDigits(tuple.minIntegerDigits);
|
||||
}
|
||||
if (tuple.maxIntegerDigits != null) {
|
||||
properties.setMaximumIntegerDigits(tuple.maxIntegerDigits);
|
||||
}
|
||||
if (tuple.minFractionDigits != null) {
|
||||
properties.setMinimumFractionDigits(tuple.minFractionDigits);
|
||||
}
|
||||
if (tuple.maxFractionDigits != null) {
|
||||
properties.setMaximumFractionDigits(tuple.maxFractionDigits);
|
||||
}
|
||||
if (tuple.currency != null) {
|
||||
properties.setCurrency(tuple.currency);
|
||||
}
|
||||
if (tuple.minGroupingDigits != null) {
|
||||
properties.setMinimumGroupingDigits(tuple.minGroupingDigits);
|
||||
}
|
||||
if (tuple.useSigDigits != null) {
|
||||
// TODO
|
||||
}
|
||||
if (tuple.minSigDigits != null) {
|
||||
properties.setMinimumSignificantDigits(tuple.minSigDigits);
|
||||
}
|
||||
if (tuple.maxSigDigits != null) {
|
||||
properties.setMaximumSignificantDigits(tuple.maxSigDigits);
|
||||
}
|
||||
if (tuple.useGrouping != null && tuple.useGrouping == 0) {
|
||||
properties.setGroupingSize(-1);
|
||||
properties.setSecondaryGroupingSize(-1);
|
||||
}
|
||||
if (tuple.multiplier != null) {
|
||||
properties.setMultiplier(new BigDecimal(tuple.multiplier));
|
||||
}
|
||||
if (tuple.roundingIncrement != null) {
|
||||
properties.setRoundingIncrement(new BigDecimal(tuple.roundingIncrement.toString()));
|
||||
}
|
||||
if (tuple.formatWidth != null) {
|
||||
properties.setFormatWidth(tuple.formatWidth);
|
||||
}
|
||||
if (tuple.padCharacter != null && tuple.padCharacter.length() > 0) {
|
||||
properties.setPadString(tuple.padCharacter.toString());
|
||||
}
|
||||
if (tuple.useScientific != null) {
|
||||
properties.setMinimumExponentDigits(
|
||||
tuple.useScientific != 0 ? 1 : Properties.DEFAULT_MINIMUM_EXPONENT_DIGITS);
|
||||
}
|
||||
if (tuple.grouping != null) {
|
||||
properties.setGroupingSize(tuple.grouping);
|
||||
}
|
||||
if (tuple.grouping2 != null) {
|
||||
properties.setSecondaryGroupingSize(tuple.grouping2);
|
||||
}
|
||||
if (tuple.roundingMode != null) {
|
||||
properties.setRoundingMode(RoundingMode.valueOf(tuple.roundingMode));
|
||||
}
|
||||
if (tuple.currencyUsage != null) {
|
||||
properties.setCurrencyUsage(tuple.currencyUsage);
|
||||
}
|
||||
if (tuple.minimumExponentDigits != null) {
|
||||
properties.setMinimumExponentDigits(tuple.minimumExponentDigits.byteValue());
|
||||
}
|
||||
if (tuple.exponentSignAlwaysShown != null) {
|
||||
properties.setExponentSignAlwaysShown(tuple.exponentSignAlwaysShown != 0);
|
||||
}
|
||||
if (tuple.decimalSeparatorAlwaysShown != null) {
|
||||
properties.setDecimalSeparatorAlwaysShown(tuple.decimalSeparatorAlwaysShown != 0);
|
||||
}
|
||||
if (tuple.padPosition != null) {
|
||||
properties.setPadPosition(PadPosition.fromOld(tuple.padPosition));
|
||||
}
|
||||
if (tuple.positivePrefix != null) {
|
||||
properties.setPositivePrefix(tuple.positivePrefix);
|
||||
}
|
||||
if (tuple.positiveSuffix != null) {
|
||||
properties.setPositiveSuffix(tuple.positiveSuffix);
|
||||
}
|
||||
if (tuple.negativePrefix != null) {
|
||||
properties.setNegativePrefix(tuple.negativePrefix);
|
||||
}
|
||||
if (tuple.negativeSuffix != null) {
|
||||
properties.setNegativeSuffix(tuple.negativeSuffix);
|
||||
}
|
||||
if (tuple.localizedPattern != null) {
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(tuple.locale);
|
||||
String converted = PatternString.convertLocalized(tuple.localizedPattern, symbols, false);
|
||||
PatternString.parseToExistingProperties(converted, properties);
|
||||
}
|
||||
if (tuple.lenient != null) {
|
||||
properties.setParseMode(tuple.lenient == 0 ? ParseMode.STRICT : ParseMode.LENIENT);
|
||||
}
|
||||
if (tuple.parseIntegerOnly != null) {
|
||||
properties.setParseIntegerOnly(tuple.parseIntegerOnly != 0);
|
||||
}
|
||||
if (tuple.parseCaseSensitive != null) {
|
||||
properties.setParseCaseSensitive(tuple.parseCaseSensitive != 0);
|
||||
}
|
||||
if (tuple.decimalPatternMatchRequired != null) {
|
||||
properties.setDecimalPatternMatchRequired(tuple.decimalPatternMatchRequired != 0);
|
||||
}
|
||||
if (tuple.parseNoExponent != null) {
|
||||
properties.setParseNoExponent(tuple.parseNoExponent != 0);
|
||||
}
|
||||
}
|
||||
|
||||
private DataDrivenNumberFormatTestUtility.CodeUnderTest ICU60 =
|
||||
new DataDrivenNumberFormatTestUtility.CodeUnderTest() {
|
||||
|
||||
@Override
|
||||
public Character Id() {
|
||||
return 'Q';
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a single formatting test. On success, returns null. On failure, returns the error.
|
||||
* This implementation just returns null. Subclasses should override.
|
||||
*
|
||||
* @param tuple contains the parameters of the format test.
|
||||
*/
|
||||
@Override
|
||||
public String format(DataDrivenNumberFormatTestData tuple) {
|
||||
String pattern = (tuple.pattern == null) ? "0" : tuple.pattern;
|
||||
ULocale locale = (tuple.locale == null) ? ULocale.ENGLISH : tuple.locale;
|
||||
Properties properties =
|
||||
PatternString.parseToProperties(
|
||||
pattern,
|
||||
tuple.currency != null
|
||||
? PatternString.IGNORE_ROUNDING_ALWAYS
|
||||
: PatternString.IGNORE_ROUNDING_NEVER);
|
||||
propertiesFromTuple(tuple, properties);
|
||||
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
|
||||
MacroProps macros = NumberPropertyMapper.oldToNew(properties, symbols, null);
|
||||
LocalizedNumberFormatter fmt = NumberFormatterImpl.fromMacros(macros).locale(locale);
|
||||
Number number = toNumber(tuple.format);
|
||||
String expected = tuple.output;
|
||||
String actual = fmt.format(number).toString();
|
||||
if (!expected.equals(actual)) {
|
||||
return "Expected \"" + expected + "\", got \"" + actual + "\"";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void TestDataDrivenICU58() {
|
||||
// Android can't access DecimalFormat_ICU58 for testing (ticket #13283).
|
||||
if (TestUtil.getJavaVendor() == TestUtil.JavaVendor.Android) return;
|
||||
@ -787,14 +830,22 @@ public class NumberFormatDataDrivenTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void TestDataDrivenJDK() {
|
||||
DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
|
||||
"numberformattestspecification.txt", JDK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestDataDrivenShane() {
|
||||
@Ignore
|
||||
public void TestDataDrivenICU59() {
|
||||
DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
|
||||
"numberformattestspecification.txt", Shane);
|
||||
"numberformattestspecification.txt", ICU59);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void TestDataDrivenICU60() {
|
||||
DataDrivenNumberFormatTestUtility.runFormatSuiteIncludingKnownFailures(
|
||||
"numberformattestspecification.txt", ICU60);
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +185,8 @@ public class NumberFormatRegressionTest extends com.ibm.icu.dev.test.TestFmwk {
|
||||
String result = format.format(data);
|
||||
assertEquals("Deserialization new version should read old version", expected[i], result);
|
||||
} catch (Exception e) {
|
||||
warnln("FAIL: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
warnln("FAIL: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,6 @@ import com.ibm.icu.text.CompactDecimalFormat;
|
||||
import com.ibm.icu.text.CurrencyPluralInfo;
|
||||
import com.ibm.icu.text.DecimalFormat;
|
||||
import com.ibm.icu.text.DecimalFormat.PropertySetter;
|
||||
import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
|
||||
import com.ibm.icu.text.DecimalFormatSymbols;
|
||||
import com.ibm.icu.text.DecimalFormat_ICU58;
|
||||
import com.ibm.icu.text.DisplayContext;
|
||||
@ -500,13 +499,13 @@ public class NumberFormatTest extends TestFmwk {
|
||||
// currency format using currency ISO name, such as "USD",
|
||||
// currency format using plural name, such as "US dollars".
|
||||
// for US locale
|
||||
{"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1234.56", "$1,234.56", "USD1,234.56", "US dollars1,234.56"},
|
||||
{"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD1,234.56", "-US dollars1,234.56"},
|
||||
{"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1", "$1.00", "USD1.00", "US dollars1.00"},
|
||||
{"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1234.56", "$1,234.56", "USD 1,234.56", "US dollars 1,234.56"},
|
||||
{"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD 1,234.56", "-US dollars 1,234.56"},
|
||||
{"en_US", "\u00A4#,##0.00;-\u00A4#,##0.00", "1", "$1.00", "USD 1.00", "US dollars 1.00"},
|
||||
// for CHINA locale
|
||||
{"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1234.56", "\uFFE51,234.56", "CNY1,234.56", "\u4EBA\u6C11\u5E011,234.56"},
|
||||
{"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "-1234.56", "(\uFFE51,234.56)", "(CNY1,234.56)", "(\u4EBA\u6C11\u5E011,234.56)"},
|
||||
{"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1", "\uFFE51.00", "CNY1.00", "\u4EBA\u6C11\u5E011.00"}
|
||||
{"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1234.56", "\uFFE51,234.56", "CNY 1,234.56", "\u4EBA\u6C11\u5E01 1,234.56"},
|
||||
{"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "-1234.56", "(\uFFE51,234.56)", "(CNY 1,234.56)", "(\u4EBA\u6C11\u5E01 1,234.56)"},
|
||||
{"zh_CN", "\u00A4#,##0.00;(\u00A4#,##0.00)", "1", "\uFFE51.00", "CNY 1.00", "\u4EBA\u6C11\u5E01 1.00"}
|
||||
};
|
||||
|
||||
String doubleCurrencyStr = "\u00A4\u00A4";
|
||||
@ -536,7 +535,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
// 'j' number of currency sign.
|
||||
String currencyFormatResult = DATA[i][2+j];
|
||||
if (!s.equals(currencyFormatResult)) {
|
||||
errln("FAIL format: Expected " + currencyFormatResult);
|
||||
errln("FAIL format: Expected " + currencyFormatResult + " but got " + s);
|
||||
}
|
||||
try {
|
||||
// mix style parsing
|
||||
@ -712,13 +711,13 @@ public class NumberFormatTest extends TestFmwk {
|
||||
// format result using CURRENCYSTYLE,
|
||||
// format result using ISOCURRENCYSTYLE,
|
||||
// format result using PLURALCURRENCYSTYLE,
|
||||
{"en_US", "1", "USD", "$1.00", "USD1.00", "1.00 US dollars"},
|
||||
{"en_US", "1234.56", "USD", "$1,234.56", "USD1,234.56", "1,234.56 US dollars"},
|
||||
{"en_US", "-1234.56", "USD", "-$1,234.56", "-USD1,234.56", "-1,234.56 US dollars"},
|
||||
{"zh_CN", "1", "USD", "US$1.00", "USD1.00", "1.00美元"},
|
||||
{"zh_CN", "1234.56", "USD", "US$1,234.56", "USD1,234.56", "1,234.56美元"},
|
||||
{"zh_CN", "1", "CNY", "¥1.00", "CNY1.00", "1.00人民币"},
|
||||
{"zh_CN", "1234.56", "CNY", "¥1,234.56", "CNY1,234.56", "1,234.56人民币"},
|
||||
{"en_US", "1", "USD", "$1.00", "USD 1.00", "1.00 US dollars"},
|
||||
{"en_US", "1234.56", "USD", "$1,234.56", "USD 1,234.56", "1,234.56 US dollars"},
|
||||
{"en_US", "-1234.56", "USD", "-$1,234.56", "-USD 1,234.56", "-1,234.56 US dollars"},
|
||||
{"zh_CN", "1", "USD", "US$1.00", "USD 1.00", "1.00 美元"},
|
||||
{"zh_CN", "1234.56", "USD", "US$1,234.56", "USD 1,234.56", "1,234.56 美元"},
|
||||
{"zh_CN", "1", "CNY", "¥1.00", "CNY 1.00", "1.00 人民币"},
|
||||
{"zh_CN", "1234.56", "CNY", "¥1,234.56", "CNY 1,234.56", "1,234.56 人民币"},
|
||||
{"ru_RU", "1", "RUB", "1,00 \u20BD", "1,00 RUB", "1,00 российского рубля"},
|
||||
{"ru_RU", "2", "RUB", "2,00 \u20BD", "2,00 RUB", "2,00 российского рубля"},
|
||||
{"ru_RU", "5", "RUB", "5,00 \u20BD", "5,00 RUB", "5,00 российского рубля"},
|
||||
@ -957,7 +956,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
1234.56, "\u00A51,235"); // Yen
|
||||
|
||||
expectCurrency(fmt, Currency.getInstance(new Locale("fr", "CH", "")),
|
||||
1234.56, "CHF1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
|
||||
1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548
|
||||
|
||||
expectCurrency(fmt, Currency.getInstance(Locale.US),
|
||||
1234.56, "$1,234.56");
|
||||
@ -1727,7 +1726,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
ULocale locale = new ULocale("th_TH@currency=QQQ");
|
||||
NumberFormat format = NumberFormat.getCurrencyInstance(locale);
|
||||
String result = format.format(12.34f);
|
||||
if (!"QQQ12.34".equals(result)) {
|
||||
if (!"QQQ 12.34".equals(result)) {
|
||||
errln("got unexpected currency: " + result);
|
||||
}
|
||||
}
|
||||
@ -2255,13 +2254,13 @@ public class NumberFormatTest extends TestFmwk {
|
||||
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("CHF 35.47", "CHF 35.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("-CHF 34.57", "-CHF 34.57", buffer20.toString());
|
||||
assertEquals("cp begin", 1, cp.getBeginIndex());
|
||||
assertEquals("cp end", 4, cp.getEndIndex());
|
||||
|
||||
@ -2296,17 +2295,17 @@ public class NumberFormatTest extends TestFmwk {
|
||||
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());
|
||||
assertEquals("35.47 スイス フラン", "35.47 スイス フラン", buffer7.toString());
|
||||
assertEquals("cp begin", 6, cp.getBeginIndex());
|
||||
assertEquals("cp end", 13, 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());
|
||||
assertEquals("-34.57 ユーロ", "-34.57 ユーロ", buffer8.toString());
|
||||
assertEquals("cp begin", 7, cp.getBeginIndex());
|
||||
assertEquals("cp end", 10, cp.getEndIndex());
|
||||
|
||||
nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(Locale.JAPAN);
|
||||
nf.setCurrency(Currency.getInstance(new Locale("ja", "jp")));
|
||||
@ -2320,9 +2319,9 @@ public class NumberFormatTest extends TestFmwk {
|
||||
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());
|
||||
assertEquals("-34.57 スイス フラン", "-34.57 スイス フラン", buffer10.toString());
|
||||
assertEquals("cp begin", 7, cp.getBeginIndex());
|
||||
assertEquals("cp end", 14, cp.getEndIndex());
|
||||
|
||||
// Nagative value with PLURALCURRENCYSTYLE, Arabic digits.
|
||||
nf = (DecimalFormat) com.ibm.icu.text.NumberFormat.getCurrencyInstance(new Locale("ar", "eg"));
|
||||
@ -2362,11 +2361,11 @@ public class NumberFormatTest extends TestFmwk {
|
||||
public void TestRoundingPattern() {
|
||||
class TestRoundingPatternItem {
|
||||
String pattern;
|
||||
double roundingIncrement;
|
||||
BigDecimal roundingIncrement;
|
||||
double testCase;
|
||||
String expected;
|
||||
|
||||
TestRoundingPatternItem(String pattern, double roundingIncrement, double testCase, String expected) {
|
||||
TestRoundingPatternItem(String pattern, BigDecimal roundingIncrement, double testCase, String expected) {
|
||||
this.pattern = pattern;
|
||||
this.roundingIncrement = roundingIncrement;
|
||||
this.testCase = testCase;
|
||||
@ -2375,13 +2374,12 @@ public class NumberFormatTest extends TestFmwk {
|
||||
};
|
||||
|
||||
TestRoundingPatternItem []tests = {
|
||||
new TestRoundingPatternItem("##0.65", 0.65, 1.234, "1.30"),
|
||||
new TestRoundingPatternItem("#50", 50.0, 1230, "1250")
|
||||
new TestRoundingPatternItem("##0.65", new BigDecimal("0.65"), 1.234, "1.30"),
|
||||
new TestRoundingPatternItem("#50", new BigDecimal("50"), 1230, "1250")
|
||||
};
|
||||
|
||||
DecimalFormat df = (DecimalFormat) com.ibm.icu.text.NumberFormat.getInstance(ULocale.ENGLISH);
|
||||
String result;
|
||||
BigDecimal bd;
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
df.applyPattern(tests[i].pattern);
|
||||
|
||||
@ -2391,9 +2389,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
|
||||
}
|
||||
|
||||
bd = new BigDecimal(tests[i].roundingIncrement);
|
||||
|
||||
df.setRoundingIncrement(bd);
|
||||
df.setRoundingIncrement(tests[i].roundingIncrement);
|
||||
|
||||
result = df.format(tests[i].testCase);
|
||||
|
||||
@ -4130,7 +4126,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
// * TWD switches from 0 decimals to 2; PKR still has 0, so change test to that
|
||||
// * CAD rounds to .05 in the cash style only.
|
||||
for (int i = 0; i < 2; i++) {
|
||||
String original_expected = "PKR124";
|
||||
String original_expected = "PKR 124";
|
||||
DecimalFormat custom = null;
|
||||
if (i == 0) {
|
||||
custom = (DecimalFormat) DecimalFormat.getInstance(new ULocale("en_US@currency=PKR"),
|
||||
@ -4153,7 +4149,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
}
|
||||
|
||||
String cash_currency = custom.format(123.567);
|
||||
String cash_currency_expected = "PKR124";
|
||||
String cash_currency_expected = "PKR 124";
|
||||
assertEquals("Test Currency Context", cash_currency_expected, cash_currency);
|
||||
}
|
||||
|
||||
@ -4195,7 +4191,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
|
||||
fmt2.setCurrency(Currency.getInstance("PKR"));
|
||||
String PKR_changed = fmt2.format(123.567);
|
||||
String PKR_changed_expected = "PKR124";
|
||||
String PKR_changed_expected = "PKR 124";
|
||||
assertEquals("Test Currency Context", PKR_changed_expected, PKR_changed);
|
||||
}
|
||||
}
|
||||
@ -4744,7 +4740,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
fmt.setDecimalFormatSymbols(symbols);
|
||||
fmt.applyPattern("#,##0.0#");
|
||||
assertEquals("Custom decimal and grouping separator string with multiple characters",
|
||||
fmt.format(1234567.89), "(1)^^(2)(3)(4)^^(5)(6)(7)~~(8)(9)");
|
||||
"(1)^^(2)(3)(4)^^(5)(6)(7)~~(8)(9)", fmt.format(1234567.89));
|
||||
|
||||
// Digits starting at U+1D7CE MATHEMATICAL BOLD DIGIT ZERO
|
||||
// These are all single code points, so parsing will work.
|
||||
@ -4917,7 +4913,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
|
||||
df.applyPattern("¤¤¤ 0");
|
||||
String result = df.getPositivePrefix();
|
||||
assertEquals("Triple-currency should give long name on getPositivePrefix", "US dollars ", result);
|
||||
assertEquals("Triple-currency should give long name on getPositivePrefix", "US dollar ", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -5263,7 +5259,7 @@ public class NumberFormatTest extends TestFmwk {
|
||||
symbols.setCurrencySymbol("#");
|
||||
df.setDecimalFormatSymbols(symbols);
|
||||
String actual = df.format(123);
|
||||
assertEquals("Should use '#' instad of '$'", "#123.00", actual);
|
||||
assertEquals("Should use '#' instad of '$'", "# 123.00", actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -5478,9 +5474,9 @@ public class NumberFormatTest extends TestFmwk {
|
||||
df.setMaximumFractionDigits(3);
|
||||
expect2(df, 35.0, "$35.000");
|
||||
df.setMinimumFractionDigits(-1);
|
||||
expect2(df, 35.0, "$35");
|
||||
df.setMaximumFractionDigits(-1);
|
||||
expect2(df, 35.0, "$35.00");
|
||||
df.setMaximumFractionDigits(1);
|
||||
expect2(df, 35.0, "$35.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -5637,46 +5633,6 @@ public class NumberFormatTest extends TestFmwk {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignificantDigitsMode() {
|
||||
String[][] allExpected = {
|
||||
{"12340.0", "12340.0", "12340.0"},
|
||||
{"1234.0", "1234.0", "1234.0"},
|
||||
{"123.4", "123.4", "123.4"},
|
||||
{"12.34", "12.34", "12.34"},
|
||||
{"1.234", "1.23", "1.23"},
|
||||
{"0.1234", "0.12", "0.123"},
|
||||
{"0.01234", "0.01", "0.0123"},
|
||||
{"0.001234", "0.00", "0.00123"}
|
||||
};
|
||||
|
||||
DecimalFormat df = new DecimalFormat();
|
||||
df.setMinimumFractionDigits(1);
|
||||
df.setMaximumFractionDigits(2);
|
||||
df.setMinimumSignificantDigits(3);
|
||||
df.setMaximumSignificantDigits(4);
|
||||
df.setGroupingUsed(false);
|
||||
|
||||
SignificantDigitsMode[] modes = new SignificantDigitsMode[] {
|
||||
SignificantDigitsMode.OVERRIDE_MAXIMUM_FRACTION,
|
||||
SignificantDigitsMode.RESPECT_MAXIMUM_FRACTION,
|
||||
SignificantDigitsMode.ENSURE_MINIMUM_SIGNIFICANT
|
||||
};
|
||||
|
||||
for (double d = 12340.0, i=0; d > 0.001; d /= 10, i++) {
|
||||
for (int j=0; j<modes.length; j++) {
|
||||
SignificantDigitsMode mode = modes[j];
|
||||
df.setSignificantDigitsMode(mode);
|
||||
String expected = allExpected[(int)i][j];
|
||||
String actual = df.format(d);
|
||||
assertEquals("Significant digits mode getter is broken",
|
||||
mode, df.getSignificantDigitsMode());
|
||||
assertEquals("Significant digits output differs for "+i+", "+j,
|
||||
expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseNoExponent() throws ParseException {
|
||||
DecimalFormat df = new DecimalFormat();
|
||||
|
@ -82,13 +82,13 @@ fpc: - 1234.56/JPY "¥1,235" 1235/JPY
|
||||
# ISO codes that overlap display names (QQQ vs. Q)
|
||||
# fake ISO code is not longer supported
|
||||
# fpc: - 123/QQQ "QQQ123.00" 123/QQQ # QQQ is fake
|
||||
fpc: - 123/GTQ "GTQ123.00" 123/GTQ
|
||||
fpc: - 123/GTQ "GTQ 123.00" 123/GTQ
|
||||
# ChoiceFormat-based display names
|
||||
fpc: - 1/INR "₹1.00" 1/INR
|
||||
|
||||
fpc: - 2/INR "₹2.00" 2/INR
|
||||
# Display names with shared prefix (YDD vs. Y)
|
||||
fpc: - 100/YDD "YDD100.00" 100/YDD
|
||||
fpc: - 100/YDD "YDD 100.00" 100/YDD
|
||||
fpc: - 100/CNY "CN¥100.00" 100/CNY
|
||||
|
||||
# Lenient Tests
|
||||
|
@ -161,7 +161,7 @@ public class NumberRegressionTests extends TestFmwk {
|
||||
try {
|
||||
logln(df.format(123, sBuf, fp).toString());
|
||||
} catch (Exception foo) {
|
||||
errln("Test for bug 4088503 failed.");
|
||||
errln("Test for bug 4088503 failed: " + foo);
|
||||
}
|
||||
|
||||
}
|
||||
@ -963,6 +963,7 @@ public class NumberRegressionTests extends TestFmwk {
|
||||
Locale.setDefault(Locale.US);
|
||||
DecimalFormat df = new DecimalFormat();
|
||||
df.setPositivePrefix("+");
|
||||
df.setNegativePrefix("-");
|
||||
double d = -0.0;
|
||||
logln("pattern: \"" + df.toPattern() + "\"");
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
@ -999,6 +1000,7 @@ public class NumberRegressionTests extends TestFmwk {
|
||||
{
|
||||
Locale[] locales = NumberFormat.getAvailableLocales();
|
||||
|
||||
outer:
|
||||
for (int i = 0; i < locales.length; i++) {
|
||||
ICUResourceBundle rb = (ICUResourceBundle)ICUResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME,locales[i]);
|
||||
|
||||
@ -1054,11 +1056,20 @@ public class NumberRegressionTests extends TestFmwk {
|
||||
|
||||
String result2 = fmt2.format(1.111);
|
||||
|
||||
// NOTE: en_IN is a special case (ChoiceFormat currency display name)
|
||||
if (!result1.equals(result2) &&
|
||||
!locales[i].toString().equals("en_IN")) {
|
||||
errln("Results for " + locales[i] + " differ: " +
|
||||
result1 + " vs " + result2);
|
||||
// Currency spacing may have been added by the real DecimalFormat. Account for that here.
|
||||
if (!result1.equals(result2)) {
|
||||
if (result1.length() == result2.length() + 1) {
|
||||
inner:
|
||||
for (int k=0; k<result2.length(); k++) {
|
||||
if (result1.charAt(k) != result2.charAt(k)) {
|
||||
if (result1.charAt(k) == '\u00A0') {
|
||||
continue outer; // currency spacing OK
|
||||
}
|
||||
break inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
errln("Results for " + locales[i] + " differ: " + result1 + " vs " + result2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1483,9 +1494,9 @@ public class NumberRegressionTests extends TestFmwk {
|
||||
fmt.applyPattern("\u00A4#.00");
|
||||
sym.setCurrencySymbol("usd");
|
||||
fmt.setDecimalFormatSymbols(sym);
|
||||
if (!fmt.format(12.5).equals("usd12.50")) {
|
||||
if (!fmt.format(12.5).equals("usd 12.50")) {
|
||||
errln("FAIL: 12.5 x (currency=usd) -> " + fmt.format(12.5) +
|
||||
", exp usd12.50");
|
||||
", exp usd 12.50");
|
||||
}
|
||||
if (!fmt.getPositivePrefix().equals("usd")) {
|
||||
errln("FAIL: (currency=usd).getPositivePrefix -> " +
|
||||
@ -1496,9 +1507,9 @@ public class NumberRegressionTests extends TestFmwk {
|
||||
fmt.applyPattern("\u00A4\u00A4#.00");
|
||||
sym.setInternationalCurrencySymbol("DOL");
|
||||
fmt.setDecimalFormatSymbols(sym);
|
||||
if (!fmt.format(12.5).equals("DOL12.50")) {
|
||||
if (!fmt.format(12.5).equals("DOL 12.50")) {
|
||||
errln("FAIL: 12.5 x (intlcurrency=DOL) -> " + fmt.format(12.5) +
|
||||
", exp DOL12.50");
|
||||
", exp DOL 12.50");
|
||||
}
|
||||
if (!fmt.getPositivePrefix().equals("DOL")) {
|
||||
errln("FAIL: (intlcurrency=DOL).getPositivePrefix -> " +
|
||||
|
@ -37,7 +37,6 @@ import com.ibm.icu.impl.number.formatters.CurrencyFormat.CurrencyStyle;
|
||||
import com.ibm.icu.impl.number.formatters.PaddingFormat.PadPosition;
|
||||
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
|
||||
import com.ibm.icu.text.CurrencyPluralInfo;
|
||||
import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
|
||||
import com.ibm.icu.text.MeasureFormat.FormatWidth;
|
||||
import com.ibm.icu.text.PluralRules;
|
||||
import com.ibm.icu.util.Currency;
|
||||
@ -306,11 +305,6 @@ public class PropertiesTest {
|
||||
RoundingMode[] values = RoundingMode.values();
|
||||
return values[seed % values.length];
|
||||
|
||||
} else if (type == SignificantDigitsMode.class) {
|
||||
if (seed == 0) return null;
|
||||
SignificantDigitsMode[] values = SignificantDigitsMode.values();
|
||||
return values[seed % values.length];
|
||||
|
||||
} else {
|
||||
fail("Don't know how to handle type " + type + ". Please add it to getSampleValueForType().");
|
||||
return null;
|
||||
|
@ -1,134 +0,0 @@
|
||||
// © 2017 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
package com.ibm.icu.dev.test.number;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ibm.icu.impl.number.FormatQuantity;
|
||||
import com.ibm.icu.impl.number.FormatQuantity4;
|
||||
import com.ibm.icu.impl.number.Properties;
|
||||
import com.ibm.icu.impl.number.rounders.SignificantDigitsRounder;
|
||||
import com.ibm.icu.text.DecimalFormat.SignificantDigitsMode;
|
||||
|
||||
public class RounderTest {
|
||||
|
||||
@Test
|
||||
public void testSignificantDigitsRounder() {
|
||||
Object[][][][] cases = {
|
||||
{
|
||||
{{1, -1}, {0, 2}, {2, 4}}, // minInt, maxInt, minFrac, maxFrac, minSig, maxSig
|
||||
{
|
||||
{0.0, "0.0", "0.0", "0"},
|
||||
{0.054321, "0.05432", "0.05", "0.054"},
|
||||
{0.54321, "0.5432", "0.54", "0.54"},
|
||||
{1.0, "1.0", "1.0", "1"},
|
||||
{5.4321, "5.432", "5.43", "5.43"},
|
||||
{10.0, "10", "10", "10"},
|
||||
{11.0, "11", "11", "11"},
|
||||
{100.0, "100", "100", "100"},
|
||||
{100.23, "100.2", "100.2", "100.2"},
|
||||
{543210.0, "543200", "543200", "543200"},
|
||||
}
|
||||
},
|
||||
{
|
||||
{{1, -1}, {0, 0}, {2, -1}}, // minInt, maxInt, minFrac, maxFrac, minSig, maxSig
|
||||
{
|
||||
{0.0, "0.0", "0", "0"},
|
||||
{0.054321, "0.054321", "0", "0.054"},
|
||||
{0.54321, "0.54321", "1", "0.54"},
|
||||
{1.0, "1.0", "1", "1"},
|
||||
{5.4321, "5.4321", "5", "5.4"},
|
||||
{10.0, "10", "10", "10"},
|
||||
{11.0, "11", "11", "11"},
|
||||
{100.0, "100", "100", "100"},
|
||||
{100.23, "100.23", "100", "100"},
|
||||
{543210.0, "543210", "543210", "543210"},
|
||||
}
|
||||
},
|
||||
{
|
||||
{{0, 2}, {1, 2}, {3, 3}}, // minInt, maxInt, minFrac, maxFrac, minSig, maxSig
|
||||
{
|
||||
{0.0, ".000", ".00", ".0"},
|
||||
{0.054321, ".0543", ".05", ".0543"},
|
||||
{0.54321, ".543", ".54", ".543"},
|
||||
{1.0, "1.00", "1.00", "1.0"},
|
||||
{5.4321, "5.43", "5.43", "5.43"},
|
||||
{10.0, "10.0", "10.0", "10.0"},
|
||||
{11.0, "11.0", "11.0", "11.0"},
|
||||
{100.0, "00.0", "00.0", "00.0"},
|
||||
{100.23, "00.2", "00.2", "00.2"},
|
||||
{543210.0, "10.0", "10.0", "10.0"}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int caseNumber = 0;
|
||||
for (Object[][][] cas : cases) {
|
||||
int minInt = (Integer) cas[0][0][0];
|
||||
int maxInt = (Integer) cas[0][0][1];
|
||||
int minFrac = (Integer) cas[0][1][0];
|
||||
int maxFrac = (Integer) cas[0][1][1];
|
||||
int minSig = (Integer) cas[0][2][0];
|
||||
int maxSig = (Integer) cas[0][2][1];
|
||||
|
||||
Properties properties = new Properties();
|
||||
FormatQuantity4 fq = new FormatQuantity4();
|
||||
properties.setMinimumIntegerDigits(minInt);
|
||||
properties.setMaximumIntegerDigits(maxInt);
|
||||
properties.setMinimumFractionDigits(minFrac);
|
||||
properties.setMaximumFractionDigits(maxFrac);
|
||||
properties.setMinimumSignificantDigits(minSig);
|
||||
properties.setMaximumSignificantDigits(maxSig);
|
||||
|
||||
int runNumber = 0;
|
||||
for (Object[] run : cas[1]) {
|
||||
double input = (Double) run[0];
|
||||
String expected1 = (String) run[1];
|
||||
String expected2 = (String) run[2];
|
||||
String expected3 = (String) run[3];
|
||||
|
||||
properties.setSignificantDigitsMode(SignificantDigitsMode.OVERRIDE_MAXIMUM_FRACTION);
|
||||
fq.setToDouble(input);
|
||||
SignificantDigitsRounder.getInstance(properties).apply(fq);
|
||||
assertEquals(
|
||||
"Case " + caseNumber + ", run " + runNumber + ", mode 0: " + fq,
|
||||
expected1,
|
||||
formatQuantityToString(fq));
|
||||
|
||||
properties.setSignificantDigitsMode(SignificantDigitsMode.RESPECT_MAXIMUM_FRACTION);
|
||||
fq.setToDouble(input);
|
||||
SignificantDigitsRounder.getInstance(properties).apply(fq);
|
||||
assertEquals(
|
||||
"Case " + caseNumber + ", run " + runNumber + ", mode 1: " + fq,
|
||||
expected2,
|
||||
formatQuantityToString(fq));
|
||||
|
||||
properties.setSignificantDigitsMode(SignificantDigitsMode.ENSURE_MINIMUM_SIGNIFICANT);
|
||||
fq.setToDouble(input);
|
||||
SignificantDigitsRounder.getInstance(properties).apply(fq);
|
||||
assertEquals(
|
||||
"Case " + caseNumber + ", run " + runNumber + ", mode 2: " + fq,
|
||||
expected3,
|
||||
formatQuantityToString(fq));
|
||||
|
||||
runNumber++;
|
||||
}
|
||||
|
||||
caseNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
private String formatQuantityToString(FormatQuantity fq) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int udm = fq.getUpperDisplayMagnitude();
|
||||
int ldm = fq.getLowerDisplayMagnitude();
|
||||
if (udm == -1) sb.append('.');
|
||||
for (int m = udm; m >= ldm; m--) {
|
||||
sb.append(fq.getDigit(m));
|
||||
if (m == 0 && m > ldm) sb.append('.');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user