本文介紹了為什么使用DateTimeForMatter進行日期解析會根據Java版本不同而產生不同的結果的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
相同的日期分析代碼顯示不同的結果,具體取決于我使用的是Java 8還是Java 11。
以下是重現該問題的代碼示例:
public static void main(String[] args) {
DateTimeFormatterBuilder dfBuilder = new DateTimeFormatterBuilder()
.appendPattern("uuuu-M-d")
.optionalStart()
.optionalStart().appendLiteral(' ').optionalEnd()
.optionalStart().appendLiteral('T').optionalEnd()
.appendValue(ChronoField.HOUR_OF_DAY)
.optionalStart()
.appendLiteral(':')
.appendValue(ChronoField.MINUTE_OF_HOUR)
.optionalStart()
.appendLiteral(':')
.appendValue(ChronoField.SECOND_OF_MINUTE)
.optionalStart()
.appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, true)
.optionalEnd()
.optionalEnd()
.optionalEnd()
.appendPattern("[XXXXX][XXXX][XXX][XX][X]")
.optionalEnd();
DateTimeFormatter df = dfBuilder.toFormatter(Locale.FRANCE).withZone(ZoneId.of("Europe/Paris"));
TemporalAccessor temporalAccessor = df.parse("1970-01-01T00:00:00.00Z");
Instant instantTime = Instant.from(temporalAccessor);
long epochTimestamp = instantTime.getEpochSecond();
System.out.println(epochTimestamp);
}
在Java 8上,輸出為-3600。
而在Java 11上,輸出為0(這是我預期的值)。
根據我的分析,其來源是使用";with Zone()";方法,如果我刪除它,它對于包含區域數據的日期將按預期工作。
但同樣,此行為在所有DateTimeForMatter上并不相同:例如,如果我使用此格式化程序:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd HH:mm:ss")
.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
.optionalStart()
.appendZoneId()
.optionalEnd()
.toFormatter()
.withZone(ZoneId.of("Europe/Paris"));
在日期內出現的情況下會很好地考慮zoneID(盡管調用了";with Zone())。
因此,我認為第一個格式化程序有問題,Java 11上的默認行為有助于它在Java 11上按預期工作,但在Java 8上不能。
我還明確表示,我的目標是讓它在Java 8上運行。
推薦答案
已知錯誤
這是Java 8中的已知錯誤。Parsing with DateTimeFormatter.withZone does not behave as described in javadocs。
有趣的是,我鏈接到的Java Bugs系統中的錯誤報告沒有提到修復版本。它確實提到了該錯誤不是在JDK 9-EA中出現的:
要重現該問題,請運行附加的測試用例。它在JDK上失敗
8u121,但在JDK 9-EA中通過。
這篇關于為什么使用DateTimeForMatter進行日期解析會根據Java版本不同而產生不同的結果的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,