首页 > 解决方案 > 无法在索引 20 处解析 Java 11 DateTimeParseException

问题描述

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

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)

标签: javajava-time

解决方案


一个好的 IDE 会为您尝试编译的代码生成警告。例如,Eclipse 警告

ofLocalizedDateTime(FormatStyle)类型中的静态方法DateTimeFormatter应该以静态方式访问

Java 允许您通过引用表达式访问static类的成员。尽管如此,大家还是一致认为你不应该,而只是忽略语言特性。

对于您的具体情况,

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

在类型为DateTimeFormatter#ofLocalizedDate(FormatStyle)的引用表达式上调用静态。您似乎认为它是在实际实例上调用的,但实际上它只是一个方法调用。返回的实例被丢弃。您的代码本质上等同于[...].toFormatter()DateTimeFormatterDateTimeFormatterstatic.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"您尝试使用的格式。据推测,对于您的 default 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());

您可以从DateTimeFormatterjavadoc 类中看出您的模式字符串

E MMM d H:m:s z yyyy

可以适当地解析您的日期字符串

Mon Aug 02 16:33:10 EDT 2021

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


推荐阅读