From 3fa5329e97361f595393dcddfe1c01e2fa6f4bde Mon Sep 17 00:00:00 2001 From: Travis Keep Date: Wed, 4 Dec 2013 21:19:34 +0000 Subject: [PATCH] ICU-8464 Update Java RelativeDateTimeFormatter with latest API proposal. X-SVN-Rev: 34709 --- .../icu/text/RelativeDateTimeFormatter.java | 60 +++++++++++++------ .../format/RelativeDateTimeFormatterTest.java | 10 +++- 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/RelativeDateTimeFormatter.java b/icu4j/main/classes/core/src/com/ibm/icu/text/RelativeDateTimeFormatter.java index 0986e4c2e4d..c0e78f6f5a4 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/RelativeDateTimeFormatter.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/RelativeDateTimeFormatter.java @@ -33,7 +33,7 @@ import com.ibm.icu.util.UResourceBundle; * involving one single unit. This API does not support relative dates * involving compound units. * e.g "in 5 days and 4 hours" nor does it support parsing. - * This class is NOT thread-safe. + * This class is both immutable and thread-safe. *

* Here are some examples of use: *

@@ -277,6 +277,8 @@ public final class RelativeDateTimeFormatter { /** * Returns a RelativeDateTimeFormatter for a particular locale. + * + * @param locale the locale. * @draft ICU 53 * @provisional */ @@ -290,6 +292,25 @@ public final class RelativeDateTimeFormatter { NumberFormat.getInstance(locale)); } + /** + * Returns a RelativeDateTimeFormatter for a particular locale that uses a particular + * NumberFormat object. + * + * @param locale the locale + * @param nf the number format object. It is defensively copied to ensure thread-safety + * and immutability of this class. + * @draft ICU 53 + * @provisional + */ + public static RelativeDateTimeFormatter getInstance(ULocale locale, NumberFormat nf) { + RelativeDateTimeFormatterData data = cache.get(locale); + return new RelativeDateTimeFormatter( + data.qualitativeUnitMap, + data.quantitativeUnitMap, + new MessageFormat(data.dateTimePattern), + PluralRules.forLocale(locale), + (NumberFormat) nf.clone()); + } /** * Formats a relative date with a quantity such as "in 5 days" or @@ -309,7 +330,13 @@ public final class RelativeDateTimeFormatter { if (direction != Direction.LAST && direction != Direction.NEXT) { throw new IllegalArgumentException("direction must be NEXT or LAST"); } - return getQuantity(unit, direction == Direction.NEXT).format(quantity, numberFormat, pluralRules); + // This class is thread-safe, yet numberFormat is not. To ensure thread-safety of this + // class we must guarantee that only one thread at a time uses our numberFormat. + synchronized (numberFormat) { + return getQuantity( + unit, direction == Direction.NEXT).format( + quantity, numberFormat, pluralRules); + } } /** @@ -330,21 +357,6 @@ public final class RelativeDateTimeFormatter { } return this.qualitativeUnitMap.get(unit).get(direction); } - - /** - * Specify which NumberFormat object this object should use for - * formatting numbers. By default this object uses the default - * NumberFormat object for this object's locale. - * @param nf the NumberFormat object to use. This method makes - * its own defensive copy of nf so that subsequent - * changes to nf will not affect the operation of this object. - * @see #format(double, Direction, RelativeUnit) - * @draft ICU 53 - * @provisional - */ - public void setNumberFormat(NumberFormat nf) { - this.numberFormat = (NumberFormat) nf.clone(); - } /** * Combines a relative date string and a time string in this object's @@ -362,6 +374,20 @@ public final class RelativeDateTimeFormatter { new Object[]{timeString, relativeDateString}, new StringBuffer(), null).toString(); } + /** + * Returns a copy of the NumberFormat this object is using. + * + * @draft ICU 53 + * @provisional + */ + public NumberFormat getNumberFormat() { + // This class is thread-safe, yet numberFormat is not. To ensure thread-safety of this + // class we must guarantee that only one thread at a time uses our numberFormat. + synchronized (numberFormat) { + return (NumberFormat) numberFormat.clone(); + } + } + private static void addQualitativeUnit( EnumMap> qualitativeUnits, AbsoluteUnit unit, diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RelativeDateTimeFormatterTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RelativeDateTimeFormatterTest.java index 043399b752c..2da388cb80c 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RelativeDateTimeFormatterTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/RelativeDateTimeFormatterTest.java @@ -215,18 +215,22 @@ public class RelativeDateTimeFormatterTest extends TestFmwk { } } - public void TestSetNumberFormat() { + public void TestCustomNumberFormat() { ULocale loc = new ULocale("en_US"); NumberFormat nf = NumberFormat.getInstance(loc); nf.setMinimumFractionDigits(1); nf.setMaximumFractionDigits(1); - RelativeDateTimeFormatter fmt = RelativeDateTimeFormatter.getInstance(loc); - fmt.setNumberFormat(nf); + RelativeDateTimeFormatter fmt = RelativeDateTimeFormatter.getInstance(loc, nf); // Change nf after the fact to prove that we made a defensive copy nf.setMinimumFractionDigits(3); nf.setMaximumFractionDigits(3); + // Change getNumberFormat to prove we made defensive copy going out. + fmt.getNumberFormat().setMinimumFractionDigits(5); + assertEquals( + "TestCustomNumberformat", 1, fmt.getNumberFormat().getMinimumFractionDigits()); + Object[][] data = { {0.0, Direction.NEXT, RelativeUnit.SECONDS, "in 0.0 seconds"}, {0.5, Direction.NEXT, RelativeUnit.SECONDS, "in 0.5 seconds"}, -- 2.40.0