summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/text/format/Formatter.java60
-rw-r--r--core/res/res/values/strings.xml42
-rw-r--r--core/res/res/values/symbols.xml12
-rw-r--r--core/tests/coretests/src/android/text/format/FormatterTest.java94
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">&lt;Untitled&gt;</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,