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 7dd08b91fc6..6f47fe0a7c1 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 @@ -50,46 +50,46 @@ import com.ibm.icu.util.UResourceBundle; * fmt.format(1, Direction.NEXT, RelativeUnit.DAYS); // "in 1 day" * fmt.format(3, Direction.NEXT, RelativeUnit.DAYS); // "in 3 days" * fmt.format(3.2, Direction.LAST, RelativeUnit.YEARS); // "3.2 years ago" - * + * * fmt.format(Direction.LAST, AbsoluteUnit.SUNDAY); // "last Sunday" * fmt.format(Direction.THIS, AbsoluteUnit.SUNDAY); // "this Sunday" * fmt.format(Direction.NEXT, AbsoluteUnit.SUNDAY); // "next Sunday" * fmt.format(Direction.PLAIN, AbsoluteUnit.SUNDAY); // "Sunday" - * + * * fmt.format(Direction.LAST, AbsoluteUnit.DAY); // "yesterday" * fmt.format(Direction.THIS, AbsoluteUnit.DAY); // "today" * fmt.format(Direction.NEXT, AbsoluteUnit.DAY); // "tomorrow" - * + * * fmt.format(Direction.PLAIN, AbsoluteUnit.NOW); // "now" * * *
* In the future, we may add more forms, such as abbreviated/short forms * (3 secs ago), and relative day periods ("yesterday afternoon"), etc. - * + * * @stable ICU 53 */ public final class RelativeDateTimeFormatter { - + /** * The formatting style * @stable ICU 54 * */ public static enum Style { - + /** * Everything spelled out. * @stable ICU 54 */ LONG, - + /** * Abbreviations used when possible. * @stable ICU 54 */ SHORT, - + /** * Use single letters when possible. * @stable ICU 54 @@ -105,43 +105,43 @@ public final class RelativeDateTimeFormatter { * @stable ICU 53 */ public static enum RelativeUnit { - + /** * Seconds * @stable ICU 53 */ SECONDS, - + /** * Minutes * @stable ICU 53 */ MINUTES, - + /** * Hours * @stable ICU 53 */ HOURS, - + /** * Days * @stable ICU 53 */ DAYS, - + /** * Weeks * @stable ICU 53 */ WEEKS, - + /** * Months * @stable ICU 53 */ MONTHS, - + /** * Years * @stable ICU 53 @@ -156,79 +156,79 @@ public final class RelativeDateTimeFormatter { @Deprecated QUARTERS, } - + /** * Represents an absolute unit. * @stable ICU 53 */ public static enum AbsoluteUnit { - + /** * Sunday * @stable ICU 53 */ SUNDAY, - + /** * Monday * @stable ICU 53 */ MONDAY, - + /** * Tuesday * @stable ICU 53 */ TUESDAY, - + /** * Wednesday * @stable ICU 53 */ WEDNESDAY, - + /** * Thursday * @stable ICU 53 */ THURSDAY, - + /** * Friday * @stable ICU 53 */ FRIDAY, - + /** * Saturday * @stable ICU 53 */ SATURDAY, - + /** * Day * @stable ICU 53 */ DAY, - + /** * Week * @stable ICU 53 */ WEEK, - + /** * Month * @stable ICU 53 */ MONTH, - + /** * Year * @stable ICU 53 */ YEAR, - + /** * Now * @stable ICU 53 @@ -259,7 +259,7 @@ public final class RelativeDateTimeFormatter { /** * Last * @stable ICU 53 - */ + */ LAST, /** @@ -294,107 +294,107 @@ public final class RelativeDateTimeFormatter { * @provisional This API might change or be removed in a future release. */ public static enum RelativeDateTimeUnit { - /** + /** * Specifies that relative unit is year, e.g. "last year", - * "in 5 years". + * "in 5 years". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ YEAR, - /** + /** * Specifies that relative unit is quarter, e.g. "last quarter", - * "in 5 quarters". + * "in 5 quarters". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ QUARTER, - /** + /** * Specifies that relative unit is month, e.g. "last month", - * "in 5 months". + * "in 5 months". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ MONTH, - /** + /** * Specifies that relative unit is week, e.g. "last week", - * "in 5 weeks". + * "in 5 weeks". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ WEEK, - /** + /** * Specifies that relative unit is day, e.g. "yesterday", - * "in 5 days". + * "in 5 days". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ DAY, - /** + /** * Specifies that relative unit is hour, e.g. "1 hour ago", - * "in 5 hours". + * "in 5 hours". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ HOUR, - /** + /** * Specifies that relative unit is minute, e.g. "1 minute ago", - * "in 5 minutes". + * "in 5 minutes". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ MINUTE, - /** + /** * Specifies that relative unit is second, e.g. "1 second ago", - * "in 5 seconds". + * "in 5 seconds". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ SECOND, - /** + /** * Specifies that relative unit is Sunday, e.g. "last Sunday", - * "this Sunday", "next Sunday", "in 5 Sundays". + * "this Sunday", "next Sunday", "in 5 Sundays". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ SUNDAY, - /** + /** * Specifies that relative unit is Monday, e.g. "last Monday", - * "this Monday", "next Monday", "in 5 Mondays". + * "this Monday", "next Monday", "in 5 Mondays". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ MONDAY, - /** + /** * Specifies that relative unit is Tuesday, e.g. "last Tuesday", - * "this Tuesday", "next Tuesday", "in 5 Tuesdays". + * "this Tuesday", "next Tuesday", "in 5 Tuesdays". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ TUESDAY, - /** + /** * Specifies that relative unit is Wednesday, e.g. "last Wednesday", - * "this Wednesday", "next Wednesday", "in 5 Wednesdays". + * "this Wednesday", "next Wednesday", "in 5 Wednesdays". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ WEDNESDAY, - /** + /** * Specifies that relative unit is Thursday, e.g. "last Thursday", - * "this Thursday", "next Thursday", "in 5 Thursdays". + * "this Thursday", "next Thursday", "in 5 Thursdays". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ THURSDAY, - /** + /** * Specifies that relative unit is Friday, e.g. "last Friday", - * "this Friday", "next Friday", "in 5 Fridays". + * "this Friday", "next Friday", "in 5 Fridays". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ FRIDAY, - /** + /** * Specifies that relative unit is Saturday, e.g. "last Saturday", - * "this Saturday", "next Saturday", "in 5 Saturdays". + * "this Saturday", "next Saturday", "in 5 Saturdays". * @draft ICU 57 * @provisional This API might change or be removed in a future release. */ @@ -411,7 +411,7 @@ public final class RelativeDateTimeFormatter { /** * Returns a RelativeDateTimeFormatter for a particular locale. - * + * * @param locale the locale. * @return An instance of RelativeDateTimeFormatter. * @stable ICU 53 @@ -422,7 +422,7 @@ public final class RelativeDateTimeFormatter { /** * Returns a RelativeDateTimeFormatter for a particular {@link java.util.Locale}. - * + * * @param locale the {@link java.util.Locale}. * @return An instance of RelativeDateTimeFormatter. * @stable ICU 54 @@ -434,21 +434,21 @@ public final class RelativeDateTimeFormatter { /** * 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. + * and immutability of this class. * @return An instance of RelativeDateTimeFormatter. * @stable ICU 53 */ public static RelativeDateTimeFormatter getInstance(ULocale locale, NumberFormat nf) { return getInstance(locale, nf, Style.LONG, DisplayContext.CAPITALIZATION_NONE); } - + /** * Returns a RelativeDateTimeFormatter for a particular locale that uses a particular * NumberFormat object, style, and capitalization context - * + * * @param locale the locale * @param nf the number format object. It is defensively copied to ensure thread-safety * and immutability of this class. May be null. @@ -484,10 +484,10 @@ public final class RelativeDateTimeFormatter { /** * Returns a RelativeDateTimeFormatter for a particular {@link java.util.Locale} that uses a * particular NumberFormat object. - * + * * @param locale the {@link java.util.Locale} * @param nf the number format object. It is defensively copied to ensure thread-safety - * and immutability of this class. + * and immutability of this class. * @return An instance of RelativeDateTimeFormatter. * @stable ICU 54 */ @@ -534,7 +534,7 @@ public final class RelativeDateTimeFormatter { * Format a combination of RelativeDateTimeUnit and numeric offset * using a numeric style, e.g. "1 week ago", "in 1 week", * "5 weeks ago", "in 5 weeks". - * + * * @param offset The signed offset for the specified unit. This * will be formatted according to this object's * NumberFormat object. @@ -564,7 +564,7 @@ public final class RelativeDateTimeFormatter { case MINUTE: relunit = RelativeUnit.MINUTES; break; case SECOND: break; // set above default: // SUNDAY..SATURDAY - return ""; + throw new UnsupportedOperationException("formatNumeric does not currently support RelativeUnit.SUNDAY..SATURDAY"); } Direction direction = Direction.NEXT; if (offset < 0) { @@ -574,7 +574,7 @@ public final class RelativeDateTimeFormatter { String result = format(offset, direction, relunit); return (result != null)? result: ""; } - + private int[] styleToDateFormatSymbolsWidth = { DateFormatSymbols.WIDE, DateFormatSymbols.SHORT, DateFormatSymbols.NARROW }; @@ -617,7 +617,7 @@ public final class RelativeDateTimeFormatter { * "next week", "yesterday", "tomorrow". Falls back to numeric * style if no appropriate text term is available for the specified * offset in the object’s locale. - * + * * @param offset The signed offset for the specified field. * @param unit The unit to use when formatting the relative * date, e.g. RelativeDateTimeUnit.WEEK, @@ -634,18 +634,20 @@ public final class RelativeDateTimeFormatter { // new CLDR data is available, update the data storage accordingly, rewrite this // to use it directly, and rewrite the old format method to call this new one; // that is covered by http://bugs.icu-project.org/trac/ticket/12171. - boolean useNumeric = false; + boolean useNumeric = true; Direction direction = Direction.THIS; - int intoffset = (offset < 0)? (int)(offset-0.5) : (int)(offset+0.5); - switch (intoffset) { - case -2: direction = Direction.LAST_2; break; - case -1: direction = Direction.LAST; break; - case 0: break; // direction = Direction.THIS was set above - case 1: direction = Direction.NEXT; break; - case 2: direction = Direction.NEXT_2; break; - default: - useNumeric = true; - break; + if (offset > -2.1 && offset < 2.1) { + // Allow a 1% epsilon, so offsets in -1.01..-0.99 map to LAST + double offsetx100 = offset * 100.0; + int intoffset = (offsetx100 < 0)? (int)(offsetx100-0.5) : (int)(offsetx100+0.5); + switch (intoffset) { + case -200/*-2*/: direction = Direction.LAST_2; useNumeric = false; break; + case -100/*-1*/: direction = Direction.LAST; useNumeric = false; break; + case 0/* 0*/: useNumeric = false; break; // direction = Direction.THIS was set above + case 100/* 1*/: direction = Direction.NEXT; useNumeric = false; break; + case 200/* 2*/: direction = Direction.NEXT_2; useNumeric = false; break; + default: break; + } } AbsoluteUnit absunit = AbsoluteUnit.NOW; switch (unit) { @@ -661,7 +663,6 @@ public final class RelativeDateTimeFormatter { case THURSDAY: absunit = AbsoluteUnit.THURSDAY; break; case FRIDAY: absunit = AbsoluteUnit.FRIDAY; break; case SATURDAY: absunit = AbsoluteUnit.SATURDAY; break; - case MINUTE: case SECOND: if (direction == Direction.THIS) { // absunit = AbsoluteUnit.NOW was set above @@ -751,7 +752,7 @@ public final class RelativeDateTimeFormatter { /** * Return style - * @return The formatting style. + * @return The formatting style. * @stable ICU 54 */ public Style getFormatStyle() { @@ -759,7 +760,7 @@ public final class RelativeDateTimeFormatter { } private String adjustForContext(String originalFormattedString) { - if (breakIterator == null || originalFormattedString.length() == 0 + if (breakIterator == null || originalFormattedString.length() == 0 || !UCharacter.isLowerCase(UCharacter.codePointAt(originalFormattedString, 0))) { return originalFormattedString; } @@ -774,7 +775,7 @@ public final class RelativeDateTimeFormatter { private RelativeDateTimeFormatter( EnumMap