private transient Map<TimeUnit, Map<String, Object[]>> 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".
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");
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) {
}
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<TimeUnit, Map<String, Object[]>>();
Set<String> pluralKeywords = pluralRules.getKeywords();
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<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns,
int style, Set<String> pluralKeywords) {
*
*/
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));
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),
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());
}
}
}