修復 DateTimeParseException:“無法從 TemporalAccessor 取得 LocalDateTime”
1.概述
使用java.time套件在 Java 中處理日期和時間非常高效,但有時我們可能會遇到DateTimeParseException錯誤,並顯示訊息「 Unable to obtain LocalDateTime from TemporalAccessor 」。此問題通常是由於預期的日期時間格式和實際輸入不相容而引起的。
本文解釋了此異常發生的原因,探討了其常見原因,並提供了預防和修復此異常的有效策略。
2. 理解異常
當 Java 的日期時間解析器無法從TemporalAccessor提取有效的LocalDateTime物件(例如LocalDate 、 ZonedDateTime或OffsetDateTime時,會發生“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列舉代表一週中的某一天(例如MONDAY 、 FRIDAY ),但它不包含任何日期或時間資訊。嘗試直接將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錯誤「 Unable to obtain LocalDateTime from TemporalAccessor 」通常是由於缺少或格式不正確的日期時間訊息,或時區處理不當而發生的。
為了避免此錯誤,我們應該確保輸入格式符合預期模式並使用適當的 Java 日期時間類別( LocalDate 、 LocalDateTime 、 ZonedDateTime或OffsetDateTime ) 。
透過遵循這些最佳實踐,可以有效地解析和管理日期時間值而不會出現錯誤。
像往常一樣,這裡討論的程式碼可以在 GitHub 上找到。