格式为“ M / dd / yy HH:mm:ss a z”的java.time.localdatetime格式为2018-11-26T15:12:03.000-0800的字符串引发异常

时间:2018-12-10 22:06:13

标签: java datetime datetime-format java-time datetime-parsing

i写了一个util函数,将格式为2018-11-26T15:12:03.000-0800的字符串时间值转换为格式为“ M / dd / yy HH:mm:ss a z”的localdatetime

格式为2018-11-26T15:12:03.000-0800的字符串转换为格式为“ M / dd / yy HH:mm:ss a z”的java.time.localdatetime转换引发异常。

public static LocalDateTime convertStringToTime(String time){
    String pattern = "M/dd/yy HH:mm z";
    DateTimeFormatter formatter =  DateTimeFormatter.ofPattern(pattern);
    ZonedDateTime zonedDateTime = ZonedDateTime.parse(time,formatter);
    return zonedDateTime.toLocalDateTime();
}

这给了我下面的例外情况

java.time.format.DateTimeParseException: Text '2018-11-26T12:45:23.000-0800' could not be parsed at index 4
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947)

1 个答案:

答案 0 :(得分:0)

您说要:LocalDateTime格式的M/dd/yy HH:mm:ss a z。由于以下三个原因,这是不可能的:

  1. LocalDateTime不能具有格式。它的toString方法总是返回类似2018-11-26T15:12:03(ISO 8601格式)的字符串,我们无法更改它。您也不要使用特定格式的LocalDateTime;我在底部包括一个链接,解释为什么不这样做。
  2. 我假设在您的格式中,z是指太平洋夏令时的时区缩写,例如PDTLocalDateTime都没有UTC偏移时间没有时区,所以这没有道理。
  3. 您输入的时间字符串也不包含任何时区,仅与UTC偏移。因此,要打印时区缩写,您首先需要选择一个时区。

相反,我建议:

    ZoneId zone = ZoneId.of("America/Whitehorse");
    DateTimeFormatter inputFormatter
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXX");
    DateTimeFormatter desiredFormatter
            = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.LONG)
                    .withLocale(Locale.US);

    String time = "2018-11-26T15:12:03.000-0800";
    OffsetDateTime dateTime = OffsetDateTime.parse(time, inputFormatter);
    String formattedDateTime = dateTime.atZoneSameInstant(zone)
            .format(desiredFormatter);

    System.out.println("Converted format: " + formattedDateTime);

输出为:

  

转换后的格式:太平洋标准时间11/26/18,3:12:03

要将日期和时间从一种格式的字符串转换为另一种格式的字符串,通常需要两个DateTimeFormatter:一个用于指定您拥有的字符串的格式,另一个用于指定所需的格式。

而不是根据格式模式字符串构建自己的格式程序,而是尽可能使用内置格式。在我们的情况下,我将FormatStyle.SHORT指定为日期(给出两位数的年份),并将FormatStyle.LONG指定为时间,为我们提供时区缩写。

依赖内置格式的想法可以更进一步。您输入的字符串为ISO 8601格式,因此我们只需要将两部分拼凑在一起:

    DateTimeFormatter inputFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .appendOffset("+HHmm", "Z")
            .toFormatter();

更长,但更不容易出错。

链接