时差表达

Expression of time difference

给定多个 seconds/milliseconds,使用 Android values/strings.xml [=69] gracefully/cleanly 以用户语言表达此时间间隔的最佳方法是什么=]?

我不是在问如何获得 days/hours/minutes -- 答案可以在 how to show milliseconds in days:hours:min:seconds 和许多其他问题中找到。为了您的信息,我的代码:

int time1, time0; // given
int seconds, minutes, hours, days;
seconds = time1 - time0;
// TODO handle seconds <= 0
days = seconds / 86400;
hours = (seconds %= 86400) / 3600;
minutes = (seconds %= 3600) / 60;
seconds %= 60;

这些是我脑补出来的一些方法,但都有不足之处。 没有这些问题的最佳方法是什么?

方法 1:使用 printf 格式

strings.xml

<string name="format_time" formatted="false">
    %d day(s) %d hour(s) %d minute(s) %d second(s)
</string>

Java代码

getString(R.string.format_time, days, hours, minutes, seconds);

问题

由于 (s) 会启发您,我们不希望看到 0 day(s) 0 hour(s) 0 minute(s) 1 second(s)。我们也不喜欢 1 day(s) 0 hour(s) 0 minute(s) 0 second(s),只喜欢 1 day

方法 2:使用每单位术语

strings.xml

<string-array name="time_units">
    <item>day(s)</item>
    <item>hour(s)</item>
    <item>minute(s)</item>
    <item>second(s)</item>
</string-array>
<string name="time_value_unit_separator">" "</string>
<string name="time_inter_unit_separator">", "</string>

Java代码

String[] units = getResources().getStringArray(R.array.time_units);
int[] values = {days, hours, minutes, seconds};
assert units.length == values.length;
StringBuilder builder = new StringBuilder();
final String valueUnitSeparator = getString(R.string.time_value_unit_separator);
final String unitSeparator = getString(R.string.time_inter_unit_separator);
for(int i = 0; i < units.length; i++){
    if(values[i] > 0)
        builder.append(values[i])
                .append(valueUnitSeparator)
                .append(units[i])
                .append(unitSeparator);
}
return builder.substring(0, builder.length() - unitSeparator.length());

问题

  1. 根据 ,不鼓励开发人员使用字符串连接来构建用户界面文本。我无法找到其背后的官方原因以供参考。
  2. 也许有些语言更喜欢说 seconds 5 而不是 5 seconds
  3. 也许有些语言更喜欢说 30 seconds, 2 minutes 而不是 2 minutes 30 seconds

关于连接的第一部分,使用 Android 框架没有干净的方法。 "official" 的原因是连接比使用格式化慢,但你在这里谈论的是毫秒。最坏的情况是,您只会每隔一秒更新一次文本,这样就不会很痛苦,而且没人会注意到。

有一个叫做 Plurals 的东西,你可以用它来获取不同的字符串(即 "Hour" 代表 1 小时,"Hours" 代表 >1 小时)。所以你可以获得像这样的实用方法并使用它:

public static String getHourString(Context ctx, int hours) {
   if (hours == 0) {
      return "";
   } else {
      return ctx.getResources().getQuantityString(R.plurals.hoursString, hours, hours);
   }
}

public static String getMinutesString(Context ctx, int mins) {
       if (mins == 0) {
          return "";
       } else {
          return ctx.getResources().getQuantityString(R.plurals.minutesString, mins, mins);
       }
    }

public static String getSecondsString(Context ctx, int secs) {
       if (secs == 0) {
          return "";
       } else {
          return ctx.getResources().getQuantityString(R.plurals.secondsString, secs, secs);
       }
    }

对于时间格式,有Java time formatting and Joda-Time has some help with date locale as well

虽然这是时间和日期格式。据我所知,您的方法(例如 1 分钟、1 秒)不是标准。对于您的方法,您必须使用 Locale Directories 并为您想要支持的每种语言创建一个字符串。虽然,由于您必须手动连接字符串,这可能对您没有太大帮助。