簡體   English   中英

解析 LocalDateTime (Java 8) 時無法從 TemporalAccessor 獲取 LocalDateTime

[英]Unable to obtain LocalDateTime from TemporalAccessor when parsing LocalDateTime (Java 8)

我只是想在 Java 8 中將日期字符串轉換為 DateTime 對象。運行以下幾行:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime dt = LocalDateTime.parse("20140218", formatter);

我收到以下錯誤:

Exception in thread "main" java.time.format.DateTimeParseException: 
Text '20140218' could not be parsed: 
Unable to obtain LocalDateTime from TemporalAccessor: 
{},ISO resolved to 2014-02-18 of type java.time.format.Parsed
    at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1918)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1853)
    at java.time.LocalDateTime.parse(LocalDateTime.java:492)

語法與這里建議的相同,但我遇到了一個例外。 我正在使用JDK-8u25

事實證明,Java 不接受裸 Date 值作為 DateTime。 使用 LocalDate 而不是 LocalDateTime 解決了這個問題:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate dt = LocalDate.parse("20140218", formatter);

如果您確實需要將日期轉換為 LocalDateTime 對象,則可以使用 LocalDate.atStartOfDay()。 這將為您提供指定日期的 LocalDateTime 對象,將小時、分鍾和秒字段設置為 0:

final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDateTime time = LocalDate.parse("20140218", formatter).atStartOfDay();

如果有人應該再次閱讀這個主題(像我一樣),那么正確的答案將在DateTimeFormatter定義中,例如:

private static DateTimeFormatter DATE_FORMAT =  
            new DateTimeFormatterBuilder().appendPattern("dd/MM/yyyy[ [HH][:mm][:ss][.SSS]]")
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
            .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
            .toFormatter(); 

如果它們會出現,應該設置可選字段。 其余代碼應該完全相同。

編輯:來自wittyameta評論的有用的東西:

請記住在調用 appendPattern 之后添加 parseDefaulting。 否則它會給出 DateTimeParseException

對於遇到此錯誤的任何人,就像我一樣:

Unable to obtain LocalDateTime from TemporalAccessor: {HourOfAmPm=0, MinuteOfHour=0}

它來自以下行:

LocalDateTime.parse(date, DateTimeFormatter.ofPattern("M/d/yy h:mm"));

事實證明,這是因為我在 0 小時上使用了 12 小時模式,而不是 24 小時模式。

通過使用大寫 H 將小時模式更改為 24 小時模式來修復它:

LocalDateTime.parse(date, DateTimeFormatter.ofPattern("M/d/yy H:mm"));

這是一個非常不清楚且無用的錯誤消息。 經過多次反復試驗,我發現如果您不嘗試解析時間, LocalDateTime會出現上述錯誤。 通過使用LocalDate ,它可以正常工作而不會出錯。

這沒有得到很好的記錄,相關的異常也非常無用。

擴展追溯的答案..:即使使用LocalDate而不是LocalDateTime我也遇到了同樣的問題。 問題是我使用.withResolverStyle(ResolverStyle.STRICT);創建了我的DateTimeFormatter ,所以我不得不使用日期模式uuuuMMdd而不是yyyyMMdd (即“年”而不是“時代”)!

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
  .parseStrict()
  .appendPattern("uuuuMMdd")
  .toFormatter()
  .withResolverStyle(ResolverStyle.STRICT);
LocalDate dt = LocalDate.parse("20140218", formatter);

(這個解決方案最初是對retrography答案的評論,但我被鼓勵將它作為一個獨立的答案發布,因為它顯然對很多人都非常有效。)

如果日期字符串不包含小時、分鍾等的任何值,則不能直接將其轉換為LocalDateTime 您只能將其轉換為LocalDate ,因為該字符串表示年、月和日期組件,這是正確的做法。

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate ld = LocalDate.parse("20180306", dtf); // 2018-03-06

無論如何,您可以將其轉換為LocalDateTime

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate ld = LocalDate.parse("20180306", dtf);
LocalDateTime ldt = LocalDateTime.of(ld, LocalTime.of(0,0)); // 2018-03-06T00:00

您不需要定義DateTimeFormatter

您不需要定義DateTimeFormatter來解析給定的日期字符串。 您可以使用 OOTB (Out-Of-The-Box)、 DateTimeFormatter.BASIC_ISO_DATE來解析它。

演示:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        LocalDate date = LocalDate.parse("20140218", DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(date);

        // In case you need an instance of LocalDateTime
        LocalDateTime ldt = date.atTime(LocalTime.MIN);
        System.out.println(ldt);
    }
}

輸出:

2014-02-18
2014-02-18T00:00

在線演示

Trail: Date Time了解有關現代日期時間 API *的更多信息。


* 如果您正在為一個 Android 項目工作,並且您的 Android API 級別仍然不符合 Java-8,請 通過 desugaring 檢查可用的 Java 8+ API 請注意,Android 8.0 Oreo 已經提供了java.time的支持 檢查此答案此答案以了解如何將java.time API 與 JDBC 一起使用。

這工作正常

public class DateDemo {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy hh:mm");
        String date = "16-08-2018 12:10";
        LocalDate localDate = LocalDate.parse(date, formatter);
        System.out.println("VALUE="+localDate);

        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm");
        LocalDateTime parse = LocalDateTime.parse(date, formatter1);
        System.out.println("VALUE1="+parse);
    }
}

輸出:

VALUE=2018-08-16
VALUE1=2018-08-16T12:10
 DateTimeFormatter format = new DateTimeFormatterBuilder()
                            .appendPattern("yyyy-MM-dd")
                            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                            .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                            .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                            .parseDefaulting(ChronoField.MILLI_OF_SECOND, 0)
                            .toFormatter();

為我工作

如果您只是想采用一種格式(無論它是否有時間)並想解析為 LocalDateTime,您可以執行以下操作。

LocalDateTime parseDateTime(String dateTime, DateTimeFormatter fmt) {
  return fmt.parse(dateTime, t -> {
    LocalDate date = t.query(TemporalQueries.localDate());
    LocalTime time = t.query(TemporalQueries.localTime());
    return LocalDateTime.of(date, time != null ? time : LocalTime.MIDNIGHT);
  });
}

我需要這個,因為我將日期/時間模式作為自定義 Spark UDF 的參數。

試試這個:

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM-dd-yyyy"); 
LocalDate fromLocalDate = LocalDate.parse(fromdstrong textate, dateTimeFormatter);

您可以添加任何您想要的格式。 這對我行得通!

我遇到了這個問題,因為我的輸入字符串沒有年份:

輸入字符串: Tuesday, June 8 at 10:00 PM
formatter: DateTimeFormatter.ofPattern("EEEE, MMMM d 'at' h:mm a", Locale.US);

我知道年份,所以我只是將其附加到:

輸入字符串: Tuesday, June 8 at 6:30 PM 2021
formatter: DateTimeFormatter.ofPattern("EEEE, MMMM d 'at' h:mm a uuuu", Locale.US);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM