簡體   English   中英

在 Java 中將字符串轉換為 LocalDateTime

[英]Convert String to LocalDateTime in Java

我有這個字符串

2020 年 8 月 7 日星期五 18:00:00 +0000

我需要將其轉換為 LocalDateTime

我嘗試了幾種方法:

創建一個 DateTimeFormatter 並解析字符串

String dateString = "Fri, 07 Aug 2020 18:00:00 +0000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("E, dd MMM yyyy HH:mm:ss", Locale.getDefault());
LocalDateTime parsedDate = LocalDateTime.parse(publishedString, formatter);

使用 SimpleDateFormat 將其轉換為 Date,然后將 resultDate 轉換為 LocalDateTime

String dateString = "Fri, 07 Aug 2020 18:00:00 +0000";
SimpleDateFormat dateFormatter = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss Z");
Date date = dateFormatter.parse(publishedString);
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

兩種解決方案都給了我同樣的例外:

java.time.format.DateTimeParseException: Text 'Fri, 07 Aug 2020 18:00:00 +0000' could not be parsed 
at index 0 at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)

如何轉換該字符串?

tl;博士

OffsetDateTime.parse( 
    "Fri, 07 Aug 2020 18:00:00 +0000" , 
    DateTimeFormatter.RFC_1123_DATE_TIME 
)

請參閱在 IdeOne.com 上實時運行的代碼

LocalDateTime是錯誤的 class

您的輸入字符串包含+0000 ,表示與 UTC 的偏移量。

所以你不應該使用LocalDateTime class 故意缺少任何時區或偏移量的概念。 使用LocalDateTime ,您的字符串Fri, 07 Aug 2020 18:00:00 +0000將在 2020 年 8 月 7 日變為 6M,但我們不知道那是日本東京的下午 6 點,法國圖盧茲的下午 6 點,還是法國的下午 6 點美國俄亥俄州托萊多——所有不同的時刻相隔幾個小時。

OffsetDateTime

相反,這個值應該被解析為OffsetDateTime

解析

您輸入的格式是RFC 1123的格式。 該特定格式在java.time中預定義。

String input = "Fri, 07 Aug 2020 18:00:00 +0000";
DateTimeFormatter f = DateTimeFormatter.RFC_1123_DATE_TIME;
OffsetDateTime odt = OffsetDateTime.parse( input , f );

odt.toString(): 2020-08-07T18:00Z

我了解您需要 API 的LocalDateTime ,由於您無法控制的設計問題,您正在嘗試在某個時間點使用LocalDateTime

如果外部合同規定要理解LocalDateTime的時區或 UTC 偏移量,則可以使LocalDateTime工作,至少在 99.977 % 的情況下。 在某些同事程序員不閱讀合同的那一天,您仍然會等待發生編程錯誤,這是我們無法在代碼中解決的問題,只能嘗試通過良好的注釋來緩解。

例如,如果合約顯示 UTC,那么我們需要確保將時間轉換為 UTC。 為此,我們需要字符串的偏移量。

    ZoneOffset contractualOffset = ZoneOffset.UTC;
    String stringWeveGot = "Fri, 07 Aug 2020 18:00:00 +0000";
    LocalDateTime convertedDateTime = OffsetDateTime
            .parse(stringWeveGot, DateTimeFormatter.RFC_1123_DATE_TIME)
            .withOffsetSameInstant(contractualOffset)
            .toLocalDateTime();
    System.out.println(convertedDateTime);

Output:

2020-08-07T18:00

如果要求字符串中的偏移量已經為 0,則需要驗證它是否為 0,否則錯誤會被 go 忽略,用戶會得到錯誤的結果。 例如:

    OffsetDateTime parsedOdt = OffsetDateTime
            .parse(stringWeveGot, DateTimeFormatter.RFC_1123_DATE_TIME);
    if (! parsedOdt.getOffset().equals(contractualOffset)) {
        throw new IllegalStateException("Offset must be " + contractualOffset
                + ", was " + parsedOdt.getOffset());
    }
    LocalDateTime convertedDateTime = parsedOdt.toLocalDateTime();

如果合同提到某個時區,則轉換為該時區。 我以澳大利亞/維多利亞為例。

    ZoneId contractualZone = ZoneId.of("Australia/Victoria");
    String stringWeveGot = "Fri, 07 Aug 2020 18:00:00 +0000";
    LocalDateTime convertedDateTime = OffsetDateTime
            .parse(stringWeveGot, DateTimeFormatter.RFC_1123_DATE_TIME)
            .atZoneSameInstant(contractualZone)
            .toLocalDateTime();
    System.out.println(convertedDateTime);

2020-08-08T04:00

在時鍾倒轉的時間異常情況下,您將得到一個模棱兩可的結果,例如在夏令時 (DST) 結束時的倒退

你的代碼出了什么問題?

此處解釋了您的異常的原因:

我會說使用 Locale.ROOT 並且不要忘記 DateTimeFormatter class 中的 Z

String dateString = "Fri, 07 Aug 2020 18:00:00 +0000";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("E, dd MMM yyyy HH:mm:ss Z", Locale.ROOT);
LocalDateTime parsedDate = LocalDateTime.parse(dateString, formatter);

暫無
暫無

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

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