2016-08-11 29 views
1

java.time類中,我們如何指定DateTimeFormatter的格式化模式,以允許FULL STOP(.)(句點或點)或COMMA (,)作爲分數秒的分隔符?`DateTimeFormatter`在小數秒內處理FULL STOP或者COMMA

例如,用於解析在20090813145607.0Z20090813145607,0Z在任一.0Z,0Z結束的輸入日期值以下工作。

String input = "20090813145607.0Z"; 
DateTimeFormatter f = DateTimeFormatter.ofPattern ("uuuuMMddHHmmss[,S][.S]X"); 

但是用於打印,輸出包含,產生一個重新對分數秒。

20090813145607,0.0Z

所以我推斷我我的格式設置模式的使用[,S][.S]是不是得到這個功能的正確方法。

DecimalStyle

我試圖用DateTimeFormatter::withDecimalStyle方法傳遞DecimalStyle,但未能表現如我所料,我的實驗。該文件並沒有真正解釋其預期的行爲。

此問題很重要,因爲ISO 8601標準建議使用COMMA,但允許完全停止。要麼在實踐中經常使用。

Instant無法容忍一個逗號

也許這種寬容逗號和/或點作爲decimal mark是不可能的java.time。

我用Java 8 Update 102試了下面的代碼。第一個帶有FULL STOP(點)的輸入成功,而第二個COMMA輸入失敗。

String inputDot = "2016-01-02T12:34:56.7Z"; // Succeeds. 
Instant instantDot = Instant.parse (inputDot); 

String inputComma = "2016-01-02T12:34:56,7Z"; // Fails. Throws a DateTimeParseException. 
Instant instantComma = Instant.parse (inputComma); 
+0

爲了澄清,你想要一個單獨的'DateTimeFormatter'來處理這兩種格式的解析,但格式化的單一格式? –

+0

我不知道「DateTimeFormatter」是否允許這種「或」模式。我能想到的兩種解決方法是1. make 2格式化程序,一個用於','和一個用於'.',如果第一個解析失敗,則使用第二個。或2,通過用'.'替換第三個字符來「歸一化」輸入,如果它是'''',並且可以使用單個格式化程序 –

+0

@SotiriosDelimanolis是的我想要一個適用於輸入和輸出的格式化程序。我認爲java.time類對命令和點都有這樣的雙向支持,但是錯誤的假設。看看我的編輯顯示'Instant.parse'可以處理點而不是逗號。 –

回答

3

上的點VS逗號,點是遠遠超過我的經驗逗號更常見。 RFC3339僅使用點,與XML schema一樣。點不再是「優選的」(根據wikipedia):

的十進制標誌,逗號或在 2003點(沒有任何偏好 第22大會CGPM 10決議陳述, [16]但根據ISO 8601:2004優先選擇逗號)

考慮到所有這些,JSR-310更喜歡使用點。

DecimalStyle類確實提供了一些控制,其中DateTimeFormatterBuilder.appendFraction方法與true一起使用以從DecimalStyle輸出小數點。

解析點或逗號是不可能的。這被追蹤爲JDK-8132536,它解決了分析中的一般「或」概念。

使用ISO_INSTANT解析Instants,它說「不使用本地化的小數點樣式」。

因此,JSR-310的格式化程序無法做到您想要的。

+1

關於您的聲明「點不再是首選」,維基百科提到會議做出這樣的聲明發生在2003年,但官方的ISO文件是從2004年開始的,所以我認爲,逗號在純ISO背景下仍然是首選儘管甚至在XML架構等ISO派生中也被禁止)。 –

1
String fmt1 = "uuuuMMddHHmmss,SX"; 
String fmt2 = "uuuuMMddHHmmss.SX"; 
DateTimeFormatter f = DateTimeFormatter.ofPattern(fmt1); 
TemporalAccessor dateObject = null; 
try { 
    dateObject = f.parse("20090813145607.0Z"); 
} catch (DateTimeParseException e) { 
    f = DateTimeFormatter.ofPattern(fmt2); 
    try { 
     dateObject = f.parse(input); 
    } catch (DateTimeParseException e1) { 
     throw new IllegalArgumentException("invalid format "+input); 
    } 
} 

也許使用不同的RuntimeException的子類,但應該排序你。

1

(根據我的問題評論)

我DBOUT如果「DateTimeFormatter」允許這樣的一種「或」的格局。

兩種解決方法,我能想到的是

  1. 利用多個格式化。例如。一個用於,,另一個用於.,如果第一個解析失敗,則使用第二個。

    僞代碼

    List<DateTimeFormatter> formatters = Arrays.asList(
         DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX"), 
         DateTimeFormatter.ofPattern("uuuuMMddHHmmss,SX")); 
    
    TemporalAccessor result = null; 
    for (DateTimeFormatter f: formatters) { 
        try { 
         result = f.parse(input); 
         break; 
        } catch(DateTimeParseException ignored) { 
        } 
    } 
    if (result == null) { 
        throw new WhateverException(); 
    } 
    
  2. 「正常化」與.更換3,最後一個字符,如果它是一個,,並且可以使用一個單一的格式輸入。例如。

    f = DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX") 
    result = f.parse(input.matches(",..$") 
           ? input.replaceAll("^(.*),(..)$", "\\1.\\2") 
           : input);