icu4j/main/classes/core/.settings/org.eclipse.core.resources.prefs -text
icu4j/main/classes/core/.settings/org.eclipse.jdt.core.prefs -text
icu4j/main/classes/core/manifest.stub -text
-icu4j/main/classes/core/src/com/ibm/icu/util/TimePeriod.java -text
icu4j/main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch -text
icu4j/main/classes/currdata/.settings/org.eclipse.core.resources.prefs -text
icu4j/main/classes/currdata/.settings/org.eclipse.jdt.core.prefs -text
import java.util.TreeMap;
import com.ibm.icu.impl.ICUResourceBundle;
-import com.ibm.icu.util.TimePeriod;
import com.ibm.icu.util.TimeUnit;
import com.ibm.icu.util.TimeUnitAmount;
-import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;
import com.ibm.icu.util.UResourceBundle;
*/
public static final int ABBREVIATED_NAME = 1;
- /**
- * Constant for numeric style format.
- * NUMERIC strives to be as brief as possible. For example: 3:05:47.
- * @draft ICU 52
- */
- public static final int NUMERIC = 2;
-
- private static final int TOTAL_STYLES = 3;
+ private static final int TOTAL_STYLES = 2;
private static final long serialVersionUID = -3707773153184971529L;
private ULocale locale;
private transient Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns;
private transient PluralRules pluralRules;
- private transient ListFormatter listFormatter;
- private transient DateFormat hourMinute;
- private transient DateFormat minuteSecond;
- private transient DateFormat hourMinuteSecond;
private transient boolean isReady;
private int style;
*/
public StringBuffer format(Object obj, StringBuffer toAppendTo,
FieldPosition pos) {
- if ( !(obj instanceof TimeUnitAmount) && !(obj instanceof TimePeriod)) {
+ if ( !(obj instanceof TimeUnitAmount) ) {
throw new IllegalArgumentException(
- "can only format TimeUnitAmount or TimePeriod objects");
+ "cannot format a non TimeUnitAmount object");
}
if (!isReady) {
setup();
}
- if (obj instanceof TimePeriod) {
- // TODO: set FieldPosition, see ICU tickets 10156 and 10157.
- toAppendTo.append(formatTimePeriod((TimePeriod) obj));
- return toAppendTo;
- }
TimeUnitAmount amount = (TimeUnitAmount) obj;
Map<String, Object[]> countToPattern = timeUnitToCountToPatterns.get(amount.getTimeUnit());
double number = amount.getNumber().doubleValue();
String count = pluralRules.select(number);
- // A hack since NUMERIC really isn't a full fledged style
- int effectiveStyle = (style == NUMERIC) ? ABBREVIATED_NAME : style;
- MessageFormat pattern = (MessageFormat)(countToPattern.get(count))[effectiveStyle];
+ MessageFormat pattern = (MessageFormat)(countToPattern.get(count))[style];
return pattern.format(new Object[]{amount.getNumber()}, toAppendTo, pos);
}
- private String formatTimePeriod(TimePeriod timePeriod) {
- if (!isReady) {
- setup();
- }
- if (style == NUMERIC) {
- String result = formatPeriodAsNumeric(timePeriod);
- if (result != null) {
- return result;
- }
- }
- String[] items = new String[timePeriod.length()];
- int idx = 0;
- for (TimeUnitAmount amount : timePeriod) {
- items[idx++] = format(amount);
- }
- return listFormatter.format((Object[]) items);
- }
-
/**
- * Parse a TimeUnitAmount. Parsing TimePeriod objects is not supported.
- * If parseObject is called on a formatted TimePeriod string, it try to parse it
- * as a TimeUnitAmount. For example,
- * <code>parseObject("5 hours and 34 minutes", pos)</code>
- * returns a TimeUnitAmount representing 5 hours and updates pos to point to the
- * space after the s in hours.
+ * Parse a TimeUnitAmount.
* @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
* @stable ICU 4.0
*/
for (Entry<String, Object[]> patternEntry : countToPattern.entrySet()) {
String count = patternEntry.getKey();
for (int styl = FULL_NAME; styl < TOTAL_STYLES; ++styl) {
- if (styl == NUMERIC) {
- // Numeric isn't a real style, so skip it.
- continue;
- }
MessageFormat pattern = (MessageFormat)(patternEntry.getValue())[styl];
pos.setErrorIndex(-1);
pos.setIndex(oldPos);
format = NumberFormat.getNumberInstance(locale);
}
pluralRules = PluralRules.forLocale(locale);
- if (style == FULL_NAME) {
- listFormatter = ListFormatter.getInstance(locale, ListFormatter.Style.DURATION);
- } else {
- listFormatter = ListFormatter.getInstance(locale, ListFormatter.Style.DURATION_SHORT);
- }
- hourMinute = loadNumericDurationFormat(locale, "hm");
- minuteSecond = loadNumericDurationFormat(locale, "ms");
- hourMinuteSecond = loadNumericDurationFormat(locale, "hms");
timeUnitToCountToPatterns = new HashMap<TimeUnit, Map<String, Object[]>>();
Set<String> pluralKeywords = pluralRules.getKeywords();
setup("units/duration", timeUnitToCountToPatterns, FULL_NAME, pluralKeywords);
isReady = true;
}
- // type is one of "hm", "ms" or "hms"
- private static DateFormat loadNumericDurationFormat(ULocale ulocale, String type) {
- ICUResourceBundle r = (ICUResourceBundle)UResourceBundle.
- getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, ulocale);
- r = r.getWithFallback(String.format("durationUnits/%s", type));
- // We replace 'h' with 'H' because 'h' does not make sense in the context of durations.
- DateFormat result = new SimpleDateFormat(r.getString().replace("h", "H"));
- result.setTimeZone(TimeZone.GMT_ZONE);
- return result;
- }
-
- private String formatPeriodAsNumeric(TimePeriod timePeriod) {
- TimeUnit biggestUnit = null, smallestUnit = null;
- Number smallestUnitAmount = null;
- for (TimeUnitAmount tua : timePeriod) {
- if (biggestUnit == null) {
- biggestUnit = tua.getTimeUnit();
- }
- smallestUnit = tua.getTimeUnit();
- smallestUnitAmount = tua.getNumber();
- }
- long millis = (long) (((getAmountOrZero(timePeriod, TimeUnit.HOUR) * 60.0
- + getAmountOrZero(timePeriod, TimeUnit.MINUTE)) * 60.0
- + getAmountOrZero(timePeriod, TimeUnit.SECOND)) * 1000.0);
- Date d = new Date(millis);
- if (biggestUnit == TimeUnit.HOUR && smallestUnit == TimeUnit.SECOND) {
- return numericFormat(
- d, hourMinuteSecond, DateFormat.Field.SECOND, smallestUnitAmount);
- }
- if (biggestUnit == TimeUnit.MINUTE && smallestUnit == TimeUnit.SECOND) {
- return numericFormat(
- d, minuteSecond, DateFormat.Field.SECOND, smallestUnitAmount);
- }
- if (biggestUnit == TimeUnit.HOUR && smallestUnit == TimeUnit.MINUTE) {
- return numericFormat(d, hourMinute, DateFormat.Field.MINUTE, smallestUnitAmount);
- }
- return null;
- }
-
- /**
- * numericFormat allows us to show fractional durations using numeric
- * style e.g 12:34:56.7. This function is necessary because there is no way to express
- * fractions of durations other than seconds with current DateFormat objects.
- *
- * After formatting the duration using a DateFormat object in the usual way, it
- * replaces the smallest field in the formatted string with the exact fractional
- * amount of that smallest field formatted with this object's NumberFormat object.
- *
- * @param duration The duration to format in milliseconds. The loss of precision here
- * is ok because we also pass in the exact amount of the smallest field.
- * @param formatter formats the date.
- * @param smallestField the smallest defined field in duration to be formatted.
- * @param smallestAmount the exact fractional value of the smallest amount.
- * @return duration formatted numeric style.
- */
- private String numericFormat(
- Date duration,
- DateFormat formatter,
- DateFormat.Field smallestField,
- Number smallestAmount) {
- // Format the smallest amount ahead of time.
- String smallestAmountFormatted = format.format(smallestAmount);
-
- // Format the duration using the provided DateFormat object. The smallest
- // field in this result will be missing the fractional part.
- AttributedCharacterIterator iterator = formatter.formatToCharacterIterator(duration);
-
- // The final formatted duration will be written here.
- StringBuilder builder = new StringBuilder();
-
- // iterate through formatted text copying to 'builder' one character at a time.
- // When we get to the smallest amount, skip over it and copy
- // 'smallestAmountFormatted' to the builder instead.
- for (iterator.first(); iterator.getIndex() < iterator.getEndIndex();) {
- if (iterator.getAttributes().containsKey(smallestField)) {
- builder.append(smallestAmountFormatted);
- iterator.setIndex(iterator.getRunLimit(smallestField));
- } else {
- builder.append(iterator.current());
- iterator.next();
- }
- }
- return builder.toString();
- }
-
- private static double getAmountOrZero(TimePeriod timePeriod, TimeUnit timeUnit) {
- TimeUnitAmount tua = timePeriod.getAmount(timeUnit);
- if (tua == null) {
- return 0.0;
- }
- return tua.getNumber().doubleValue();
- }
-
private void setup(String resourceKey, Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns,
int style, Set<String> pluralKeywords) {
// fill timeUnitToCountToPatterns from resource file
+++ /dev/null
-/*
- *******************************************************************************
- * Copyright (C) 2013, International Business Machines Corporation and *
- * others. All Rights Reserved. *
- *******************************************************************************
- */
-package com.ibm.icu.util;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * TimePeriod represents a time period. TimePeriod objects are immutable.
- * <p>Example usage:
- * <pre>
- * Period p = Period.forAmounts(
- * new TimeUnitAmount (TimeUnit.WEEK, 5),
- * new TimeUnitAmount (TimeUnit.DAY, 40),
- * new TimeUnitAmount (TimeUnit.HOUR, 2),
- * new TimeUnitAmount (TimeUnit.SECOND, 8));
- * </pre>
- * @draft ICU 52
- * @provisional This API might change or be removed in a future release.
- */
-public final class TimePeriod implements Iterable<TimeUnitAmount> {
-
- private final TimeUnitAmount[] fields;
- private final int length;
- private final int hash;
-
- /**
- * Constructor.
- * @param amounts the TimeUnitAmounts. Must be non-empty. Normalization of the
- * amounts and inclusion/exclusion of 0 amounts is up to caller. The Number
- * object in each TimeUnitAmount must not change. Otherwise the created
- * TimePeriod object may not work as expected.
- * @throws IllegalArgumentException if multiple TimeUnitAmount objects match
- * the same time unit or if any but the smallest TimeUnit has a fractional value
- * Or if amounts is empty.
- * @draft ICU 52
- * @provisional This API might change or be removed in a future release.
- */
- public TimePeriod(TimeUnitAmount ...amounts) {
- fields = new TimeUnitAmount[TimeUnit.TIME_UNIT_COUNT];
- int tempSize = 0;
- for (TimeUnitAmount tua : amounts) {
- int index = tua.getTimeUnit().getIndex();
- if (fields[index] != null) {
- throw new IllegalArgumentException(
- "Only one TimeUnitAmount per unit allowed.");
- }
- fields[index] = tua;
- tempSize++;
- }
- length = tempSize;
- if (length == 0) {
- throw new IllegalArgumentException(
- "There must be at least one TimeUnitAmount.");
- }
- boolean fractionalFieldEncountered = false;
- for (TimeUnitAmount tua : this) {
- if (fractionalFieldEncountered) {
- throw new IllegalArgumentException(
- "Only the smallest time unit can have a fractional amount.");
- }
- double value = tua.getNumber().doubleValue();
- if (value != Math.floor(value)) {
- fractionalFieldEncountered = true;
- }
- }
- hash = computeHash(fields);
- }
-
- /**
- * Gets the value for a specific time unit.
- * @param timeUnit the time unit.
- * @return the TimeUnitAmount or null if no value is present for given TimeUnit.
- * A non-existing value and a zero value are two different things.
- * @draft ICU 52
- * @provisional This API might change or be removed in a future release.
- */
- public TimeUnitAmount getAmount(TimeUnit timeUnit) {
- return fields[timeUnit.getIndex()];
- }
-
- /**
- * Returned iterator iterates over all TimeUnitAmount objects in this object.
- * Iterated TimeUnitAmount objects are ordered from largest TimeUnit to
- * smallest TimeUnit. Remove method on returned iterator throws an
- * UnsupportedOperationException.
- * @draft ICU 52
- * @provisional This API might change or be removed in a future release.
- */
- public Iterator<TimeUnitAmount> iterator() {
- return new TPIterator();
- }
-
- /**
- * Returns the number of TimeUnitAmount objects in this object.
- * @draft ICU 52
- */
- public int length() {
- return length;
- }
-
- /**
- * Two TimePeriod objects are equal if they contain equal TimeUnitAmount objects.
- * @draft ICU 52
- * @provisional This API might change or be removed in a future release.
- */
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof TimePeriod)) {
- return false;
- }
- TimePeriod rhs = (TimePeriod) o;
- if (this.hash != rhs.hash) {
- return false;
- }
- return Arrays.equals(fields, rhs.fields);
- }
-
- /**
- * Overrides hashCode().
- * @draft ICU 52
- * @provisional This API might change or be removed in a future release.
- */
- @Override
- public int hashCode() {
- return hash;
- }
-
- private static int computeHash(TimeUnitAmount[] fields) {
- int result = 0;
- for (TimeUnitAmount amount : fields) {
- result *= 31;
- if (amount != null) {
- result += amount.hashCode();
- }
- }
- return result;
- }
-
- private class TPIterator implements Iterator<TimeUnitAmount> {
-
- private int index = 0;
-
- public boolean hasNext() {
- while (index < fields.length && fields[index] == null) {
- index++;
- }
- return index < fields.length;
- }
-
- public TimeUnitAmount next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return fields[index++];
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-}
-
import com.ibm.icu.dev.test.TestFmwk;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.text.TimeUnitFormat;
-import com.ibm.icu.util.TimePeriod;
import com.ibm.icu.util.TimeUnit;
import com.ibm.icu.util.TimeUnitAmount;
import com.ibm.icu.util.ULocale;
*
*/
public class TimeUnitTest extends TestFmwk {
- private static final TimePeriod _19m = new TimePeriod(
- new TimeUnitAmount(19.0, TimeUnit.MINUTE));
- private static final TimePeriod _19m_28s = new TimePeriod(
- new TimeUnitAmount(19.0, TimeUnit.MINUTE),
- new TimeUnitAmount(28.0, TimeUnit.SECOND));
- private static final TimePeriod _1h_23_5s = new TimePeriod(
- new TimeUnitAmount(1.0, TimeUnit.HOUR),
- new TimeUnitAmount(23.5, TimeUnit.SECOND));
- private static final TimePeriod _1h_23_5m = new TimePeriod(
- new TimeUnitAmount(1.0, TimeUnit.HOUR),
- new TimeUnitAmount(23.5, TimeUnit.MINUTE));
- private static final TimePeriod _1h_0m_23s = new TimePeriod(
- new TimeUnitAmount(1.0, TimeUnit.HOUR),
- new TimeUnitAmount(0.0, TimeUnit.MINUTE),
- new TimeUnitAmount(23.0, TimeUnit.SECOND));
- private static final TimePeriod _5h_17m = new TimePeriod(
- new TimeUnitAmount(5.0, TimeUnit.HOUR),
- new TimeUnitAmount(17.0, TimeUnit.MINUTE));
- private static final TimePeriod _2y_5M_3w_4d = new TimePeriod(
- new TimeUnitAmount(2.0, TimeUnit.YEAR),
- new TimeUnitAmount(5.0, TimeUnit.MONTH),
- new TimeUnitAmount(3.0, TimeUnit.WEEK),
- new TimeUnitAmount(4.0, TimeUnit.DAY));
- private static final TimePeriod _0h_0m_17s = new TimePeriod(
- new TimeUnitAmount(0.0, TimeUnit.HOUR),
- new TimeUnitAmount(0.0, TimeUnit.MINUTE),
- new TimeUnitAmount(17.0, TimeUnit.SECOND));
- private static final TimePeriod _6h_56_92m = new TimePeriod(
- new TimeUnitAmount(6.0, TimeUnit.HOUR),
- new TimeUnitAmount(56.92, TimeUnit.MINUTE));
- private static final TimePeriod _1m_59_9996s = new TimePeriod(
- new TimeUnitAmount(1.0, TimeUnit.MINUTE),
- new TimeUnitAmount(59.9996, TimeUnit.SECOND));
-
public static void main(String[] args) throws Exception{
new TimeUnitTest().run(args);
}
TimeUnitFormat[] formats = new TimeUnitFormat[] {
new TimeUnitFormat(new ULocale(locales[locIndex]), TimeUnitFormat.FULL_NAME),
new TimeUnitFormat(new ULocale(locales[locIndex]), TimeUnitFormat.ABBREVIATED_NAME),
- new TimeUnitFormat(new ULocale(locales[locIndex]), TimeUnitFormat.NUMERIC)
};
for (int style = TimeUnitFormat.FULL_NAME;
- style <= TimeUnitFormat.NUMERIC;
+ style <= TimeUnitFormat.ABBREVIATED_NAME;
++style) {
final TimeUnit[] values = TimeUnit.values();
for (int j = 0; j < values.length; ++j) {
logln(tests[i] + " => " + formatted);
try {
// Style should not matter when parsing.
- for (int parseStyle = TimeUnitFormat.FULL_NAME; parseStyle <= TimeUnitFormat.NUMERIC; parseStyle++) {
+ for (int parseStyle = TimeUnitFormat.FULL_NAME; parseStyle <= TimeUnitFormat.ABBREVIATED_NAME; parseStyle++) {
TimeUnitAmount result = (TimeUnitAmount) formats[parseStyle].parseObject(formatted);
if (result == null || !source.equals(result)) {
errln("No round trip: " + source + " => " + formatted + " => " + result);
}
public void TestAPI() {
- try {
TimeUnitFormat format = new TimeUnitFormat();
format.setLocale(new ULocale("pt_BR"));
formatParsing(format);
format = new TimeUnitFormat(new Locale("ja"));
format.setNumberFormat(NumberFormat.getNumberInstance(new Locale("en")));
formatParsing(format);
- } catch (Exception e) {
- e.printStackTrace();
- }
}
/*
tuf1.setNumberFormat(NumberFormat.getInstance());
tuf1.parseObject("", new ParsePosition(0));
}
-
- public void TestFormatPeriodEn() {
- Object[][] fullData = {
- {_1m_59_9996s, "1 minute, 59.9996 seconds"},
- {_19m, "19 minutes"},
- {_1h_23_5s, "1 hour, 23.5 seconds"},
- {_1h_23_5m, "1 hour, 23.5 minutes"},
- {_1h_0m_23s, "1 hour, 0 minutes, 23 seconds"},
- {_2y_5M_3w_4d, "2 years, 5 months, 3 weeks, 4 days"}};
- Object[][] abbrevData = {
- {_1m_59_9996s, "1 min, 59.9996 secs"},
- {_19m, "19 mins"},
- {_1h_23_5s, "1 hr, 23.5 secs"},
- {_1h_23_5m, "1 hr, 23.5 mins"},
- {_1h_0m_23s, "1 hr, 0 mins, 23 secs"},
- {_2y_5M_3w_4d, "2 yrs, 5 mths, 3 wks, 4 days"}};
- Object[][] numericData = {
- {_1m_59_9996s, "1:59.9996"},
- {_19m, "19 mins"},
- {_1h_23_5s, "1:00:23.5"},
- {_1h_0m_23s, "1:00:23"},
- {_1h_23_5m, "1:23.5"},
- {_5h_17m, "5:17"},
- {_19m_28s, "19:28"},
- {_2y_5M_3w_4d, "2 yrs, 5 mths, 3 wks, 4 days"},
- {_0h_0m_17s, "0:00:17"},
- {_6h_56_92m, "6:56.92"}};
- TimeUnitFormat tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.FULL_NAME);
- NumberFormat nf = NumberFormat.getNumberInstance(ULocale.ENGLISH);
- nf.setMaximumFractionDigits(4);
- tuf.setNumberFormat(nf);
- verifyFormatPeriod("en FULL", tuf, fullData);
- tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.ABBREVIATED_NAME);
- tuf.setNumberFormat(nf);
- verifyFormatPeriod("en ABBREV", tuf, abbrevData);
- tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.NUMERIC);
- tuf.setNumberFormat(nf);
- verifyFormatPeriod("en NUMERIC", tuf, numericData);
- }
-
- public void TestTimePeriodLength() {
- assertEquals("length", 2, new TimePeriod(
- new TimeUnitAmount(3.0, TimeUnit.HOUR),
- new TimeUnitAmount(5.0, TimeUnit.MINUTE)).length());
- }
-
- public void TestTimePeriodForAmounts() {
- try {
- new TimePeriod(
- new TimeUnitAmount(3.0, TimeUnit.HOUR),
- new TimeUnitAmount(5.0, TimeUnit.HOUR));
- errln("Expected IllegalArgumentException on duplicate TimeUnits.");
- } catch (IllegalArgumentException e) {
- // expected
- }
- try {
- new TimePeriod();
- errln("Expected IllegalArgumentException on missing TimeUnitAmounts.");
- } catch (IllegalArgumentException e) {
- // expected
- }
- try {
- new TimePeriod(
- new TimeUnitAmount(3.5, TimeUnit.HOUR),
- new TimeUnitAmount(5.0, TimeUnit.MINUTE));
- errln("Expected IllegalArgumentException. Only smallest time unit can have a fractional amount.");
- } catch (IllegalArgumentException e) {
- // expected
- }
- }
-
- public void TestTimePeriodEqualsHashCode() {
- TimePeriod our_19m_28s = new TimePeriod(
- new TimeUnitAmount(28.0, TimeUnit.SECOND),
- new TimeUnitAmount(19.0, TimeUnit.MINUTE));
- assertEquals("TimePeriod equals", _19m_28s, our_19m_28s);
- assertEquals("Hash code", _19m_28s.hashCode(), our_19m_28s.hashCode());
- TimePeriod our_19m_29s = new TimePeriod(
- new TimeUnitAmount(29.0, TimeUnit.SECOND),
- new TimeUnitAmount(19.0, TimeUnit.MINUTE));
- assertNotEquals("TimePeriod not equals", _19m_28s, our_19m_29s);
-
- // It may be possible for non-equal objects to have equal hashCodes, but we
- // are betting on the probability of that to be miniscule.
- assertNotEquals("TimePeriod hash not equals", _19m_28s.hashCode(), our_19m_29s.hashCode());
- }
-
- private void verifyFormatPeriod(String desc, TimeUnitFormat tuf, Object[][] testData) {
- StringBuilder builder = new StringBuilder();
- boolean failure = false;
- for (Object[] testCase : testData) {
- String actual = tuf.format(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(builder.toString());
- }
- }
}