diff options
author | Travis Keep <rocketman@google.com> | 2015-04-07 09:55:56 -0700 |
---|---|---|
committer | Neil Fuller <nfuller@google.com> | 2015-04-14 13:21:37 +0000 |
commit | f7d3d845d1db889060262cfb7a9f73a2c4fdb7f3 (patch) | |
tree | 738f020604ef6f7004367cc0e860eebb6ca9a943 | |
parent | 3ac9db28f6db21aaecb6970f36547073b34f6983 (diff) | |
download | libcore-f7d3d845d1db889060262cfb7a9f73a2c4fdb7f3.zip libcore-f7d3d845d1db889060262cfb7a9f73a2c4fdb7f3.tar.gz libcore-f7d3d845d1db889060262cfb7a9f73a2c4fdb7f3.tar.bz2 |
Switch DateIntervalFormat/RelativeDateTimeFormatter to ICU4J
Information below from the existing benchmarks on a hammerhead. All
times given in microseconds. Note that the new version is slower,
but this is a small difference in absolute terms and means less
maintenance for libcore.
The ICU team is rewriting some of the underlying code in ICU4J
for a future ICU release which may alter performance.
ICU4C + JNI
DateIntervalFormat_formatDateRange_DATE 67.8
DateIntervalFormat_formatDateRange_DATE_TIME 76.0
DateIntervalFormat_formatDateRange_TIME 54.8
ICU4J
DateIntervalFormat_formatDateRange_DATE 179
DateIntervalFormat_formatDateRange_DATE_TIME 181
DateIntervalFormat_formatDateRange_TIME 167
ICU4C + JNI
RelativeDateTimeFormatter_getRelativeDateTimeString 151.6
RelativeDateTimeFormatter_getRelativeDateTimeString_ABBREV 169.0
RelativeDateTimeFormatter_getRelativeTimeSpanString 27.8
RelativeDateTimeFormatter_getRelativeTimeSpanString_ABBREV 27.7
ICU4J
RelativeDateTimeFormatter_getRelativeDateTimeString 366.5
RelativeDateTimeFormatter_getRelativeDateTimeString_ABBREV 377.6
RelativeDateTimeFormatter_getRelativeTimeSpanString 23.2
RelativeDateTimeFormatter_getRelativeTimeSpanString_ABBREV 22.9
Bug: 20127691
Change-Id: I1ebc08fd9c974743026ae1e6c848fb4de8aa0e48
-rw-r--r-- | luni/src/main/java/libcore/icu/DateIntervalFormat.java | 50 | ||||
-rw-r--r-- | luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java | 146 | ||||
-rw-r--r-- | luni/src/main/native/Register.cpp | 2 | ||||
-rw-r--r-- | luni/src/main/native/libcore_icu_DateIntervalFormat.cpp | 78 | ||||
-rw-r--r-- | luni/src/main/native/libcore_icu_RelativeDateTimeFormatter.cpp | 109 | ||||
-rw-r--r-- | luni/src/main/native/sub.mk | 2 | ||||
-rw-r--r-- | luni/src/test/java/libcore/icu/DateIntervalFormatTest.java | 1 |
7 files changed, 86 insertions, 302 deletions
diff --git a/luni/src/main/java/libcore/icu/DateIntervalFormat.java b/luni/src/main/java/libcore/icu/DateIntervalFormat.java index fbef89a..96d2ca7 100644 --- a/luni/src/main/java/libcore/icu/DateIntervalFormat.java +++ b/luni/src/main/java/libcore/icu/DateIntervalFormat.java @@ -16,13 +16,14 @@ package libcore.icu; +import java.text.FieldPosition; import java.util.Calendar; import java.util.Locale; import java.util.TimeZone; import libcore.util.BasicLruCache; /** - * Exposes icu4c's DateIntervalFormat. + * Exposes icu4j's DateIntervalFormat. */ public final class DateIntervalFormat { @@ -49,15 +50,11 @@ public final class DateIntervalFormat { private static final FormatterCache CACHED_FORMATTERS = new FormatterCache(); - static class FormatterCache extends BasicLruCache<String, Long> { + static class FormatterCache extends BasicLruCache<String, com.ibm.icu.text.DateIntervalFormat> { FormatterCache() { super(8); } - - protected void entryEvicted(String key, Long value) { - destroyDateIntervalFormat(value); - } - }; + } private DateIntervalFormat() { } @@ -73,7 +70,8 @@ public final class DateIntervalFormat { // This is our slightly more sensible internal API. (A truly sane replacement would take a // skeleton instead of int flags.) - public static String formatDateRange(Locale locale, TimeZone tz, long startMs, long endMs, int flags) { + public static String formatDateRange(Locale locale, TimeZone tz, long startMs, long endMs, + int flags) { Calendar startCalendar = Calendar.getInstance(tz); startCalendar.setTimeInMillis(startMs); @@ -89,7 +87,7 @@ public final class DateIntervalFormat { // If we're not showing the time or the start and end times are on the same day, and the // end time is midnight, fudge the end date so we don't count the day that's about to start. - // This is not the behavior of icu4c's DateIntervalFormat, but it's the historical behavior + // This is not the behavior of icu4j's DateIntervalFormat, but it's the historical behavior // of Android's DateUtils.formatDateRange. if (startMs != endMs && endsAtMidnight && ((flags & FORMAT_SHOW_TIME) == 0 || dayDistance(startCalendar, endCalendar) <= 1)) { @@ -99,19 +97,24 @@ public final class DateIntervalFormat { String skeleton = toSkeleton(startCalendar, endCalendar, flags); synchronized (CACHED_FORMATTERS) { - return formatDateInterval(getFormatter(skeleton, locale.toString(), tz.getID()), startMs, endMs); + com.ibm.icu.text.DateIntervalFormat formatter = getFormatter(skeleton, locale, tz); + com.ibm.icu.util.Calendar scal = icuCalendar(startCalendar); + com.ibm.icu.util.Calendar ecal = icuCalendar(endCalendar); + return formatter.format(scal, ecal, new StringBuffer(), new FieldPosition(0)).toString(); } } - private static long getFormatter(String skeleton, String localeName, String tzName) { - String key = skeleton + "\t" + localeName + "\t" + tzName; - Long formatter = CACHED_FORMATTERS.get(key); + private static com.ibm.icu.text.DateIntervalFormat getFormatter(String skeleton, Locale locale, + TimeZone tz) { + String key = skeleton + "\t" + locale + "\t" + tz; + com.ibm.icu.text.DateIntervalFormat formatter = CACHED_FORMATTERS.get(key); if (formatter != null) { return formatter; } - long address = createDateIntervalFormat(skeleton, localeName, tzName); - CACHED_FORMATTERS.put(key, address); - return address; + formatter = com.ibm.icu.text.DateIntervalFormat.getInstance(skeleton, locale); + formatter.setTimeZone(icuTimeZone(tz)); + CACHED_FORMATTERS.put(key, formatter); + return formatter; } private static String toSkeleton(Calendar startCalendar, Calendar endCalendar, int flags) { @@ -243,7 +246,16 @@ public final class DateIntervalFormat { return (int) (utcMs / DAY_IN_MS) + EPOCH_JULIAN_DAY; } - private static native long createDateIntervalFormat(String skeleton, String localeName, String tzName); - private static native void destroyDateIntervalFormat(long address); - private static native String formatDateInterval(long address, long fromDate, long toDate); + private static com.ibm.icu.util.TimeZone icuTimeZone(TimeZone tz) { + final int timezoneType = com.ibm.icu.util.TimeZone.TIMEZONE_JDK; + return com.ibm.icu.util.TimeZone.getTimeZone(tz.getID(), timezoneType); + } + + private static com.ibm.icu.util.Calendar icuCalendar(Calendar cal) { + com.ibm.icu.util.TimeZone timeZone = icuTimeZone(cal.getTimeZone()); + com.ibm.icu.util.Calendar result = com.ibm.icu.util.Calendar.getInstance(timeZone); + result.setTime(cal.getTime()); + return result; + } + } diff --git a/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java b/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java index e861571..750df00 100644 --- a/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java +++ b/luni/src/main/java/libcore/icu/RelativeDateTimeFormatter.java @@ -22,9 +22,11 @@ import java.util.Locale; import java.util.TimeZone; import libcore.util.BasicLruCache; import libcore.icu.DateIntervalFormat; +import com.ibm.icu.text.DisplayContext; +import com.ibm.icu.util.ULocale; /** - * Exposes icu4c's RelativeDateTimeFormatter. + * Exposes icu4j's RelativeDateTimeFormatter. */ public final class RelativeDateTimeFormatter { @@ -48,48 +50,13 @@ public final class RelativeDateTimeFormatter { // constant comes from public API in DateUtils, it cannot be fixed here. public static final long YEAR_IN_MILLIS = WEEK_IN_MILLIS * 52; - // Values from icu4c UDateRelativeUnit enum in unicode/reldatefmt.h. - // The following U* constants must agree with the ones in icu4c. - private static final int UDAT_RELATIVE_SECONDS = 0; - private static final int UDAT_RELATIVE_MINUTES = 1; - private static final int UDAT_RELATIVE_HOURS = 2; - private static final int UDAT_RELATIVE_DAYS = 3; - private static final int UDAT_RELATIVE_WEEKS = 4; - private static final int UDAT_RELATIVE_MONTHS = 5; - private static final int UDAT_RELATIVE_YEARS = 6; - - // Values from icu4c UDateAbsoluteUnit enum in unicode/reldatefmt.h. - private static final int UDAT_ABSOLUTE_DAY = 7; - - // Values from icu4c UDisplayContext enum in unicode/udisplaycontext.h. - private static final int UDISPCTX_CAPITALIZATION_NONE = 1 << 8; - private static final int UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE = (1 << 8) + 2; - - // Values from icu4c UDateDirection enum in unicode/reldatefmt.h. - private static final int UDAT_DIRECTION_LAST_2 = 0; - private static final int UDAT_DIRECTION_LAST = 1; - private static final int UDAT_DIRECTION_THIS = 2; - private static final int UDAT_DIRECTION_NEXT = 3; - private static final int UDAT_DIRECTION_NEXT_2 = 4; - private static final int UDAT_DIRECTION_PLAIN = 5; - - // Values from icu4c UDateRelativeDateTimeFormatterStyle enum in - // unicode/reldatefmt.h. - private static final int UDAT_STYLE_LONG = 0; - private static final int UDAT_STYLE_SHORT = 1; - private static final int UDAT_STYLE_NARROW = 2; - private static final FormatterCache CACHED_FORMATTERS = new FormatterCache(); - private static final int EPOCH_JULIAN_DAY = 2440588; - static class FormatterCache extends BasicLruCache<String, Long> { + static class FormatterCache + extends BasicLruCache<String, com.ibm.icu.text.RelativeDateTimeFormatter> { FormatterCache() { super(8); } - - protected void entryEvicted(String key, Long value) { - destroyRelativeDateTimeFormatter(value); - } }; private RelativeDateTimeFormatter() { @@ -107,7 +74,7 @@ public final class RelativeDateTimeFormatter { * Callers may also specify the desired minimum resolution to show in the * result. For example, '45 minutes ago' will become '0 hours ago' when * minResolution is HOUR_IN_MILLIS. Once getting the quantity and unit to - * display, it calls icu4c's RelativeDateTimeFormatter to format the actual + * display, it calls icu4j's RelativeDateTimeFormatter to format the actual * string according to the given locale. * * Note that when minResolution is set to DAY_IN_MILLIS, it returns the @@ -133,12 +100,11 @@ public final class RelativeDateTimeFormatter { long duration = Math.abs(now - time); boolean past = (now >= time); - // Use UDAT_STYLE_SHORT or UDAT_STYLE_LONG. - int style; + com.ibm.icu.text.RelativeDateTimeFormatter.Style style; if ((flags & (FORMAT_ABBREV_RELATIVE | FORMAT_ABBREV_ALL)) != 0) { - style = UDAT_STYLE_SHORT; + style = com.ibm.icu.text.RelativeDateTimeFormatter.Style.SHORT; } else { - style = UDAT_STYLE_LONG; + style = com.ibm.icu.text.RelativeDateTimeFormatter.Style.LONG; } // We are currently using the _NONE and _FOR_BEGINNING_OF_SENTENCE for the @@ -146,14 +112,13 @@ public final class RelativeDateTimeFormatter { // to capitalize the first letter of strings that don't contain // quantities, such as "Yesterday", "Today" and etc. This is for backward // compatibility (see b/14493853). - int capitalizationContext = UDISPCTX_CAPITALIZATION_NONE; + DisplayContext capitalizationContext = DisplayContext.CAPITALIZATION_NONE; - // Use UDAT_DIRECTION_LAST or UDAT_DIRECTION_NEXT. - int direction; + com.ibm.icu.text.RelativeDateTimeFormatter.Direction direction; if (past) { - direction = UDAT_DIRECTION_LAST; + direction = com.ibm.icu.text.RelativeDateTimeFormatter.Direction.LAST; } else { - direction = UDAT_DIRECTION_NEXT; + direction = com.ibm.icu.text.RelativeDateTimeFormatter.Direction.NEXT; } // 'relative' defaults to true as we are generating relative time span @@ -161,65 +126,68 @@ public final class RelativeDateTimeFormatter { // a quantity, such as 'Yesterday', etc. boolean relative = true; int count; - int unit; + com.ibm.icu.text.RelativeDateTimeFormatter.RelativeUnit unit; + com.ibm.icu.text.RelativeDateTimeFormatter.AbsoluteUnit aunit = null; if (duration < MINUTE_IN_MILLIS && minResolution < MINUTE_IN_MILLIS) { count = (int)(duration / SECOND_IN_MILLIS); - unit = UDAT_RELATIVE_SECONDS; + unit = com.ibm.icu.text.RelativeDateTimeFormatter.RelativeUnit.SECONDS; } else if (duration < HOUR_IN_MILLIS && minResolution < HOUR_IN_MILLIS) { count = (int)(duration / MINUTE_IN_MILLIS); - unit = UDAT_RELATIVE_MINUTES; + unit = com.ibm.icu.text.RelativeDateTimeFormatter.RelativeUnit.MINUTES; } else if (duration < DAY_IN_MILLIS && minResolution < DAY_IN_MILLIS) { // Even if 'time' actually happened yesterday, we don't format it as // "Yesterday" in this case. Unless the duration is longer than a day, // or minResolution is specified as DAY_IN_MILLIS by user. count = (int)(duration / HOUR_IN_MILLIS); - unit = UDAT_RELATIVE_HOURS; + unit = com.ibm.icu.text.RelativeDateTimeFormatter.RelativeUnit.HOURS; } else if (duration < WEEK_IN_MILLIS && minResolution < WEEK_IN_MILLIS) { count = Math.abs(DateIntervalFormat.dayDistance(tz, time, now)); - unit = UDAT_RELATIVE_DAYS; + unit = com.ibm.icu.text.RelativeDateTimeFormatter.RelativeUnit.DAYS; if (count == 2) { // Some locales have special terms for "2 days ago". Return them if // available. Note that we cannot set up direction and unit here and // make it fall through to use the call near the end of the function, // because for locales that don't have special terms for "2 days ago", - // icu4c returns an empty string instead of falling back to strings + // icu4j returns an empty string instead of falling back to strings // like "2 days ago". - capitalizationContext = UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE; + capitalizationContext = DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE; String str; if (past) { synchronized (CACHED_FORMATTERS) { - str = formatWithAbsoluteUnit(getFormatter(locale.toString(), style, - capitalizationContext), - UDAT_DIRECTION_LAST_2, UDAT_ABSOLUTE_DAY); + str = getFormatter(locale.toString(), style, capitalizationContext) + .format( + com.ibm.icu.text.RelativeDateTimeFormatter.Direction.LAST_2, + com.ibm.icu.text.RelativeDateTimeFormatter.AbsoluteUnit.DAY); } } else { synchronized (CACHED_FORMATTERS) { - str = formatWithAbsoluteUnit(getFormatter(locale.toString(), style, - capitalizationContext), - UDAT_DIRECTION_NEXT_2, UDAT_ABSOLUTE_DAY); + str = getFormatter(locale.toString(), style, capitalizationContext) + .format( + com.ibm.icu.text.RelativeDateTimeFormatter.Direction.NEXT_2, + com.ibm.icu.text.RelativeDateTimeFormatter.AbsoluteUnit.DAY); } } - if (!str.isEmpty()) { + if (str != null && !str.isEmpty()) { return str; } // Fall back to show something like "2 days ago". Reset the // capitalization setting. - capitalizationContext = UDISPCTX_CAPITALIZATION_NONE; + capitalizationContext = DisplayContext.CAPITALIZATION_NONE; } else if (count == 1) { // Show "Yesterday / Tomorrow" instead of "1 day ago / in 1 day". - unit = UDAT_ABSOLUTE_DAY; + aunit = com.ibm.icu.text.RelativeDateTimeFormatter.AbsoluteUnit.DAY; relative = false; } else if (count == 0) { // Show "Today" if time and now are on the same day. - unit = UDAT_ABSOLUTE_DAY; - direction = UDAT_DIRECTION_THIS; + aunit = com.ibm.icu.text.RelativeDateTimeFormatter.AbsoluteUnit.DAY; + direction = com.ibm.icu.text.RelativeDateTimeFormatter.Direction.THIS; relative = false; } } else if (minResolution == WEEK_IN_MILLIS) { count = (int)(duration / WEEK_IN_MILLIS); - unit = UDAT_RELATIVE_WEEKS; + unit = com.ibm.icu.text.RelativeDateTimeFormatter.RelativeUnit.WEEKS; } else { // The duration is longer than a week and minResolution is not // WEEK_IN_MILLIS. Return the absolute date instead of relative time. @@ -249,16 +217,14 @@ public final class RelativeDateTimeFormatter { if (relative) { synchronized (CACHED_FORMATTERS) { - return formatWithRelativeUnit(getFormatter(locale.toString(), style, - capitalizationContext), - count, direction, unit); + return getFormatter(locale.toString(), style, capitalizationContext) + .format(count, direction, unit); } } else { - capitalizationContext = UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE; + capitalizationContext = DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE; synchronized (CACHED_FORMATTERS) { - return formatWithAbsoluteUnit(getFormatter(locale.toString(), style, - capitalizationContext), - direction, unit); + return getFormatter(locale.toString(), style, capitalizationContext) + .format(direction, aunit); } } } @@ -277,7 +243,7 @@ public final class RelativeDateTimeFormatter { * clause. When the elapsed time is less than the transition resolution, it * displays the relative time string. Otherwise, it gives the absolute * numeric date string as the date clause. With the date and time clauses, it - * relies on icu4c's RelativeDateTimeFormatter::combineDateAndTime() to + * relies on icu4j's RelativeDateTimeFormatter::combineDateAndTime() to * concatenate the two. * * It takes two additional parameters of Locale and TimeZone than the @@ -311,17 +277,16 @@ public final class RelativeDateTimeFormatter { if (transitionResolution > WEEK_IN_MILLIS) { transitionResolution = WEEK_IN_MILLIS; } - // Use UDAT_STYLE_SHORT or UDAT_STYLE_LONG. - int style; + com.ibm.icu.text.RelativeDateTimeFormatter.Style style; if ((flags & (FORMAT_ABBREV_RELATIVE | FORMAT_ABBREV_ALL)) != 0) { - style = UDAT_STYLE_SHORT; + style = com.ibm.icu.text.RelativeDateTimeFormatter.Style.SHORT; } else { - style = UDAT_STYLE_LONG; + style = com.ibm.icu.text.RelativeDateTimeFormatter.Style.LONG; } - // icu4c also has other options available to control the capitalization. We + // icu4j also has other options available to control the capitalization. We // are currently using the _NONE option only. - int capitalizationContext = UDISPCTX_CAPITALIZATION_NONE; + DisplayContext capitalizationContext = DisplayContext.CAPITALIZATION_NONE; Calendar timeCalendar = new GregorianCalendar(false); timeCalendar.setTimeZone(tz); @@ -358,8 +323,8 @@ public final class RelativeDateTimeFormatter { // Combine the two clauses, such as '5 days ago, 10:50 AM'. synchronized (CACHED_FORMATTERS) { - return combineDateAndTime(getFormatter(locale.toString(), style, capitalizationContext), - dateClause, timeClause); + return getFormatter(locale.toString(), style, capitalizationContext) + .combineDateAndTime(dateClause, timeClause); } } @@ -371,19 +336,16 @@ public final class RelativeDateTimeFormatter { * getFormatter() may have been evicted by the time of the call to * formatter->action(). */ - private static long getFormatter(String localeName, int style, int capitalizationContext) { + private static com.ibm.icu.text.RelativeDateTimeFormatter getFormatter( + String localeName, com.ibm.icu.text.RelativeDateTimeFormatter.Style style, + DisplayContext capitalizationContext) { String key = localeName + "\t" + style + "\t" + capitalizationContext; - Long formatter = CACHED_FORMATTERS.get(key); + com.ibm.icu.text.RelativeDateTimeFormatter formatter = CACHED_FORMATTERS.get(key); if (formatter == null) { - formatter = createRelativeDateTimeFormatter(localeName, style, capitalizationContext); + formatter = com.ibm.icu.text.RelativeDateTimeFormatter.getInstance( + new ULocale(localeName), null, style, capitalizationContext); CACHED_FORMATTERS.put(key, formatter); } return formatter; } - - private static native long createRelativeDateTimeFormatter(String localeName, int style, int capitalizationContext); - private static native void destroyRelativeDateTimeFormatter(long address); - private static native String formatWithRelativeUnit(long address, int quantity, int direction, int unit); - private static native String formatWithAbsoluteUnit(long address, int direction, int unit); - private static native String combineDateAndTime(long address, String relativeDateString, String timeString); } diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp index fdc4027..035b1d9 100644 --- a/luni/src/main/native/Register.cpp +++ b/luni/src/main/native/Register.cpp @@ -58,7 +58,6 @@ jint JNI_OnLoad(JavaVM* vm, void*) { REGISTER(register_java_util_zip_Deflater); REGISTER(register_java_util_zip_Inflater); REGISTER(register_libcore_icu_AlphabeticIndex); - REGISTER(register_libcore_icu_DateIntervalFormat); REGISTER(register_libcore_icu_ICU); REGISTER(register_libcore_icu_NativeCollation); REGISTER(register_libcore_icu_NativeConverter); @@ -66,7 +65,6 @@ jint JNI_OnLoad(JavaVM* vm, void*) { REGISTER(register_libcore_icu_NativeIDN); REGISTER(register_libcore_icu_NativeNormalizer); REGISTER(register_libcore_icu_NativePluralRules); - REGISTER(register_libcore_icu_RelativeDateTimeFormatter); REGISTER(register_libcore_icu_TimeZoneNames); REGISTER(register_libcore_icu_Transliterator); REGISTER(register_libcore_io_AsynchronousCloseMonitor); diff --git a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp deleted file mode 100644 index f369a09..0000000 --- a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "DateIntervalFormat" - -#include "IcuUtilities.h" -#include "JniConstants.h" -#include "ScopedIcuLocale.h" -#include "ScopedJavaUnicodeString.h" -#include "cutils/log.h" -#include "unicode/dtitvfmt.h" - -static jlong DateIntervalFormat_createDateIntervalFormat(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName, jstring javaTzName) { - ScopedIcuLocale icuLocale(env, javaLocaleName); - if (!icuLocale.valid()) { - return 0; - } - - ScopedJavaUnicodeString skeletonHolder(env, javaSkeleton); - if (!skeletonHolder.valid()) { - return 0; - } - - UErrorCode status = U_ZERO_ERROR; - icu::DateIntervalFormat* formatter(icu::DateIntervalFormat::createInstance(skeletonHolder.unicodeString(), icuLocale.locale(), status)); - if (maybeThrowIcuException(env, "DateIntervalFormat::createInstance", status)) { - return 0; - } - - ScopedJavaUnicodeString tzNameHolder(env, javaTzName); - if (!tzNameHolder.valid()) { - return 0; - } - formatter->adoptTimeZone(icu::TimeZone::createTimeZone(tzNameHolder.unicodeString())); - - return reinterpret_cast<uintptr_t>(formatter); -} - -static void DateIntervalFormat_destroyDateIntervalFormat(JNIEnv*, jclass, jlong address) { - delete reinterpret_cast<icu::DateIntervalFormat*>(address); -} - -static jstring DateIntervalFormat_formatDateInterval(JNIEnv* env, jclass, jlong address, jlong fromDate, jlong toDate) { - icu::DateIntervalFormat* formatter(reinterpret_cast<icu::DateIntervalFormat*>(address)); - icu::DateInterval date_interval(fromDate, toDate); - - icu::UnicodeString s; - icu::FieldPosition pos = 0; - UErrorCode status = U_ZERO_ERROR; - formatter->format(&date_interval, s, pos, status); - if (maybeThrowIcuException(env, "DateIntervalFormat::format", status)) { - return NULL; - } - - return env->NewString(s.getBuffer(), s.length()); -} - -static JNINativeMethod gMethods[] = { - NATIVE_METHOD(DateIntervalFormat, createDateIntervalFormat, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J"), - NATIVE_METHOD(DateIntervalFormat, destroyDateIntervalFormat, "(J)V"), - NATIVE_METHOD(DateIntervalFormat, formatDateInterval, "(JJJ)Ljava/lang/String;"), -}; -void register_libcore_icu_DateIntervalFormat(JNIEnv* env) { - jniRegisterNativeMethods(env, "libcore/icu/DateIntervalFormat", gMethods, NELEM(gMethods)); -} diff --git a/luni/src/main/native/libcore_icu_RelativeDateTimeFormatter.cpp b/luni/src/main/native/libcore_icu_RelativeDateTimeFormatter.cpp deleted file mode 100644 index 6215d5f..0000000 --- a/luni/src/main/native/libcore_icu_RelativeDateTimeFormatter.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "RelativeDateTimeFormatter" - -#include "IcuUtilities.h" -#include "JniConstants.h" -#include "ScopedIcuLocale.h" -#include "ScopedJavaUnicodeString.h" -#include "cutils/log.h" -#include "unicode/reldatefmt.h" - -static jlong RelativeDateTimeFormatter_createRelativeDateTimeFormatter(JNIEnv* env, jclass, - jstring javaLocaleName, jint style, jint capitalizationContext) { - ScopedIcuLocale icuLocale(env, javaLocaleName); - if (!icuLocale.valid()) { - return 0; - } - - UErrorCode status = U_ZERO_ERROR; - icu::RelativeDateTimeFormatter* formatter = new icu::RelativeDateTimeFormatter( - icuLocale.locale(), nullptr, static_cast<UDateRelativeDateTimeFormatterStyle>(style), - static_cast<UDisplayContext>(capitalizationContext), status); - if (maybeThrowIcuException(env, "RelativeDateTimeFormatter::RelativeDateTimeFormatter", status)) { - return 0; - } - - return reinterpret_cast<uintptr_t>(formatter); -} - -static void RelativeDateTimeFormatter_destroyRelativeDateTimeFormatter(JNIEnv*, jclass, - jlong formatterAddress) { - delete reinterpret_cast<icu::RelativeDateTimeFormatter*>(static_cast<uintptr_t>(formatterAddress)); -} - -static jstring RelativeDateTimeFormatter_formatWithRelativeUnit(JNIEnv* env, jclass, - jlong formatterAddress, jint quantity, jint direction, jint unit) { - icu::RelativeDateTimeFormatter* formatter(reinterpret_cast<icu::RelativeDateTimeFormatter*>(formatterAddress)); - icu::UnicodeString s; - UErrorCode status = U_ZERO_ERROR; - // RelativeDateTimeFormatter::format() takes a double-type quantity. - formatter->format(static_cast<double>(quantity), static_cast<UDateDirection>(direction), - static_cast<UDateRelativeUnit>(unit), s, status); - if (maybeThrowIcuException(env, "RelativeDateTimeFormatter::format", status)) { - return nullptr; - } - - return env->NewString(s.getBuffer(), s.length()); -} - -static jstring RelativeDateTimeFormatter_formatWithAbsoluteUnit(JNIEnv* env, jclass, - jlong formatterAddress, jint direction, jint unit) { - icu::RelativeDateTimeFormatter* formatter(reinterpret_cast<icu::RelativeDateTimeFormatter*>(formatterAddress)); - icu::UnicodeString s; - UErrorCode status = U_ZERO_ERROR; - formatter->format(static_cast<UDateDirection>(direction), static_cast<UDateAbsoluteUnit>(unit), s, status); - if (maybeThrowIcuException(env, "RelativeDateTimeFormatter::format", status)) { - return nullptr; - } - - return env->NewString(s.getBuffer(), s.length()); -} - -static jstring RelativeDateTimeFormatter_combineDateAndTime(JNIEnv* env, jclass, - jlong formatterAddress, jstring relativeDateString0, jstring timeString0) { - icu::RelativeDateTimeFormatter* formatter(reinterpret_cast<icu::RelativeDateTimeFormatter*>(formatterAddress)); - ScopedJavaUnicodeString relativeDateString(env, relativeDateString0); - if (!relativeDateString.valid()) { - return 0; - } - - ScopedJavaUnicodeString timeString(env, timeString0); - if (!timeString.valid()) { - return 0; - } - icu::UnicodeString s; - UErrorCode status = U_ZERO_ERROR; - formatter->combineDateAndTime(relativeDateString.unicodeString(), timeString.unicodeString(), s, status); - if (maybeThrowIcuException(env, "RelativeDateTimeFormatter::combineDateAndTime", status)) { - return nullptr; - } - - return env->NewString(s.getBuffer(), s.length()); -} - -static JNINativeMethod gMethods[] = { - NATIVE_METHOD(RelativeDateTimeFormatter, createRelativeDateTimeFormatter, "(Ljava/lang/String;II)J"), - NATIVE_METHOD(RelativeDateTimeFormatter, destroyRelativeDateTimeFormatter, "(J)V"), - NATIVE_METHOD(RelativeDateTimeFormatter, formatWithRelativeUnit, "(JIII)Ljava/lang/String;"), - NATIVE_METHOD(RelativeDateTimeFormatter, formatWithAbsoluteUnit, "(JII)Ljava/lang/String;"), - NATIVE_METHOD(RelativeDateTimeFormatter, combineDateAndTime, "(JLjava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), -}; - -void register_libcore_icu_RelativeDateTimeFormatter(JNIEnv* env) { - jniRegisterNativeMethods(env, "libcore/icu/RelativeDateTimeFormatter", gMethods, NELEM(gMethods)); -} diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk index 886ab0d..2bc44ed 100644 --- a/luni/src/main/native/sub.mk +++ b/luni/src/main/native/sub.mk @@ -38,7 +38,6 @@ LOCAL_SRC_FILES := \ java_util_zip_Deflater.cpp \ java_util_zip_Inflater.cpp \ libcore_icu_AlphabeticIndex.cpp \ - libcore_icu_DateIntervalFormat.cpp \ libcore_icu_ICU.cpp \ libcore_icu_NativeCollation.cpp \ libcore_icu_NativeConverter.cpp \ @@ -46,7 +45,6 @@ LOCAL_SRC_FILES := \ libcore_icu_NativeIDN.cpp \ libcore_icu_NativeNormalizer.cpp \ libcore_icu_NativePluralRules.cpp \ - libcore_icu_RelativeDateTimeFormatter.cpp \ libcore_icu_TimeZoneNames.cpp \ libcore_icu_Transliterator.cpp \ libcore_io_AsynchronousCloseMonitor.cpp \ diff --git a/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java index 279f934..d49579c 100644 --- a/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java +++ b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java @@ -143,6 +143,7 @@ public class DateIntervalFormatTest extends junit.framework.TestCase { assertEquals("19 de ene. de 2009 – 9 de feb. de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL)); assertEquals("ene. de 2009 – feb. de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL)); + assertEquals("19 de enero de 2009–9 de febrero de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, 0)); assertEquals("lunes, 19 de enero de 2009–jueves, 9 de febrero de 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR, FORMAT_SHOW_WEEKDAY)); |