ICU-10640 Carry rounding measure amounts down except the last to the JAVA implementation.

X-SVN-Rev: 35182
This commit is contained in:
Travis Keep 2014-02-20 18:54:00 +00:00
parent 8b58bace5e
commit d09b746a61
2 changed files with 53 additions and 13 deletions

View File

@ -31,6 +31,7 @@ import com.ibm.icu.impl.DontCareFieldPosition;
import com.ibm.icu.impl.ICUResourceBundle; import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache; import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimplePatternFormatter; import com.ibm.icu.impl.SimplePatternFormatter;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.util.Currency; import com.ibm.icu.util.Currency;
import com.ibm.icu.util.CurrencyAmount; import com.ibm.icu.util.CurrencyAmount;
import com.ibm.icu.util.Measure; import com.ibm.icu.util.Measure;
@ -121,6 +122,8 @@ public class MeasureFormat extends UFormat {
private final transient NumericFormatters numericFormatters; private final transient NumericFormatters numericFormatters;
private final transient ImmutableNumberFormat currencyFormat; private final transient ImmutableNumberFormat currencyFormat;
private final transient ImmutableNumberFormat integerFormat;
private static final SimpleCache<ULocale,Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>>> localeToUnitToStyleToCountToFormat private static final SimpleCache<ULocale,Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>>> localeToUnitToStyleToCountToFormat
= new SimpleCache<ULocale,Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>>>(); = new SimpleCache<ULocale,Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>>>();
@ -247,7 +250,10 @@ public class MeasureFormat extends UFormat {
localeToNumericDurationFormatters.put(locale, formatters); localeToNumericDurationFormatters.put(locale, formatters);
} }
} }
NumberFormat intFormat = NumberFormat.getInstance(locale);
intFormat.setMaximumFractionDigits(0);
intFormat.setMinimumFractionDigits(0);
intFormat.setRoundingMode(BigDecimal.ROUND_DOWN);
return new MeasureFormat( return new MeasureFormat(
locale, locale,
formatWidth, formatWidth,
@ -256,7 +262,8 @@ public class MeasureFormat extends UFormat {
unitToStyleToCountToFormat, unitToStyleToCountToFormat,
formatters, formatters,
new ImmutableNumberFormat( new ImmutableNumberFormat(
NumberFormat.getInstance(locale, formatWidth.getCurrencyStyle()))); NumberFormat.getInstance(locale, formatWidth.getCurrencyStyle())),
new ImmutableNumberFormat(intFormat));
} }
/** /**
@ -297,7 +304,7 @@ public class MeasureFormat extends UFormat {
} else if (obj instanceof Measure[]) { } else if (obj instanceof Measure[]) {
toAppendTo.append(formatMeasures(new StringBuilder(), fpos, (Measure[]) obj)); toAppendTo.append(formatMeasures(new StringBuilder(), fpos, (Measure[]) obj));
} else if (obj instanceof Measure){ } else if (obj instanceof Measure){
toAppendTo.append(formatMeasure((Measure) obj, new StringBuilder(), fpos)); toAppendTo.append(formatMeasure((Measure) obj, numberFormat, new StringBuilder(), fpos));
} else { } else {
throw new IllegalArgumentException(obj.toString()); throw new IllegalArgumentException(obj.toString());
} }
@ -362,7 +369,7 @@ public class MeasureFormat extends UFormat {
return appendTo; return appendTo;
} }
if (measures.length == 1) { if (measures.length == 1) {
return formatMeasure(measures[0], appendTo, fieldPosition); return formatMeasure(measures[0], numberFormat, appendTo, fieldPosition);
} }
if (formatWidth == FormatWidth.NUMERIC) { if (formatWidth == FormatWidth.NUMERIC) {
@ -382,7 +389,9 @@ public class MeasureFormat extends UFormat {
// Fast track: No field position. // Fast track: No field position.
String[] results = new String[measures.length]; String[] results = new String[measures.length];
for (int i = 0; i < measures.length; i++) { for (int i = 0; i < measures.length; i++) {
results[i] = formatMeasure(measures[i]); results[i] = formatMeasure(
measures[i],
i == measures.length - 1 ? numberFormat : integerFormat);
} }
return appendTo.append(listFormatter.format((Object[]) results)); return appendTo.append(listFormatter.format((Object[]) results));
@ -482,7 +491,8 @@ public class MeasureFormat extends UFormat {
this.rules, this.rules,
this.unitToStyleToCountToFormat, this.unitToStyleToCountToFormat,
this.numericFormatters, this.numericFormatters,
this.currencyFormat); this.currencyFormat,
this.integerFormat);
} }
private MeasureFormat( private MeasureFormat(
@ -492,7 +502,8 @@ public class MeasureFormat extends UFormat {
PluralRules rules, PluralRules rules,
Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat, Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat,
NumericFormatters formatters, NumericFormatters formatters,
ImmutableNumberFormat currencyFormat) { ImmutableNumberFormat currencyFormat,
ImmutableNumberFormat integerFormat) {
setLocale(locale, locale); setLocale(locale, locale);
this.formatWidth = formatWidth; this.formatWidth = formatWidth;
this.numberFormat = format; this.numberFormat = format;
@ -500,6 +511,7 @@ public class MeasureFormat extends UFormat {
this.unitToStyleToCountToFormat = unitToStyleToCountToFormat; this.unitToStyleToCountToFormat = unitToStyleToCountToFormat;
this.numericFormatters = formatters; this.numericFormatters = formatters;
this.currencyFormat = currencyFormat; this.currencyFormat = currencyFormat;
this.integerFormat = integerFormat;
} }
MeasureFormat() { MeasureFormat() {
@ -510,6 +522,7 @@ public class MeasureFormat extends UFormat {
this.unitToStyleToCountToFormat = null; this.unitToStyleToCountToFormat = null;
this.numericFormatters = null; this.numericFormatters = null;
this.currencyFormat = null; this.currencyFormat = null;
this.integerFormat = null;
} }
static class NumericFormatters { static class NumericFormatters {
@ -601,14 +614,17 @@ public class MeasureFormat extends UFormat {
return unitToStyleToCountToFormat; return unitToStyleToCountToFormat;
} }
private String formatMeasure(Measure measure) { private String formatMeasure(Measure measure, ImmutableNumberFormat nf) {
return formatMeasure( return formatMeasure(
measure, new StringBuilder(), measure, nf, new StringBuilder(),
DontCareFieldPosition.INSTANCE).toString(); DontCareFieldPosition.INSTANCE).toString();
} }
private StringBuilder formatMeasure( private StringBuilder formatMeasure(
Measure measure, StringBuilder appendTo, FieldPosition fieldPosition) { Measure measure,
ImmutableNumberFormat nf,
StringBuilder appendTo,
FieldPosition fieldPosition) {
if (measure.getUnit() instanceof Currency) { if (measure.getUnit() instanceof Currency) {
return appendTo.append( return appendTo.append(
currencyFormat.format( currencyFormat.format(
@ -620,7 +636,7 @@ public class MeasureFormat extends UFormat {
Number n = measure.getNumber(); Number n = measure.getNumber();
MeasureUnit unit = measure.getUnit(); MeasureUnit unit = measure.getUnit();
UFieldPosition fpos = new UFieldPosition(fieldPosition.getFieldAttribute(), fieldPosition.getField()); UFieldPosition fpos = new UFieldPosition(fieldPosition.getFieldAttribute(), fieldPosition.getField());
StringBuffer formattedNumber = numberFormat.format(n, new StringBuffer(), fpos); StringBuffer formattedNumber = nf.format(n, new StringBuffer(), fpos);
String keyword = rules.select(new PluralRules.FixedDecimal(n.doubleValue(), fpos.getCountVisibleFractionDigits(), fpos.getFractionDigits())); String keyword = rules.select(new PluralRules.FixedDecimal(n.doubleValue(), fpos.getCountVisibleFractionDigits(), fpos.getFractionDigits()));
Map<FormatWidth, QuantityFormatter> styleToCountToFormat = unitToStyleToCountToFormat.get(unit); Map<FormatWidth, QuantityFormatter> styleToCountToFormat = unitToStyleToCountToFormat.get(unit);
@ -705,13 +721,14 @@ public class MeasureFormat extends UFormat {
int fieldPositionFoundIndex = -1; int fieldPositionFoundIndex = -1;
for (int i = 0; i < measures.length; ++i) { for (int i = 0; i < measures.length; ++i) {
ImmutableNumberFormat nf = (i == measures.length - 1 ? numberFormat : integerFormat);
if (fieldPositionFoundIndex == -1) { if (fieldPositionFoundIndex == -1) {
results[i] = formatMeasure(measures[i], new StringBuilder(), fpos).toString(); results[i] = formatMeasure(measures[i], nf, new StringBuilder(), fpos).toString();
if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) { if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
fieldPositionFoundIndex = i; fieldPositionFoundIndex = i;
} }
} else { } else {
results[i] = formatMeasure(measures[i]); results[i] = formatMeasure(measures[i], nf);
} }
} }
ListFormatter.FormattedListBuilder builder = ListFormatter.FormattedListBuilder builder =

View File

@ -575,6 +575,29 @@ public class MeasureUnitTest extends TestFmwk {
assertEquals("getWidth", MeasureFormat.FormatWidth.WIDE, mf.getWidth()); assertEquals("getWidth", MeasureFormat.FormatWidth.WIDE, mf.getWidth());
} }
public void testDoubleZero() {
ULocale en = new ULocale("en");
NumberFormat nf = NumberFormat.getInstance(en);
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
MeasureFormat mf = MeasureFormat.getInstance(en, FormatWidth.WIDE, nf);
assertEquals(
"Positive Rounding",
"4 hours, 23 minutes, 16.00 seconds",
mf.formatMeasures(
new Measure(4.7, MeasureUnit.HOUR),
new Measure(23, MeasureUnit.MINUTE),
new Measure(16, MeasureUnit.SECOND)));
assertEquals(
"Negative Rounding",
"-4 hours, 23 minutes, 16.00 seconds",
mf.formatMeasures(
new Measure(-4.7, MeasureUnit.HOUR),
new Measure(23, MeasureUnit.MINUTE),
new Measure(16, MeasureUnit.SECOND)));
}
static void generateCXXHConstants() { static void generateCXXHConstants() {
Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>(); Map<String, MeasureUnit> seen = new HashMap<String, MeasureUnit>();
TreeMap<String, List<MeasureUnit>> allUnits = new TreeMap<String, List<MeasureUnit>>(); TreeMap<String, List<MeasureUnit>> allUnits = new TreeMap<String, List<MeasureUnit>>();