java.time.format.DateTimeParseException:无法在索引处解析文本
这看起来是一件非常简单的事情,但我没有这样做。
我有一个字符串模式,yyyyMMddHH我正在尝试解析2021061104为LocalDateTime
这是代码:
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
class Main {
public static void main(String[] args) {
String pattern = "yyyyMMddHH";
String date = "2021061104";
DateTimeFormatter formatter =
new DateTimeFormatterBuilder()
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.parseLenient()
.appendPattern(pattern)
.toFormatter();
LocalDateTime ldt = LocalDateTime.parse(date, formatter);
}
}
它抛出这个异常:
Exception in thread "main" java.time.format.DateTimeParseException: Text '2021061104' could not be parsed at index 8
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.LocalDateTime.parse(LocalDateTime.java:492)
at Main.main(Main.java:22)
无法HH从输入解析字段。
我在这里查看了 javadoc但这无济于事。
为什么我有这个例外?如何解决这个问题?
编辑:
我无法删除 .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
以下是限制条件:
- 用户将给出
pattern和date(可能是args[0]和args[1]) - 模式必须始终有日期(年月和日期)
- 中的时间
pattern是可选的,最多只能是小时。 - 一对夫妇合法的模式的例子有:
yyyy-MM-dd HH,yyyy MM dd
有了这些限制,我无法删除,.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)因为如果我这样做,我将无法解析yyyy-MM-dd到这里的实例LocalDateTime
回答
好吧,我认为这是由.parseDefaulting(ChronoField.HOUR_OF_DAY, 0). 在进行任何解析之前,构建器会立即插入一个默认值。解析的时候,hour组件已经有了值,所以解析HH失败。
JavaDocs 中实际上提到了这种行为:
在解析过程中,会检查解析的当前状态。如果指定的字段没有关联值,因为在那个时候还没有被成功解析,那么指定的值被注入到解析结果中。注入是即时的,因此字段值对将对 formatter 中的任何后续元素可见。因此,通常在构建器的末尾调用此方法。
强调我的。
因此,可能的解决方法是将parseDefaulting行移动到格式化程序构建器的末尾:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseLenient()
.appendPattern(pattern)
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
.toFormatter();
这是一个工作示例,将这些行移动到构建器的末尾。
THE END
二维码