Pav*_* S. 10 formatting time android
我想格式化一个字符串中的持续时间(例如以秒为单位),该字符串将包含时间单位的本地化名称.例如,对于输入8692,我将得到字符串"2小时24分52秒",其中时间单位正确地针对每种语言进行了本地化.Android中是否有一些类可以做到这一点?有没有人知道一些外部开源库?谢谢.
我在尝试使用本地化格式打印 KotlinDuration类型时刚刚遇到了同样的问题,因为我找不到好的解决方案,所以我自己编写了一个。它基于从 Android 9 开始提供的 API(针对本地化单位),但对于较低的 Android 版本则回退到英语单位,因此它可以与较低定位的应用程序一起使用。
下面是它在使用方面的样子(请参阅 Kotlin Duration类型以了解第一行):
\nval duration = 5.days.plus(3.hours).plus(2.minutes).plus(214.milliseconds)\n\nDurationFormat().format(duration) // "5day 3hour 2min"\nDurationFormat(Locale.GERMANY).format(duration) // "5T 3Std. 2Min."\nDurationFormat(Locale.forLanguageTag("ar").format(duration) // "\xd9\xa5\xd9\x8a\xd9\x88\xd9\x85 \xd9\xa3\xd8\xb3\xd8\xa7\xd8\xb9\xd8\xa9 \xd9\xa2\xd8\xaf"\nDurationFormat().format(duration, smallestUnit = DurationFormat.Unit.HOUR) // "5day 3hour"\nDurationFormat().format(15.minutes) // "15min"\nDurationFormat().format(0.hours) // "0sec"\nRun Code Online (Sandbox Code Playgroud)\nlocale正如您所看到的,您可以指定类型的自定义DurationFormat。默认情况下它使用Locale.getDefault(). 还支持具有与罗马语不同的数字符号的语言(通过NumberFormat)。另外,您可以指定自定义smallestUnit,默认情况下将其设置为SECOND,因此不会显示毫秒。请注意,任何值为 的单位0都将被忽略,如果整个数字为0,则该值将使用最小单位0。
这是完整的DurationFormat类型,请随意复制(也可以作为GitHub gist提供,包括单元测试):
import android.icu.text.MeasureFormat\nimport android.icu.text.NumberFormat\nimport android.icu.util.MeasureUnit\nimport android.os.Build\nimport java.util.Locale\nimport kotlin.time.Duration\nimport kotlin.time.ExperimentalTime\nimport kotlin.time.days\nimport kotlin.time.hours\nimport kotlin.time.milliseconds\nimport kotlin.time.minutes\nimport kotlin.time.seconds\n\n@ExperimentalTime\ndata class DurationFormat(val locale: Locale = Locale.getDefault()) {\n enum class Unit {\n DAY, HOUR, MINUTE, SECOND, MILLISECOND\n }\n\n fun format(duration: kotlin.time.Duration, smallestUnit: Unit = Unit.SECOND): String {\n var formattedStringComponents = mutableListOf<String>()\n var remainder = duration\n\n for (unit in Unit.values()) {\n val component = calculateComponent(unit, remainder)\n\n remainder = when (unit) {\n Unit.DAY -> remainder - component.days\n Unit.HOUR -> remainder - component.hours\n Unit.MINUTE -> remainder - component.minutes\n Unit.SECOND -> remainder - component.seconds\n Unit.MILLISECOND -> remainder - component.milliseconds\n }\n\n val unitDisplayName = unitDisplayName(unit)\n\n if (component > 0) {\n val formattedComponent = NumberFormat.getInstance(locale).format(component)\n formattedStringComponents.add("$formattedComponent$unitDisplayName")\n }\n\n if (unit == smallestUnit) {\n val formattedZero = NumberFormat.getInstance(locale).format(0)\n if (formattedStringComponents.isEmpty()) formattedStringComponents.add("$formattedZero$unitDisplayName")\n break\n }\n }\n\n return formattedStringComponents.joinToString(" ")\n }\n\n private fun calculateComponent(unit: Unit, remainder: Duration) = when (unit) {\n Unit.DAY -> remainder.inDays.toLong()\n Unit.HOUR -> remainder.inHours.toLong()\n Unit.MINUTE -> remainder.inMinutes.toLong()\n Unit.SECOND -> remainder.inSeconds.toLong()\n Unit.MILLISECOND -> remainder.inMilliseconds.toLong()\n }\n\n private fun unitDisplayName(unit: Unit) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {\n val measureFormat = MeasureFormat.getInstance(locale, MeasureFormat.FormatWidth.NARROW)\n when (unit) {\n DurationFormat.Unit.DAY -> measureFormat.getUnitDisplayName(MeasureUnit.DAY)\n DurationFormat.Unit.HOUR -> measureFormat.getUnitDisplayName(MeasureUnit.HOUR)\n DurationFormat.Unit.MINUTE -> measureFormat.getUnitDisplayName(MeasureUnit.MINUTE)\n DurationFormat.Unit.SECOND -> measureFormat.getUnitDisplayName(MeasureUnit.SECOND)\n DurationFormat.Unit.MILLISECOND -> measureFormat.getUnitDisplayName(MeasureUnit.MILLISECOND)\n }\n } else {\n when (unit) {\n Unit.DAY -> "day"\n Unit.HOUR -> "hour"\n Unit.MINUTE -> "min"\n Unit.SECOND -> "sec"\n Unit.MILLISECOND -> "msec"\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
我不知道任何开源库,但如果我正确理解问题,那么手工完成应该不会太难:
public static String foo(int duration) {
int hours = duration/3600;
int minutes = (duration%3600)/60;
int seconds = duration%60;
return hours + getResources().getString(R.string.hours) +
minutes + getResources().getString(R.string.minutes) +
seconds + getResources().getString(R.string.seconds);
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以在您的文件中定义这些字符串strings.xml,并像平常一样对它们进行本地化。(请参阅http://developer.android.com/guide/topics/resources/localization.html)
至于Android,有一个Duration类(http://developer.android.com/reference/javax/xml/datatype/Duration.html),您可以使用它,但它的toString()方法并不完全符合您的要求。
编辑只是为了完整性:我现在更好地理解您的问题,您不想手动本地化所有时间单位。Unicode 通用区域设置数据存储库提供了一些(嗯,很多)有趣的数据。它们提供几乎所有您可能想要本地化的内容的 XML 数据,例如de.xml(德语):
<unit type="duration-hour">
<displayName>Stunden</displayName>
<unitPattern count="one">{0} Stunde</unitPattern>
<unitPattern count="other">{0} Stunden</unitPattern>
<perUnitPattern>{0} pro Stunde</perUnitPattern>
</unit>
Run Code Online (Sandbox Code Playgroud)
我认为这有点矫枉过正,但正如我所说:为了完整性。