解决 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