ICU-10219 Fix rounding in TimeUnitFormat for JAVA.

X-SVN-Rev: 34554
This commit is contained in:
Travis Keep 2013-10-10 22:35:06 +00:00
parent a3e12a9fe7
commit 80b75a5817
2 changed files with 46 additions and 28 deletions

View File

@ -7,6 +7,7 @@
package com.ibm.icu.text; package com.ibm.icu.text;
import java.text.FieldPosition; import java.text.FieldPosition;
import java.text.ParseException;
import java.text.ParsePosition; import java.text.ParsePosition;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
@ -189,18 +190,6 @@ public class TimeUnitFormat extends MeasureFormat {
} else { } else {
this.format = format; this.format = format;
} }
// reset the number formatter in the timeUnitToCountToPatterns map
if (isReady == false) {
return this;
}
for (Map<String, Object[]> countToPattern : timeUnitToCountToPatterns.values()) {
for (Object[] pair : countToPattern.values()) {
MessageFormat pattern = (MessageFormat)pair[FULL_NAME];
pattern.setFormatByArgumentIndex(0, format);
pattern = (MessageFormat)pair[ABBREVIATED_NAME];
pattern.setFormatByArgumentIndex(0, format);
}
}
return this; return this;
} }
@ -221,10 +210,16 @@ public class TimeUnitFormat extends MeasureFormat {
} }
TimeUnitAmount amount = (TimeUnitAmount) obj; TimeUnitAmount amount = (TimeUnitAmount) obj;
Map<String, Object[]> countToPattern = timeUnitToCountToPatterns.get(amount.getTimeUnit()); Map<String, Object[]> countToPattern = timeUnitToCountToPatterns.get(amount.getTimeUnit());
double number = amount.getNumber().doubleValue(); String formattedNumber = format.format(amount.getNumber());
String count = pluralRules.select(number); double doubleNumber = amount.getNumber().doubleValue();
String count;
if (format instanceof DecimalFormat) {
count = pluralRules.select(((DecimalFormat) format).getFixedDecimal(doubleNumber));
} else {
count = pluralRules.select(doubleNumber);
}
MessageFormat pattern = (MessageFormat)(countToPattern.get(count))[style]; MessageFormat pattern = (MessageFormat)(countToPattern.get(count))[style];
return pattern.format(new Object[]{amount.getNumber()}, toAppendTo, pos); return pattern.format(new Object[]{formattedNumber}, toAppendTo, pos);
} }
/** /**
@ -264,10 +259,17 @@ public class TimeUnitFormat extends MeasureFormat {
// pattern with Number as beginning, // pattern with Number as beginning,
// such as "{0} d". // such as "{0} d".
// check to make sure that the timeUnit is consistent // check to make sure that the timeUnit is consistent
temp = (Number)((Object[])parsed)[0]; Object tempObj = ((Object[])parsed)[0];
String select = pluralRules.select(temp.doubleValue()); if (tempObj instanceof Number) {
if (!count.equals(select)) { temp = (Number) tempObj;
continue; } else {
// Since we now format the number ourselves, parseObject will likely give us back a String for
// the number. When this happens we must parse the formatted number ourselves.
try {
temp = format.parse((String) tempObj.toString());
} catch (ParseException e) {
continue;
}
} }
} }
int parseDistance = pos.getIndex() - oldPos; int parseDistance = pos.getIndex() - oldPos;
@ -377,9 +379,6 @@ public class TimeUnitFormat extends MeasureFormat {
continue; continue;
String pattern = oneUnitRes.get(pluralIndex).getString(); String pattern = oneUnitRes.get(pluralIndex).getString();
final MessageFormat messageFormat = new MessageFormat(pattern, locale); final MessageFormat messageFormat = new MessageFormat(pattern, locale);
if (format != null) {
messageFormat.setFormatByArgumentIndex(0, format);
}
// save both full name and abbreviated name in one table // save both full name and abbreviated name in one table
// is good space-wise, but it degrades performance, // is good space-wise, but it degrades performance,
// since it needs to check whether the needed space // since it needs to check whether the needed space
@ -457,9 +456,6 @@ public class TimeUnitFormat extends MeasureFormat {
ICUResourceBundle oneUnitRes = unitsRes.getWithFallback(srcTimeUnitName); ICUResourceBundle oneUnitRes = unitsRes.getWithFallback(srcTimeUnitName);
String pattern = oneUnitRes.getStringWithFallback(searchPluralCount); String pattern = oneUnitRes.getStringWithFallback(searchPluralCount);
final MessageFormat messageFormat = new MessageFormat(pattern, locale); final MessageFormat messageFormat = new MessageFormat(pattern, locale);
if (format != null) {
messageFormat.setFormatByArgumentIndex(0, format);
}
Object[] pair = countToPatterns.get(srcPluralCount); Object[] pair = countToPatterns.get(srcPluralCount);
if (pair == null) { if (pair == null) {
pair = new Object[2]; pair = new Object[2];
@ -503,9 +499,6 @@ public class TimeUnitFormat extends MeasureFormat {
} else if ( timeUnit == TimeUnit.YEAR ) { } else if ( timeUnit == TimeUnit.YEAR ) {
messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_YEAR, locale); messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_YEAR, locale);
} }
if (format != null && messageFormat != null) {
messageFormat.setFormatByArgumentIndex(0, format);
}
Object[] pair = countToPatterns.get(srcPluralCount); Object[] pair = countToPatterns.get(srcPluralCount);
if (pair == null) { if (pair == null) {
pair = new Object[2]; pair = new Object[2];

View File

@ -11,6 +11,7 @@ import java.text.ParsePosition;
import java.util.Locale; import java.util.Locale;
import com.ibm.icu.dev.test.TestFmwk; import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.text.NumberFormat; import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.text.TimeUnitFormat; import com.ibm.icu.text.TimeUnitFormat;
import com.ibm.icu.util.TimeUnit; import com.ibm.icu.util.TimeUnit;
@ -25,6 +26,30 @@ public class TimeUnitTest extends TestFmwk {
public static void main(String[] args) throws Exception{ public static void main(String[] args) throws Exception{
new TimeUnitTest().run(args); new TimeUnitTest().run(args);
} }
public void Test10219FractionalPlurals() {
TimeUnitFormat tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.FULL_NAME);
String[] expected = {"1 minute", "1.5 minutes", "1.58 minutes"};
for (int i = 2; i >= 0; i--) {
NumberFormat nf = NumberFormat.getNumberInstance(ULocale.ENGLISH);
nf.setRoundingMode(BigDecimal.ROUND_DOWN);
nf.setMaximumFractionDigits(i);
tuf.setNumberFormat(nf);
assertEquals("Test10219", expected[i], tuf.format(new TimeUnitAmount(1.588, TimeUnit.MINUTE)));
}
}
public void Test10219FactionalPluralsParse() throws ParseException {
TimeUnitFormat tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.FULL_NAME);
ParsePosition ppos = new ParsePosition(0);
String parseString = "1 minutes";
tuf.parseObject(parseString, ppos);
// Parsing should go all the way to the end of the string.
// We want the longest match, and we don't care if the plural form of the unit
// matches the plural form of the number.
assertEquals("Test10219FractionalPluralParse", parseString.length(), ppos.getIndex());
}
public void TestBasic() { public void TestBasic() {
String[] locales = {"en", "sl", "fr", "zh", "ar", "ru", "zh_Hant"}; String[] locales = {"en", "sl", "fr", "zh", "ar", "ru", "zh_Hant"};