From c6bffbf6033c88d1b8403360ba129831b0155f33 Mon Sep 17 00:00:00 2001 From: Roozbeh Pournader Date: Tue, 13 Dec 2016 13:58:56 -0800 Subject: [PATCH] Use ICU for formatting in DateUtils.formatDuration Previously, we were using native strings. ICU has higher quality and more comprehensive data. Also adds parameters for specifying the format width (e.g. "2 hrs" vs "2 hours"). Bug: 31526474 Test: adb shell am instrument -w -e class android.text.format.DateUtilsTest com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner Change-Id: I754f6c761c2ed3853046796c57ff2d86a6ccd43e --- core/java/android/text/format/DateUtils.java | 50 +++++++++++++++---- .../android/text/format/DateUtilsTest.java | 30 +++++++++++ 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java index f16e714d82d17..e19b2c71b8414 100644 --- a/core/java/android/text/format/DateUtils.java +++ b/core/java/android/text/format/DateUtils.java @@ -19,6 +19,10 @@ package android.text.format; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; +import android.icu.text.MeasureFormat; +import android.icu.text.MeasureFormat.FormatWidth; +import android.icu.util.Measure; +import android.icu.util.MeasureUnit; import com.android.internal.R; @@ -351,26 +355,54 @@ public class DateUtils } /** - * Return given duration in a human-friendly format. For example, "4 - * minutes" or "1 second". Returns only largest meaningful unit of time, + * Returns the given duration in a human-friendly format. For example, + * "4 minutes" or "1 second". Returns only the largest meaningful unit of time, * from seconds up to hours. * * @hide */ public static CharSequence formatDuration(long millis) { - final Resources res = Resources.getSystem(); + return formatDuration(millis, LENGTH_LONG); + } + + /** + * Returns the given duration in a human-friendly format. For example, + * "4 minutes" or "1 second". Returns only the largest meaningful unit of time, + * from seconds up to hours. + *

+ * You can use abbrev to specify a preference for abbreviations (but note that some + * locales may not have abbreviations). Use LENGTH_LONG for the full spelling (e.g. "2 hours"), + * LENGTH_SHORT for the abbreviated spelling if available (e.g. "2 hr"), and LENGTH_SHORTEST for + * the briefest form available (e.g. "2h"). + * @hide + */ + public static CharSequence formatDuration(long millis, int abbrev) { + final FormatWidth width; + switch (abbrev) { + case LENGTH_LONG: + width = FormatWidth.WIDE; + break; + case LENGTH_SHORT: + case LENGTH_SHORTER: + case LENGTH_MEDIUM: + width = FormatWidth.SHORT; + break; + case LENGTH_SHORTEST: + width = FormatWidth.NARROW; + break; + default: + width = FormatWidth.WIDE; + } + final MeasureFormat formatter = MeasureFormat.getInstance(Locale.getDefault(), width); if (millis >= HOUR_IN_MILLIS) { final int hours = (int) ((millis + 1800000) / HOUR_IN_MILLIS); - return res.getQuantityString( - com.android.internal.R.plurals.duration_hours, hours, hours); + return formatter.format(new Measure(hours, MeasureUnit.HOUR)); } else if (millis >= MINUTE_IN_MILLIS) { final int minutes = (int) ((millis + 30000) / MINUTE_IN_MILLIS); - return res.getQuantityString( - com.android.internal.R.plurals.duration_minutes, minutes, minutes); + return formatter.format(new Measure(minutes, MeasureUnit.MINUTE)); } else { final int seconds = (int) ((millis + 500) / SECOND_IN_MILLIS); - return res.getQuantityString( - com.android.internal.R.plurals.duration_seconds, seconds, seconds); + return formatter.format(new Measure(seconds, MeasureUnit.SECOND)); } } diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java index 909f971db1b1f..de43fc67dcf56 100644 --- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java +++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java @@ -61,6 +61,18 @@ public class DateUtilsTest extends TestCase { assertEquals("1 second", DateUtils.formatDuration(500)); assertEquals("1 second", DateUtils.formatDuration(1000)); assertEquals("2 seconds", DateUtils.formatDuration(1500)); + + assertEquals("0 seconds", DateUtils.formatDuration(0, DateUtils.LENGTH_LONG)); + assertEquals("1 second", DateUtils.formatDuration(1000, DateUtils.LENGTH_LONG)); + assertEquals("2 seconds", DateUtils.formatDuration(1500, DateUtils.LENGTH_LONG)); + + assertEquals("0 sec", DateUtils.formatDuration(0, DateUtils.LENGTH_SHORT)); + assertEquals("1 sec", DateUtils.formatDuration(1000, DateUtils.LENGTH_SHORT)); + assertEquals("2 sec", DateUtils.formatDuration(1500, DateUtils.LENGTH_SHORT)); + + assertEquals("0s", DateUtils.formatDuration(0, DateUtils.LENGTH_SHORTEST)); + assertEquals("1s", DateUtils.formatDuration(1000, DateUtils.LENGTH_SHORTEST)); + assertEquals("2s", DateUtils.formatDuration(1500, DateUtils.LENGTH_SHORTEST)); } @SmallTest @@ -69,6 +81,15 @@ public class DateUtilsTest extends TestCase { assertEquals("60 seconds", DateUtils.formatDuration(59500)); assertEquals("1 minute", DateUtils.formatDuration(60000)); assertEquals("2 minutes", DateUtils.formatDuration(120000)); + + assertEquals("1 minute", DateUtils.formatDuration(60000, DateUtils.LENGTH_LONG)); + assertEquals("2 minutes", DateUtils.formatDuration(120000, DateUtils.LENGTH_LONG)); + + assertEquals("1 min", DateUtils.formatDuration(60000, DateUtils.LENGTH_SHORT)); + assertEquals("2 min", DateUtils.formatDuration(120000, DateUtils.LENGTH_SHORT)); + + assertEquals("1m", DateUtils.formatDuration(60000, DateUtils.LENGTH_SHORTEST)); + assertEquals("2m", DateUtils.formatDuration(120000, DateUtils.LENGTH_SHORTEST)); } @SmallTest @@ -76,5 +97,14 @@ public class DateUtilsTest extends TestCase { assertEquals("59 minutes", DateUtils.formatDuration(3540000)); assertEquals("1 hour", DateUtils.formatDuration(3600000)); assertEquals("48 hours", DateUtils.formatDuration(172800000)); + + assertEquals("1 hour", DateUtils.formatDuration(3600000, DateUtils.LENGTH_LONG)); + assertEquals("48 hours", DateUtils.formatDuration(172800000, DateUtils.LENGTH_LONG)); + + assertEquals("1 hr", DateUtils.formatDuration(3600000, DateUtils.LENGTH_SHORT)); + assertEquals("48 hr", DateUtils.formatDuration(172800000, DateUtils.LENGTH_SHORT)); + + assertEquals("1h", DateUtils.formatDuration(3600000, DateUtils.LENGTH_SHORTEST)); + assertEquals("48h", DateUtils.formatDuration(172800000, DateUtils.LENGTH_SHORTEST)); } }