From: Travis Keep Date: Thu, 28 Mar 2013 22:25:47 +0000 (+0000) Subject: ICU-10017 Add test for formatPeriod for numeric style and for TimePeriods with just... X-Git-Tag: milestone-59-0-1~2969 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3af99923b3b9b6f3f43898ada6a130cc6bf839e9;p=icu ICU-10017 Add test for formatPeriod for numeric style and for TimePeriods with just a single field. X-SVN-Rev: 33475 --- diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/TimeUnitFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/TimeUnitFormat.java index d6a4170ba12..6b7def06646 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/TimeUnitFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/TimeUnitFormat.java @@ -100,12 +100,15 @@ public class TimeUnitFormat extends MeasureFormat { private transient Map> timeUnitToCountToPatterns; private transient PluralRules pluralRules; private transient ListFormatter listFormatter; + private transient MessageFormat hourMinute; + private transient MessageFormat minuteSecond; + private transient MessageFormat hourMinuteSecond; private transient boolean isReady; private int style; // When style is set to NUMERIC, this field is set to true and the style // field becomes ABBREVIATED_NAME. - private boolean numeric; + private boolean isNumericStyle; /** * Create empty format using full name style, for example, "hours". @@ -148,7 +151,7 @@ public class TimeUnitFormat extends MeasureFormat { public TimeUnitFormat(ULocale locale, int style) { if (style == NUMERIC) { style = ABBREVIATED_NAME; - numeric = true; + isNumericStyle = true; } if (style < FULL_NAME || style >= TOTAL_STYLES) { throw new IllegalArgumentException("style should be either FULL_NAME or ABBREVIATED_NAME style"); @@ -258,6 +261,12 @@ public class TimeUnitFormat extends MeasureFormat { if (!isReady) { setup(); } + if (isNumericStyle) { + String result = formatPeriodAsNumeric(timePeriod); + if (result != null) { + return result; + } + } String[] items = new String[timePeriod.size()]; int idx = 0; for (TimeUnitAmount amount : timePeriod) { @@ -370,6 +379,10 @@ public class TimeUnitFormat extends MeasureFormat { } pluralRules = PluralRules.forLocale(locale); listFormatter = ListFormatter.getInstance(locale); + DateTimePatternGenerator df = DateTimePatternGenerator.getInstance(locale); + hourMinute = getPattern(df, "hm", locale, "{0}", "{1,number,00.###}", null); + minuteSecond = getPattern(df, "ms", locale, null, "{1}", "{2,number,00.###}"); + hourMinuteSecond = getPattern(df, "hms", locale, "{0}", "{1,number,00}", "{2,number,00.###}"); timeUnitToCountToPatterns = new HashMap>(); Set pluralKeywords = pluralRules.getKeywords(); @@ -377,7 +390,64 @@ public class TimeUnitFormat extends MeasureFormat { setup("unitsShort", timeUnitToCountToPatterns, ABBREVIATED_NAME, pluralKeywords); isReady = true; } - + + private MessageFormat getPattern(DateTimePatternGenerator dtpg, String skeleton, ULocale locale, + String h, String m, String s) { + String pat = dtpg.getBestPattern(skeleton); + StringBuilder buffer = new StringBuilder(); + for (Object item : new DateTimePatternGenerator.FormatParser().set(pat).getItems()) { + if (item instanceof DateTimePatternGenerator.VariableField) { + DateTimePatternGenerator.VariableField fld = (DateTimePatternGenerator.VariableField)item; + switch (fld.getType()) { + case DateTimePatternGenerator.HOUR: buffer.append(h); break; + case DateTimePatternGenerator.MINUTE: buffer.append(m); break; + case DateTimePatternGenerator.SECOND: buffer.append(s); break; + } + } else { + buffer.append(item); + } + } + return new MessageFormat(buffer.toString(), locale); + } + + private String formatPeriodAsNumeric(TimePeriod timePeriod) { + TimeUnit biggestUnit = null, smallestUnit = null; + for (TimeUnitAmount tua : timePeriod) { + if (biggestUnit == null) { + biggestUnit = tua.getTimeUnit(); + } + smallestUnit = tua.getTimeUnit(); + } + // We have to trim the result of MessageFormat.format() not sure why. + if (biggestUnit == TimeUnit.HOUR && smallestUnit == TimeUnit.SECOND) { + return hourMinuteSecond.format(new Object[]{ + getZeroedAmount(timePeriod, TimeUnit.HOUR), + getZeroedAmount(timePeriod, TimeUnit.MINUTE), + getZeroedAmount(timePeriod, TimeUnit.SECOND)}).trim(); + + } + if (biggestUnit == TimeUnit.MINUTE && smallestUnit == TimeUnit.SECOND) { + return minuteSecond.format(new Object[]{ + null, + getZeroedAmount(timePeriod, TimeUnit.MINUTE), + getZeroedAmount(timePeriod, TimeUnit.SECOND)}).trim(); + + } + if (biggestUnit == TimeUnit.HOUR && smallestUnit == TimeUnit.MINUTE) { + return hourMinute.format(new Object[]{ + getZeroedAmount(timePeriod, TimeUnit.HOUR), + getZeroedAmount(timePeriod, TimeUnit.MINUTE)}).trim(); + } + return null; + } + + private Number getZeroedAmount(TimePeriod timePeriod, TimeUnit timeUnit) { + TimeUnitAmount tua = timePeriod.getAmount(timeUnit); + if (tua == null) { + return Double.valueOf(0); + } + return tua.getNumber(); + } private void setup(String resourceKey, Map> timeUnitToCountToPatterns, int style, Set pluralKeywords) { diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/TimeUnitTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/TimeUnitTest.java index 84b63f74aa4..63bce453087 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/TimeUnitTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/TimeUnitTest.java @@ -23,7 +23,11 @@ import com.ibm.icu.util.ULocale; * */ public class TimeUnitTest extends TestFmwk { - + private static final TimePeriod _19m = TimePeriod.forAmounts( + new TimeUnitAmount(19.0, TimeUnit.MINUTE)); + private static final TimePeriod _19m_28s = TimePeriod.forAmounts( + new TimeUnitAmount(19.0, TimeUnit.MINUTE), + new TimeUnitAmount(28.0, TimeUnit.SECOND)); private static final TimePeriod _1h_23_5s = TimePeriod.forAmounts( new TimeUnitAmount(1.0, TimeUnit.HOUR), new TimeUnitAmount(23.5, TimeUnit.SECOND)); @@ -31,6 +35,9 @@ public class TimeUnitTest extends TestFmwk { new TimeUnitAmount(1.0, TimeUnit.HOUR), new TimeUnitAmount(0.0, TimeUnit.MINUTE), new TimeUnitAmount(23.0, TimeUnit.SECOND)); + private static final TimePeriod _5h_17m = TimePeriod.forAmounts( + new TimeUnitAmount(5.0, TimeUnit.HOUR), + new TimeUnitAmount(17.0, TimeUnit.MINUTE)); private static final TimePeriod _2y_5M_3w_4d = TimePeriod.forAmounts( new TimeUnitAmount(2.0, TimeUnit.YEAR), new TimeUnitAmount(5.0, TimeUnit.MONTH), @@ -342,25 +349,42 @@ public class TimeUnitTest extends TestFmwk { public void TestFormatPeriodEn() { Object[][] fullData = { + {_19m, "19 minutes"}, {_1h_23_5s, "1 hour and 23.5 seconds"}, {_1h_0m_23s, "1 hour, 0 minutes, and 23 seconds"}, {_2y_5M_3w_4d, "2 years, 5 months, 3 weeks, and 4 days"}}; + Object[][] abbrevData = { + {_19m, "19 mins"}, + {_1h_23_5s, "1 hr and 23.5 secs"}, + {_1h_0m_23s, "1 hr, 0 mins, and 23 secs"}, + {_2y_5M_3w_4d, "2 yrs, 5 mths, 3 wks, and 4 days"}}; + Object[][] numericData = { + {_19m, "19 mins"}, + {_1h_23_5s, "1:00:23.5"}, + {_1h_0m_23s, "1:00:23"}, + {_5h_17m, "5:17"}, + {_19m_28s, "19:28"}, + {_2y_5M_3w_4d, "2 yrs, 5 mths, 3 wks, and 4 days"}}; TimeUnitFormat tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.FULL_NAME); verifyFormatPeriod("en FULL", tuf, fullData); + tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.ABBREVIATED_NAME); + verifyFormatPeriod("en ABBREV", tuf, abbrevData); + tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.NUMERIC); + verifyFormatPeriod("en NUMERIC", tuf, numericData); } private void verifyFormatPeriod(String desc, TimeUnitFormat tuf, Object[][] testData) { + StringBuilder builder = new StringBuilder(); boolean failure = false; for (Object[] testCase : testData) { - try { - assertEquals(desc, testCase[1], tuf.formatTimePeriod((TimePeriod) testCase[0])); - } catch (RuntimeException e) { - logln(e.getMessage()); + String actual = tuf.formatTimePeriod((TimePeriod) testCase[0]); + if (!testCase[1].equals(actual)) { + builder.append(String.format("%s: Expected: '%s', got: '%s'\n", desc, testCase[1], actual)); failure = true; } } if (failure) { - errln("Test failed."); + errln(builder.toString()); } } }