修復 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 上找到。