2016-01-07 49 views
2

DateTimeFormatter中可選模式的順序如何影響解析操作?使用多個可選模式時的順序重要性

我正在運行這個程序,並想知道爲什麼最後一行拋出一個異常,但不是前三個。

public static void main(String[] args) { 
    String p1 = "[EEEE][E] dd-MM-yyyy"; 
    String p2 = "[E][EEEE] dd-MM-yyyy"; 
    String date1 = "Thu 07-01-2016"; 
    String date2 = "Thursday 07-01-2016"; 
    parse(date1, p1); //OK 
    parse(date1, p2); //OK 
    parse(date2, p1); //OK 
    parse(date2, p2); //Exception 
} 

private static void parse(String date, String pattern) { 
    DateTimeFormatter fmt = DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH); 
    System.out.println(fmt.parse(date)); 
} 

最後一行的例外是:

java.time.format.DateTimeParseException:文本 '週四2016年7月1日' 無法在索引3

+1

如果'java.time'提供了一個帶有後備模式(如jodatime)的'DateTimeFormatter',我一定會很好。 –

+1

@SotiriosDelimanolis有一個關於在解析中添加對「OR」的支持的增強請求:[JDK-8132536](https://bugs.openjdk.java.net/browse/JDK-8132536) – Tunaki

+0

@Tunaki Java的錯誤跟蹤站點是太慢了。希望這個請求被接受。 –

回答

3

該文檔沒有提到任何優先級,我會爭辯說,你得到的結果是正常的。這是從左向右讀取String格式的結果。

  • 讓我們考慮第一種格式"[EEEE][E] dd-MM-yyyy"

    • "Thu 07-01-2016":該API試圖找到,如果第一可選部分"[EEEE]"可以匹配。引用來自DateTimeFormatter Javadoc約文字標記

      確切地說4個模式字母將使用完整的形式。

      在這種情況下,這是一週的完整形式。這與"Thu"不匹配,因此可選部分將被跳過。然而,第二個可選部分是"[E]",仍然引用

      少於4個模式字母將使用簡寫形式。

      所以這將匹配"Thu"。因此,要解析的字符串可以被正確理解

    • "Thursday 07-01-2016":它與上面相同,除了它將在第一個可選部分與"Thursday"相匹配。但API仍然會繼續搜索下一個可選部分"[E]"的有效部分,並且它不會找到任何部分,因此可選部分將被跳過。
  • 現在考慮第二種格式"[E][EEEE] dd-MM-yyyy"
    • "Thu 07-01-2016":該API試圖找到,如果第一可選部分"[E]"能夠匹配,它併爲"Thu"工作。如上所述,API現在將嘗試找到"[EEEE]"的匹配項,但它不會找到任何可跳過的選項部分。
    • "Thursday 07-01-2016":API試圖再次匹配"[E]",這就是事情發生的地方:它確實匹配。 "Thursday""Thu"開頭,因此格式化程序能夠找到匹配項。但是,它試圖解析其餘的是"rsday 07-01-2016"[EEEE]可選部分不會被匹配,因此它將被跳過。然後它失敗了,因爲剩下的空間沒有空間(取而代之的是"r")。

所以,如果你有

parse("ThuThursday 07-01-2016", "[E][EEEE] dd-MM-yyyy"); 

運行你的代碼,你會看到,它的工作原理:"[E]"匹配"Thu""[EEEE]"匹配"Thursday"

注意異常消息怎麼也暗示了這一點(重點煤礦):

java.time.format.DateTimeParseException:文本「週四2016年7月1日」無法在索引3解析

指數3相當於"rsday""r"所以這意味着它能夠解析,一直到這一點。

1
解析

可選格式的順序事項:

當解析器格式爲[E][EEEE] dd-MM-yyyy解析"Thursday 07-01-2016"那麼它

  • 使用可選的部分消耗Thu[E]
  • 跳過[EEEE],因爲它不能識別一個漫長的一天的星期 -
  • 現在需要一個空間,因爲它看到r並因此引發錯誤指數3無一例外失敗

因此,如果您使用可選部分來解析替代版本(此處使用長或短的星期幾),請首先添加更具體的格式。

2

DateTimeFormatter中可選模式的順序如何影響解析操作?

解析器嘗試按照出現在模式中的順序匹配每個可選部分。

請注意,字符串「星期四」以「Thu」開頭,可以與模式片段「E」匹配。接下來,觀察匹配失敗在索引3處報告,索引3對應於「週四」中的'r'。在錯誤情況下會發生什麼情況是解析器將字符串的前三個字符與第一個可選部分相匹配,跳過第二個可選部分,因爲它不匹配字符串的下一部分,然後不能匹配'r'。

換句話說,這些格式化程序不會回溯嘗試替代匹配。用正則表達式來說,可選部分是貪婪的。

還要注意,你的兩種模式比你想要的更寬容。例如,您的模式p1將匹配字符串"ThursdayThu 07-01-2016"