簡體   English   中英

無法從西班牙日期字符串轉換為 Java 中的 LocalDate

[英]Cannot convert from Spanish date string to LocalDate in Java

您好,我是來解決 Locale 格式化程序語言的 DateTimeFormatter 問題的,讓我向您介紹一下:

  • 我正在使用以下字符串格式讀取 CSV 文件:“dd-MMM-yyyy”<-->“28-dic-2017”
  • 然后我必須將列表中的每個字符串解析為 LocalDate 以使用 timeAPI 方法處理每個字符串。
  • 請注意,我的月份是西班牙語縮寫的。 那是一團糟!
  • 執行時返回:

觀察到堆棧跟蹤錯誤:

Exception in thread "main" java.time.format.DateTimeParseException: Text '28-dic-2017' could not be parsed at index 3
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2051)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1953)
    at java.base/java.time.LocalDate.parse(LocalDate.java:429)
    at com.examen.Presentation.Principal.parseDate(Principal.java:28)
    at com.examen.Presentation.Principal.main(Principal.java:19)

最小的、可重現的代碼示例:

public static LocalDate parseDate(String fecha) {

    Locale loc = new Locale("es", "ES");
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy", loc);
    LocalDate date = LocalDate.parse(fecha, formatter);

    return date;
}

我從語言環境嘗試不同的事情和方法時遇到了同樣的錯誤,而 DateTimeFormatter 甚至不知道我在做什么,但我認為這顯然不應該起作用。

在另一個答案中,geocodezip 已經解釋了您的嘗試失敗的原因。 這里有兩個解決方案的建議,我發現它們比那個答案中的那個更優雅。

Java 語言環境數據提供者

Java 可以從多達四個來源獲取其區域設置數據,包括不同語言的月份縮寫。 由於 Java 9 默認情況下,它更喜歡從 CLDR、Unicode 公共區域設置數據存儲庫中獲取它們。 在 CLDR 西班牙語月份縮寫帶有一個點(或全點),如另一個答案中所述,如dic. diciembre 另一個來源是自早期版本以來內置於 Java 的語言環境數據(在 Java 8 之前一直是默認設置)。 這里西班牙月份的縮寫沒有點(你的數據可能是由在 Java 8 或更早版本上運行的程序生成的,我不知道)。 這些語言環境數據被稱為COMPAT ,以與早期的 Java 版本兼容。 啟動程序時,您可以在命令行中指定 Java 應該更喜歡 COMPAT 而不是 CLDR,例如:

java -Djava.locale.providers=COMPAT,CLDR YourJavaMainClass

這將導致您現有的代碼接受dic和其他不帶點的月份縮寫。

這是 JVM 的全局設置,因此它還會導致您的程序中的任何位置以及在同一 JVM 中運行的其他程序中的任何區域設置敏感操作都使用來自 ZD52387880E1522817A72D7 的舊區域設置數據。

DateTimeFormatterBuilder.appendText()

由於您知道您的格式始終為28-dic-2017 ,因此您還可以通過明確指定輸入數據中使用的月份縮寫來使自己完全獨立於任何語言環境數據。

private static Map<Long, String> getMonthAbbreviations() {
    return Map.ofEntries(
            Map.entry(1L, "ene"),
            Map.entry(2L, "feb"),
            Map.entry(3L, "mar"),
            Map.entry(4L, "abr"),
            Map.entry(5L, "may"),
            Map.entry(6L, "jun"),
            Map.entry(7L, "jul"),
            Map.entry(8L, "ago"),
            Map.entry(9L, "sep"),
            Map.entry(10L, "oct"),
            Map.entry(11L, "nov"),
            Map.entry(12L, "dic"));
}

private static final DateTimeFormatter inputDateFormatter = new DateTimeFormatterBuilder()
        .appendPattern("dd-")
        .appendText(ChronoField.MONTH_OF_YEAR, getMonthAbbreviations())
        .appendPattern("-uuuu")
        .toFormatter();

此格式化程序獨立於語言環境並解析您的日期字符串:

    String fecha = "28-dic-2017";
    LocalDate date = LocalDate.parse(fecha, inputDateFormatter);
    System.out.println(date);

Output 是:

2017-12-28

解析問題的提示:先嘗試格式化

提示:當解析不起作用時,您可以先嘗試格式化以了解要解析的字符串應該是什么樣子,並與您嘗試解析的字符串進行比較。 例如:

    Locale loc = new Locale("es", "ES");
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy", loc);
    
    System.out.println("Want to parse: 28-dic-2017");
    System.out.println("Formatted:     "
            + LocalDate.of(2017, Month.DECEMBER, 28).format(formatter));
    System.out.println("Want to parse: 29-sep-2017");
    System.out.println("Formatted:     "
            + LocalDate.of(2017, Month.SEPTEMBER, 29).format(formatter));
 Want to parse: 28-dic-2017 Formatted: 28-dic.-2017 Want to parse: 29-sep-2017 Formatted: 29-sept.-2017

現在我們至少可以一開始就看到哪里出了問題。

文檔鏈接

對於西班牙語, DateTimeFormatter期望縮寫的月份以句點結束。 像這樣: 28-dic.-2017

如果您的所有日期都采用該格式,您可以解析輸入字符串以添加句點,然后將其發送到DateTimeFormatter

public static LocalDate parseDate(String fecha) {
    int firstDash = fecha.indexOf('-')+1;
    int secondDash = fecha.indexOf('-', fecha.indexOf('-')+1);
    String month = fecha.substring(firstDash, secondDash);
    String dateStr = fecha.substring(0,firstDash)+month+"."+fecha.substring(secondDash);
    Locale loc = new Locale("es", "ES");
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy", loc);
    LocalDate date = LocalDate.parse(dateStr, formatter);

    return date;
}

如果格式有時有句點,如果它不存在,則需要添加它:

public static LocalDate parseDate(String fecha) {
    String dateStr;
    if (fecha.indexOf(".")!=-1) {
        dateStr = fecha;
    } else {
        int firstDash = fecha.indexOf('-')+1;
        int secondDash = fecha.indexOf('-', fecha.indexOf('-')+1);
        String month = fecha.substring(firstDash, secondDash);
        dateStr = fecha.substring(0,firstDash)+month+"."+fecha.substring(secondDash);
    }
    System.out.println(dateStr);
    Locale loc = new Locale("es", "ES");
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy", loc);
    LocalDate date = LocalDate.parse(dateStr, formatter);

    return date;
}

output:

2017-12-28

暫無
暫無

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

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