diff options
| -rw-r--r-- | core/java/android/text/format/Formatter.java | 60 | ||||
| -rw-r--r-- | core/res/res/values/strings.xml | 42 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 12 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/text/format/FormatterTest.java | 94 |
4 files changed, 123 insertions, 85 deletions
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java index b67ac9840d60..e5bc32bb4f0a 100644 --- a/core/java/android/text/format/Formatter.java +++ b/core/java/android/text/format/Formatter.java @@ -20,6 +20,9 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.content.res.Resources; +import android.icu.text.MeasureFormat; +import android.icu.util.Measure; +import android.icu.util.MeasureUnit; import android.net.NetworkUtils; import android.text.BidiFormatter; import android.text.TextUtils; @@ -51,9 +54,13 @@ public final class Formatter { } } + private static Locale localeFromContext(@NonNull Context context) { + return context.getResources().getConfiguration().getLocales().get(0); + } + /* Wraps the source string in bidi formatting characters in RTL locales */ private static String bidiWrap(@NonNull Context context, String source) { - final Locale locale = context.getResources().getConfiguration().locale; + final Locale locale = localeFromContext(context); if (TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL) { return BidiFormatter.getInstance(true /* RTL*/).unicodeWrap(source); } else { @@ -197,7 +204,7 @@ public final class Formatter { /** * Returns elapsed time for the given millis, in the following format: - * 1 day 5 hrs; will include at most two units, can go down to seconds precision. + * 1 day, 5 hr; will include at most two units, can go down to seconds precision. * @param context the application context * @param millis the elapsed time in milli seconds * @return the formatted elapsed time @@ -221,44 +228,38 @@ public final class Formatter { } int seconds = (int)secondsLong; + final Locale locale = localeFromContext(context); + final MeasureFormat measureFormat = MeasureFormat.getInstance( + locale, MeasureFormat.FormatWidth.SHORT); if (days >= 2) { days += (hours+12)/24; - return context.getString(com.android.internal.R.string.durationDays, days); + return measureFormat.format(new Measure(days, MeasureUnit.DAY)); } else if (days > 0) { - if (hours == 1) { - return context.getString(com.android.internal.R.string.durationDayHour, days, hours); - } - return context.getString(com.android.internal.R.string.durationDayHours, days, hours); + return measureFormat.formatMeasures( + new Measure(days, MeasureUnit.DAY), + new Measure(hours, MeasureUnit.HOUR)); } else if (hours >= 2) { hours += (minutes+30)/60; - return context.getString(com.android.internal.R.string.durationHours, hours); + return measureFormat.format(new Measure(hours, MeasureUnit.HOUR)); } else if (hours > 0) { - if (minutes == 1) { - return context.getString(com.android.internal.R.string.durationHourMinute, hours, - minutes); - } - return context.getString(com.android.internal.R.string.durationHourMinutes, hours, - minutes); + return measureFormat.formatMeasures( + new Measure(hours, MeasureUnit.HOUR), + new Measure(minutes, MeasureUnit.MINUTE)); } else if (minutes >= 2) { minutes += (seconds+30)/60; - return context.getString(com.android.internal.R.string.durationMinutes, minutes); + return measureFormat.format(new Measure(minutes, MeasureUnit.MINUTE)); } else if (minutes > 0) { - if (seconds == 1) { - return context.getString(com.android.internal.R.string.durationMinuteSecond, minutes, - seconds); - } - return context.getString(com.android.internal.R.string.durationMinuteSeconds, minutes, - seconds); - } else if (seconds == 1) { - return context.getString(com.android.internal.R.string.durationSecond, seconds); + return measureFormat.formatMeasures( + new Measure(minutes, MeasureUnit.MINUTE), + new Measure(seconds, MeasureUnit.SECOND)); } else { - return context.getString(com.android.internal.R.string.durationSeconds, seconds); + return measureFormat.format(new Measure(seconds, MeasureUnit.SECOND)); } } /** * Returns elapsed time for the given millis, in the following format: - * 1 day 5 hrs; will include at most two units, can go down to minutes precision. + * 1 day, 5 hr; will include at most two units, can go down to minutes precision. * @param context the application context * @param millis the elapsed time in milli seconds * @return the formatted elapsed time @@ -267,10 +268,11 @@ public final class Formatter { public static String formatShortElapsedTimeRoundingUpToMinutes(Context context, long millis) { long minutesRoundedUp = (millis + MILLIS_PER_MINUTE - 1) / MILLIS_PER_MINUTE; - if (minutesRoundedUp == 0) { - return context.getString(com.android.internal.R.string.durationMinutes, 0); - } else if (minutesRoundedUp == 1) { - return context.getString(com.android.internal.R.string.durationMinute, 1); + if (minutesRoundedUp == 0 || minutesRoundedUp == 1) { + final Locale locale = localeFromContext(context); + final MeasureFormat measureFormat = MeasureFormat.getInstance( + locale, MeasureFormat.FormatWidth.SHORT); + return measureFormat.format(new Measure(minutesRoundedUp, MeasureUnit.MINUTE)); } return formatShortElapsedTime(context, minutesRoundedUp * MILLIS_PER_MINUTE); diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index f48e037c8e47..f643f516f606 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -38,48 +38,6 @@ the placeholders. --> <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g> <xliff:g id="unit" example="MB">%2$s</xliff:g></string> - <!-- [CHAR_LIMIT=10] Suffix added to signify duration in days --> - <string name="durationDays"><xliff:g id="days">%1$d</xliff:g> days</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one day with hours --> - <string name="durationDayHours"><xliff:g id="days">%1$d</xliff:g> day - <xliff:g id="hours">%2$d</xliff:g> hrs</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one day with one hours --> - <string name="durationDayHour"><xliff:g id="days">%1$d</xliff:g> day - <xliff:g id="hours">%2$d</xliff:g> hr</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration in hours --> - <string name="durationHours"><xliff:g id="hours">%1$d</xliff:g> hrs</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one hour with minutes --> - <string name="durationHourMinutes"><xliff:g id="hours">%1$d</xliff:g> hr - <xliff:g id="minutes">%2$d</xliff:g> mins</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one hour with one minute --> - <string name="durationHourMinute"><xliff:g id="hours">%1$d</xliff:g> hr - <xliff:g id="minutes">%2$d</xliff:g> min</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration in minutes --> - <string name="durationMinutes"><xliff:g id="minutes">%1$d</xliff:g> mins</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one minute --> - <string name="durationMinute"><xliff:g id="minutes">%1$d</xliff:g> min</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one minute with seconds --> - <string name="durationMinuteSeconds"><xliff:g id="minutes">%1$d</xliff:g> min - <xliff:g id="seconds">%2$d</xliff:g> secs</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one minute with one second --> - <string name="durationMinuteSecond"><xliff:g id="minutes">%1$d</xliff:g> min - <xliff:g id="seconds">%2$d</xliff:g> sec</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration in seconds --> - <string name="durationSeconds"><xliff:g id="seconds">%1$d</xliff:g> secs</string> - - <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one second --> - <string name="durationSecond"><xliff:g id="seconds">%1$d</xliff:g> sec</string> - <!-- Used in Contacts for a field that has no label and in Note Pad for a note with no name. --> <string name="untitled"><Untitled></string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 7cee6d698c81..caa579cc8795 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -655,18 +655,6 @@ <java-symbol type="string" name="display_manager_overlay_display_secure_suffix" /> <java-symbol type="string" name="display_manager_overlay_display_title" /> <java-symbol type="string" name="double_tap_toast" /> - <java-symbol type="string" name="durationDays" /> - <java-symbol type="string" name="durationDayHours" /> - <java-symbol type="string" name="durationDayHour" /> - <java-symbol type="string" name="durationHours" /> - <java-symbol type="string" name="durationHourMinutes" /> - <java-symbol type="string" name="durationHourMinute" /> - <java-symbol type="string" name="durationMinutes" /> - <java-symbol type="string" name="durationMinute" /> - <java-symbol type="string" name="durationMinuteSeconds" /> - <java-symbol type="string" name="durationMinuteSecond" /> - <java-symbol type="string" name="durationSeconds" /> - <java-symbol type="string" name="durationSecond" /> <java-symbol type="string" name="elapsed_time_short_format_h_mm_ss" /> <java-symbol type="string" name="elapsed_time_short_format_mm_ss" /> <java-symbol type="string" name="emailTypeCustom" /> diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java index a4ce911cf929..ff75c29cc112 100644 --- a/core/tests/coretests/src/android/text/format/FormatterTest.java +++ b/core/tests/coretests/src/android/text/format/FormatterTest.java @@ -26,12 +26,13 @@ import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.text.format.Formatter.BytesResult; -import java.util.Locale; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Locale; + @SmallTest @RunWith(AndroidJUnit4.class) public class FormatterTest { @@ -54,7 +55,7 @@ public class FormatterTest { @Test public void testFormatBytes() { - setLocale(Locale.ENGLISH); + setLocale(Locale.US); checkFormatBytes(0, true, "0", 0); checkFormatBytes(0, false, "0", 0); @@ -99,6 +100,95 @@ public class FormatterTest { checkFormatBytes(9123000, false, "9,12", 9120000); } + private static final long SECOND = 1000; + private static final long MINUTE = 60 * SECOND; + private static final long HOUR = 60 * MINUTE; + private static final long DAY = 24 * HOUR; + + @Test + public void testFormatShortElapsedTime() { + setLocale(Locale.US); + assertEquals("3 days", Formatter.formatShortElapsedTime(mContext, 2 * DAY + 12 * HOUR)); + assertEquals("2 days", Formatter.formatShortElapsedTime(mContext, 2 * DAY + 11 * HOUR)); + assertEquals("2 days", Formatter.formatShortElapsedTime(mContext, 2 * DAY)); + assertEquals("1 day, 23 hr", + Formatter.formatShortElapsedTime(mContext, 1 * DAY + 23 * HOUR + 59 * MINUTE)); + assertEquals("1 day, 0 hr", + Formatter.formatShortElapsedTime(mContext, 1 * DAY + 59 * MINUTE)); + assertEquals("1 day, 0 hr", Formatter.formatShortElapsedTime(mContext, 1 * DAY)); + assertEquals("24 hr", Formatter.formatShortElapsedTime(mContext, 23 * HOUR + 30 * MINUTE)); + assertEquals("3 hr", Formatter.formatShortElapsedTime(mContext, 2 * HOUR + 30 * MINUTE)); + assertEquals("2 hr", Formatter.formatShortElapsedTime(mContext, 2 * HOUR)); + assertEquals("1 hr, 0 min", Formatter.formatShortElapsedTime(mContext, 1 * HOUR)); + assertEquals("60 min", + Formatter.formatShortElapsedTime(mContext, 59 * MINUTE + 30 * SECOND)); + assertEquals("59 min", + Formatter.formatShortElapsedTime(mContext, 59 * MINUTE)); + assertEquals("3 min", Formatter.formatShortElapsedTime(mContext, 2 * MINUTE + 30 * SECOND)); + assertEquals("2 min", Formatter.formatShortElapsedTime(mContext, 2 * MINUTE)); + assertEquals("1 min, 59 sec", + Formatter.formatShortElapsedTime(mContext, 1 * MINUTE + 59 * SECOND + 999)); + assertEquals("1 min, 0 sec", Formatter.formatShortElapsedTime(mContext, 1 * MINUTE)); + assertEquals("59 sec", Formatter.formatShortElapsedTime(mContext, 59 * SECOND + 999)); + assertEquals("1 sec", Formatter.formatShortElapsedTime(mContext, 1 * SECOND)); + assertEquals("0 sec", Formatter.formatShortElapsedTime(mContext, 1)); + assertEquals("0 sec", Formatter.formatShortElapsedTime(mContext, 0)); + + // Make sure it works on different locales. + setLocale(Locale.FRANCE); + assertEquals("2 j", Formatter.formatShortElapsedTime(mContext, 2 * DAY)); + } + + @Test + public void testFormatShortElapsedTimeRoundingUpToMinutes() { + setLocale(Locale.US); + assertEquals("3 days", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 2 * DAY + 12 * HOUR)); + assertEquals("2 days", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 2 * DAY + 11 * HOUR)); + assertEquals("2 days", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 2 * DAY)); + assertEquals("1 day, 23 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 1 * DAY + 23 * HOUR + 59 * MINUTE)); + assertEquals("1 day, 0 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 1 * DAY + 59 * MINUTE)); + assertEquals("1 day, 0 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 1 * DAY)); + assertEquals("24 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 23 * HOUR + 30 * MINUTE)); + assertEquals("3 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 2 * HOUR + 30 * MINUTE)); + assertEquals("2 hr", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 2 * HOUR)); + assertEquals("1 hr, 0 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 1 * HOUR)); + assertEquals("1 hr, 0 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 59 * MINUTE + 30 * SECOND)); + assertEquals("59 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 59 * MINUTE)); + assertEquals("3 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 2 * MINUTE + 30 * SECOND)); + assertEquals("2 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 2 * MINUTE)); + assertEquals("2 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 1 * MINUTE + 59 * SECOND + 999)); + assertEquals("1 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 1 * MINUTE)); + assertEquals("1 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 59 * SECOND + 999)); + assertEquals("1 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 1 * SECOND)); + assertEquals("1 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 1)); + assertEquals("0 min", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 0)); + + // Make sure it works on different locales. + setLocale(new Locale("ru", "RU")); + assertEquals("1 мин", Formatter.formatShortElapsedTimeRoundingUpToMinutes( + mContext, 1 * SECOND)); + } + private void checkFormatBytes(long bytes, boolean useShort, String expectedString, long expectedRounded) { BytesResult r = Formatter.formatBytes(mContext.getResources(), bytes, |