解决 DateTimeParseException: “Unable to obtain LocalDateTime from TemporalAccessor” 异常

1、概览

在 Java 中使用 java.time 包处理日期和时间非常高效,但有时我们可能会遇到 DateTimeParseException 异常,提示 “Unable to obtain LocalDateTime from TemporalAccessor(无法从 TemporalAccessor 获取 LocalDateTime)”。出现这种问题的原因通常是预期的日期时间格式与实际输入不兼容。

本文将带你了解出现该异常的原因以及解决办法。

2、理解异常

当 Java 的日期时间解析器无法从 TemporalAccessor(如 LocalDateZonedDateTimeOffsetDateTime)中提取有效的 LocalDateTime 对象时,就会出现 “Unable to obtain LocalDateTime from TemporalAccessor” 异常。根本原因通常是输入字符串格式不当或不完整

LocalDateTime 需要 日期时间 两个部分。如果输入字符串缺少所需的部分或不符合预期的格式,解析过程就会失败,从而产生此异常。很多人认为 Java 可以自动推断缺少的时间值,但事实并非如此。

示例如下,解析一个日期字符串为 LocalDateTime 的错误例子:

public static void main(String[] args) {
    String dateTimeStr = "20250327";  // 只有日期,没时间
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
    LocalDateTime localDateTime = LocalDateTime.parse(dateTimeStr, formatter);
}

执行该代码时,会出现以下异常:

java.time.format.DateTimeParseException: Text '20250327' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {},ISO resolved to 2025-03-27 of type java.time.format.Parsed

出现错误的原因是 LocalDateTime 要求同时输入日期和时间,但输入内容只包含日期。

3、常见原因和解决方案

java.time API 严格执行格式规则,这意味着任何偏差,如缺少时间成分、格式不正确或意外时区,都会触发异常。

3.1、输入字符串中缺少时间部分

当输入字符串只包含日期(如 2024-03-25),但被解析为 LocalDateTime 时,解析会失败,因为 LocalDateTime 需要日期和时间部分。这将导致 DateTimeParseException 异常。

要解决这个问题,可以将日期解析为 LocalDate,而不是 LocalDateTime

LocalDate date = LocalDate.parse("2024-03-25", DateTimeFormatter.ISO_LOCAL_DATE);

或者,如果我们需要 LocalDateTime,可以在输入字符串中附加一个默认时间值,例如 T00:00:00

String dateTimeStr = "2024-03-25T00:00:00";
LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ISO_LOCAL_DATE_TIME);

3.2、将 DayOfWeek 解析为 LocalDateTime

DayOfWeek 枚举表示一周中的某一天(如星期一、星期五),但不包括任何日期或时间信息。如果试图将 DayOfWeek 当作 LocalDateTime,则会出现异常,因为 LocalDateTime 需要日期和时间。

如果需要一个特定工作日的完整 LocalDateTime,则可以确定该日的下一次出现时间,并将其与所选时间相结合:

DayOfWeek targetDay = DayOfWeek.FRIDAY;
LocalDate today = LocalDate.now();
LocalDate nextTargetDate = today.with(TemporalAdjusters.next(targetDay));

LocalTime time = LocalTime.of(14, 30);
LocalDateTime dateTime = LocalDateTime.of(nextTargetDate, time);

这种方法可确保我们正确地将 DayOfWeek 值与实际日期相关联,然后再将其与时间相结合,形成有效的 LocalDateTime

3.3、将 LocalTime 解析为 LocalDateTime

当输入字符串只包含时间(如 14:30:00)并被解析为 LocalDateTime 时,由于 LocalDateTime 需要同时包含日期和时间部分,因此会失败。LocalTime 只提供时间部分,因此将其解析为 LocalDateTime 会导致异常。

为了解决这个问题,可以将 LocalTimeLocalDate 结合起来,形成一个完整的 LocalDateTime

LocalDate date = LocalDate.of(2024, 3, 25);
LocalTime time = LocalTime.parse("14:30:00");
LocalDateTime dateTime = LocalDateTime.of(date, time);

3.4、将 YearMonth 解析为 LocalDateTime

YearMonth 类只表示年和月,没有任何具体的日期或时间信息。因此,尝试将 YearMonth 作为 LocalDateTime 解析会失败,因为 LocalDateTime 需要完整的日期和时间。

为了解决这个问题,我们可以使用 YearMonth 类来进行只需年和月的操作。或者,如果我们需要一个完整的 LocalDateTime,我们可以将 YearMonth 与特定的日期和时间结合起来:

YearMonth yearMonth = YearMonth.parse("2024-03", DateTimeFormatter.ofPattern("yyyy-MM"));
LocalDate date = yearMonth.atDay(1);
LocalTime time = LocalTime.of(14, 30);
LocalDateTime dateTime = LocalDateTime.of(date, time);

3.5、解析 MonthDay 为 LocalDateTime

MonthDay 类只表示月和日(例如 “03-25”),不包括年或时间成分。将 MonthDay 作为 LocalDateTime 解析失败,因为 LocalDateTime 需要完整的日期和时间。

为了解决这个问题,如果只需要月和日,我们可以使用 MonthDay。或者,如果我们需要 LocalDateTime,我们可以将 MonthDay 与特定的年份和时间相结合:

MonthDay monthDay = MonthDay.parse("03-25", DateTimeFormatter.ofPattern("MM-dd"));
LocalDate date = LocalDate.of(2024, monthDay.getMonth(), monthDay.getDayOfMonth());
LocalTime time = LocalTime.of(14, 30);
LocalDateTime dateTime = LocalDateTime.of(date, time);

4、总结

DateTimeParseException 异常 “nable to obtain LocalDateTime from TemporalAccessor” 通常是由于日期时间信息丢失或格式不正确,或时区处理不当造成的。

为避免此错误,应确保输入格式符合预期模式,并使用适当的 Java 日期时间类(LocalDateLocalDateTimeZonedDateTimeOffsetDateTime)。


Ref:https://www.baeldung.com/java-datetimeparseexception-localdatetime-temporalaccessor