![](/img/trans.png)
[英]Formatter in DateTimeFormatter for ISO 8601 date format of the time
[英]Java 8 DateTimeFormatter rejects correct ISO 8601 date/time with offset
我使用DateTimeFormatter的格式字符串:uuuu-MM-dd'T'HH:mm:ssX
必須支持所有可能的時區偏移格式,包括:Z,00,00:00,0000
根據官方的DateTimeFormatter文檔,'X'限定符必須與這些格式的偏移匹配:
X區偏移'Z'表示零偏移-X Z; -08; -0830; -08:30; -083015; -08:30:15;
但事實上,事實並非如此
輸入字符串 :“2014-01-01T00:30:00 + 00:00”
result : java.time.format.DateTimeParseException:無法解析文本'2014-01-01T00:30:00 + 00:00',在索引22處找到未解析的文本
輸入字符串 :“2014-01-01T00:30:00Z”
結果 : 正確
編碼:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssX");
OffsetDateTime parsed = OffsetDateTime.parse(dateTimeAsString, formatter);
JDK 1.8.0_192(Oracle,而不是OpenJDK)
這有點復雜。 正如jvdmr所說 ,X的數量很重要。 XXXXX
將識別-08:30:15
,但不是-083015
。 XXXX
將承認后者,但不承認前者。
為了考慮所有可能的示例格式,我們需要指定不同的可能性。 這可以使用方括號在格式模式字符串中完成。 這些包含可選部件。 一些實驗表明,以下模式涵蓋了所有示例:
uuuu-MM-dd'T'HH:mm:ss[XXXXX][XXXX][X]
我們來試試吧:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[XXXXX][XXXX][X]");
for (String dts : new String[] {
"2014-01-01T00:30:00-08:30:15", "2014-01-01T00:30:00-083015",
"2014-01-01T00:30:00-08:30", "2014-01-01T00:30:00-0830",
"2014-01-01T00:30:00-08", "2014-01-01T00:30:00Z",
}) {
System.out.println(OffsetDateTime.parse(dts, formatter));
}
此代碼段的輸出是:
2014-01-01T00:30-08:30:15 2014-01-01T00:30-08:30:15 2014-01-01T00:30-08:30 2014-01-01T00:30-08:30 2014-01-01T00:30-08:00 2014-01-01T00:30Z
編輯
VelNaga建議不要對ISO日期時間格式進行硬編碼。 由於編寫格式模式字符串容易出錯,因此這可能是一個好主意。 例如:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.appendPattern("[XXXXX][XXXX][X]")
.toFormatter();
使用此格式化程序的輸出與使用上述格式化程序的輸出相同。 它更啰嗦,但我們很容易認為這是值得的,因為它不易出錯,可能更清晰,更容易閱讀。
從文檔 (強調我的) :
偏移X和x: 根據模式字母的數量格式化偏移。 一個字母僅輸出小時,例如'+01',除非分鍾非零,在這種情況下分鍾也輸出,例如'+0130'。 兩個字母輸出小時和分鍾,沒有冒號,例如'+0130'。 三個字母輸出小時和分鍾,帶有冒號,例如'+01:30'。 四個字母輸出小時和分鍾以及可選秒,沒有冒號,例如'+013015'。 五個字母輸出小時和分鍾,可選秒輸出冒號,例如'+01:30:15'。 六個或更多字母拋出IllegalArgumentException。 當要輸出的偏移量為零時,模式字母“X”(大寫)將輸出“Z”,而模式字母“x”(小寫)將輸出“+00”,“+ 0000”或“+00” :00' 。
這也適用於解析日期。 您想要使用和不使用冒號進行解析,這意味着您必須使用可選節,因為沒有單個模式支持此選項。 嘗試這種模式: "uuuu-MM-dd'T'HH:mm:ss[XXX][XXXX]"
不要硬編碼任何ISO日期格式。 DateFormatter已經有一個ISO日期格式轉換的靜態方法。 使用以下代碼,
DateTimeFormatter formatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
OffsetDateTime parsed = OffsetDateTime.parse(dateTimeAsString,formatter);
它肯定會起作用。 請在此鏈接中找到更多格式化程序選項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.