Java 11 无法在索引 20 处解析 DateTimeParseException

Java 11 DateTimeParseException could not be parsed at index 20

我正在尝试将字符串转换为 Java 中的 Date 对象 11. 下面的代码给出了异常。尝试了不同的方法,到目前为止没有运气。任何解决此错误消息的帮助?

String date = 'Mon Aug 02 16:33:10 EDT 2021'
OffsetDateTime odt = OffsetDateTime.now( ZoneId.systemDefault() ) ;
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy").toFormatter().ofLocalizedDateTime(FormatStyle.LONG) .withZone(odt.getOffset());
LocalDateTime  localDateTime = LocalDateTime.parse(date, formatter);
System.out.println(localDateTime);
System.out.println(formatter.format(localDateTime));

错误

Exception in thread "main" java.time.format.DateTimeParseException: Text 'Mon Aug 02 16:33:10 EDT 2021' could not be parsed at index 20
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
    at java_time_LocalDateTime$parse.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)

使用模式,EEE MMM dd HH:mm:ss z yyyy

此外,由于您有时区而不是日期时间字符串中的偏移量,因此您应该使用 ZonedDateTime 而不是 OffsetDateTime

import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        String strDate = "Mon Aug 02 16:33:10 EDT 2021";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy");
        ZonedDateTime zdt = ZonedDateTime.parse(strDate, formatter);
        System.out.println(zdt);

        LocalDateTime ldt = zdt.toLocalDateTime();
        System.out.println(ldt);
    }
}

输出:

2021-08-02T16:33:10-04:00[America/New_York]
2021-08-02T16:33:10

注():ZonedDateTime转换成LocalDateTime几乎肯定是没有意义的。这种转换会丢弃有价值的信息,即时区,而不会增加任何价值。

好的 IDE 会对您尝试编译的代码产生警告。例如,Eclipse 警告

The static method ofLocalizedDateTime(FormatStyle) from the type DateTimeFormatter should be accessed in a static way

Java 允许您通过引用表达式访问 class 的 static 成员。不过,大家一致认为您 should not 只是忽略了语言功能。

针对您的具体情况,

new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy")
            .toFormatter()
            .ofLocalizedDateTime(FormatStyle.LONG)
            .withZone(odt.getOffset());

静态 DateTimeFormatter#ofLocalizedDate(FormatStyle) 是在 DateTimeFormatter 类型的引用表达式 [...].toFormatter() 上调用的。您似乎认为它是在实际的 DateTimeFormatter 实例上调用的,但实际上它只是一个 static 方法调用。 .toFormatter() 返回的实例被丢弃。您的代码本质上等同于

new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy")
            .toFormatter(); // thrown away

DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
            .withZone(odt.getOffset());

换句话说,您的 formatter 具有 ofLocalizedDateTime 选择的格式,而不是您尝试使用的 "E MMM d H:m:s z yyyy"。据推测,对于您的默认 Locale,该格式无法解析您的日期字符串。

不清楚您是否打算使用该方法。如果您知道具有适当格式的相应语言环境,则可以跳过您的自定义模式并只使用选定的模式

Locale currentLocale = /* whatever is appropriate */;
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
         .withLocale(currentLocale);

然后解析你的日期字符串。

否则,完全忽略该方法,只使用您提供的模式和时区构建您的 DateTimeFormatter

DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("E MMM d H:m:s z yyyy")
                .toFormatter()
                .withZone(odt.getOffset());

您可以从 DateTimeFormatter class javadoc 看出您的模式字符串

E MMM d H:m:s z yyyy

可以正确解析您的日期字符串

Mon Aug 02 16:33:10 EDT 2021

无关,你确定LocalDateTime是你需要的吗?您实际上丢失了原始字符串中的时区信息 (EDT)。此外,提供给 withZoneZoneId 将被忽略以解析为 LocalDateTime.

在我的例子中,我解析的日期字符串有小写的 am/pm,像这样

May 12 2021 at 3:31 pm

我必须先将 'pm' 转换为 'PM',然后使用格式化程序 DateTimeFormatter.ofPattern("MMMM d yyyy 'at' h:mm a");