如何从字符串中解析时间(小时,分钟)?

时间:2018-04-18 09:23:04

标签: java jodatime datetime-format android-jodatime

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

我的输入时间实际上来自TimePickerDialog(特别是this MaterialDateTimePicker implementation,因此我只收到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,但它似乎需要一个完整的日期时间字符串,例如this related question

3 个答案:

答案 0 :(得分:4)

正如@ ole-v-v所指出的那样,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小时加上午/小时 - 格式为h。

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

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

导致

   01:30 pm-> 1:30 PM

答案 1 :(得分: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     21:20 - >晚上9:20

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

答案 2 :(得分:1)

你的两个好选择是Joda-Time和java.time

由于您从时间选择器接收hourOfDay,minute和seconds作为整数,因此您无需进行任何解析。

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’s answer进行操作。这是一个很好且知识渊博的答案。

  

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

(引自the Joda-Time homepage

远离SimpleDateFormat

远离SimpleDateFormat课程。它可以用于工作,但它不仅已经过时,而且也是出了名的麻烦。

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

是的,java.time适用于较旧和较新的Android设备。它只需要至少Java 6

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

链接