解决 DateTimeParseException: “Unable to obtain LocalDateTime from TemporalAccessor” 异常
1、概览
在 Java 中使用 java.time 包处理日期和时间非常高效,但有时我们可能会遇到 DateTimeParseException 异常,提示 “Unable to obtain LocalDateTime from TemporalAccessor(无法从 TemporalAccessor 获取 LocalDateTime)”。出现这种问题的原因通常是预期的日期时间格式与实际输入不兼容。
本文将带你了解出现该异常的原因以及解决办法。
2、理解异常
当 Java 的日期时间解析器无法从 TemporalAccessor(如 LocalDate、ZonedDateTime 或 OffsetDateTime)中提取有效的 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 会导致异常。
为了解决这个问题,可以将 LocalTime 与 LocalDate 结合起来,形成一个完整的 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 日期时间类(LocalDate、LocalDateTime、ZonedDateTime 或 OffsetDateTime)。
Ref:https://www.baeldung.com/java-datetimeparseexception-localdatetime-temporalaccessor