3

有人知道如何从看起来像“01:20”-> 1:20AM 和“21:20”-> 9:20PM 的字符串中解析时间(小时、分钟和 AM/PM)吗?大多数解决方案似乎都假设或需要一个 Date 或 Calendar 对象。

我的输入时间实际上来自 TimePickerDialog(具体来说,这个 MaterialDateTimePicker 实现,所以我只收到 hourOfDay、分钟和秒(整数)。

我希望能够以友好的方式格式化用户选择的时间,即 12:30 PM、02:15 AM 等。

我正在尝试使用 Joda Time:

fun formattedTime(timeStr: String): String {
    // Get time from date
    val timeFormatter = DateTimeFormat.forPattern("h:mm a")
    val displayTime = timeFormatter.parseLocalTime(timeStr)
    return displayTime.toString()
}

但我在输入字符串(例如“1:20”)时收到此错误: java.lang.IllegalArgumentException: Invalid format: "1:20" is too short

我也研究过SimpleDateFormat但它似乎需要一个完整的日期时间字符串,例如在这个相关问题中

4

3 回答 3

6

正如@ole-vv 指出的那样,SimpleDateFormat已经看到了更好的日子 - 所以今天你可以利用 java.time 包来完成这项工作:

java.time.format.DateTimeFormatter target2 = 
     java.time.format.DateTimeFormatter.ofPattern("h:mm a");
java.time.format.DateTimeFormatter source2 = 
     java.time.format.DateTimeFormatter.ofPattern("HH:mm");

System.out.println("01:30 -> " + target2.format(source2.parse("01:30")));
System.out.println("21:20 -> " + target2.format(source2.parse("21:20")));

产生的结果

01:30 -> 1:30 AM
21:20 -> 9:20 PM

正如预期的那样。

在 Joda-Time 中,您可以将其编码为 @meno-hochschild 在下面的回答中指出的那样。

使用SimpleDateFormat它看起来像这样:

    SimpleDateFormat target = new SimpleDateFormat("h:mm a");
    SimpleDateFormat source = new SimpleDateFormat("HH:mm");
    System.out.println("01:30 -> " + target.format(source.parse("01:30")));
    System.out.println("21:20 -> " + target.format(source.parse("21:20")));

这将从 24 小时解析到 12 小时显示

    01:30 -> 1:30 AM
    21:20 -> 9:20 PM      

这一切都取决于小时的格式 - 对于解析,您需要 24 小时(格式 HH),对于输出,您需要 12 小时加上 am / pm - 格式是 h。

如果您希望 01:30 成为 PM,则必须将其添加到要以某种方式解析的字符串中:

   System.out.println("01:30 pm-> " + target.format(target.parse("01:30 pm")));

导致

   01:30 pm-> 1:30 PM
于 2018-04-18T09:27:42.360 回答
2

接受的答案是正确的。但是,我很惊讶地看到旧课程,SimpleDateFormat尽管 OP 已经明确首先需要 Joda 答案(请参阅问题的标签)。所以我在这里发布 Joda 的答案作为补充:

DateTimeFormatter target = DateTimeFormat.forPattern("h:mm a").withLocale(Locale.ENGLISH);
DateTimeFormatter source = DateTimeFormat.forPattern("HH:mm");
System.out.println("01:30 -> " + target.print(source.parseLocalTime("01:30")));
System.out.println("21:20 -> " + target.print(source.parseLocalTime("21:20")));

01:30 -> 1:30 AM
21:20 -> 9:20 PM

我建议不要混合两个不同的时间库(OP 显然使用 Joda-Time-Android)。

于 2018-04-18T14:18:55.607 回答
1

您的两个不错的选择是 Joda-Time 和java.time.

由于您从时间选择器收到小时、分钟和秒作为整数,因此您不需要进行任何解析。

java.time

    DateTimeFormatter timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
            .withLocale(Locale.US);
    LocalTime time = LocalTime.of(hourOfDay, minute, second);
    String displayTime = time.format(timeFormatter);
    System.out.println(displayTime);

这会像这样打印时间:

晚上 11:45

我依赖于美国语言环境的内置本地化格式,而不是显式格式模式字符串。PM它在分钟和(或AM)之间放置了一个空格。我相信您的用户会对此感到高兴。如果没有,您将需要DateTimeFormatter.ofPattern("h:mma", Locale.US)改用。

乔达时间

如果您已经在使用 Joda-Time 并且此时没有改变的理由,那么坚持使用它是合理的。您可以使用LocalTime(int hourOfDay, int minuteOfHour, int secondOfMinute)构造函数。然后按照Meno Hochschild 的回答进行。这是一个很好且知识渊博的答案。

请注意,Joda-Time 被认为是一个基本上“完成”的项目。没有计划进行重大改进。如果使用 Java SE 8,请迁移到java.time(JSR-310)。

(引自Joda-Time 主页

远离 SimpleDateFormat

远离SimpleDateFormat课堂。它可以为工作而工作,但它不仅过时了,而且出了名的麻烦。

问题:我可以在 Android 上使用 java.time 吗?

是的,java.time在较旧和较新的 Android 设备上运行良好。它只需要至少 Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备上(我听说从 API 级别 26 开始),现代 API 是内置的。
  • 在 Java 6 和 7 中获得 ThreeTen Backport,即新类的后向端口(对于 JSR 310,ThreeTen;请参阅底部的链接)。
  • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。并确保从org.threeten.bp子包中导入日期和时间类。

链接

于 2018-04-19T10:02:30.700 回答