【问题标题】:What's wrong with Java date parsing code?Java 日期解析代码有什么问题?
【发布时间】:2018-09-13 07:36:34
【问题描述】:

这个Java代码:

LocalDate.parse("12 Сен 2018", DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(new Locale("ru", "RUS")).ofPattern("dd MMM yyyy"));

导致

java.time.format.DateTimeParseException: Text '12 Сен 2018' could not be parsed at index 3
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDate.parse(LocalDate.java:428)

尝试了所有 Proper Russian month string translation Java 示例 - 没有结果。

这段代码有什么问题?

注意:我使用的是 Java 8

更新: 在本地机器和在线编译器上试过这个 - 在本地机器上工作的在线编译器 - 出现错误。

    Map<Long, String> map = new HashMap<>();
    map.put(1L, "Янв");
    map.put(2L, "Фев");
    map.put(3L, "Мар");
    map.put(4L, "Апр");
    map.put(5L, "Май");
    map.put(6L, "Июн");
    map.put(7L, "Июл");
    map.put(8L, "Авг");
    map.put(9L, "Cен");
    map.put(10L, "Окт");
    map.put(11L, "Ноя");
    map.put(12L, "Дек");
    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendPattern("dd ")
            .appendText(ChronoField.MONTH_OF_YEAR, map)
            .appendPattern(" yyyy")
            .toFormatter(new Locale("ru", "RU"));       
    System.out.println(LocalDate.parse("12 Cен 2018", formatter));

【问题讨论】:

  • Java 好像用什么сент 而不是Сен
  • @MadProgrammer,试过了,结果一样
  • @CodeMatrix,这是一个相关链接,感谢提供,但这个问题不是重复的。

标签: java date parsing localization java-time


【解决方案1】:

你需要为此创建一个自定义格式化程序,这并不复杂(第一次了解俄语,回答 stackoverflow 问题变得很方便):

Map<Long, String> map = new HashMap<>();
    map.put(1L, "янв");
    map.put(2L, "фев");
    map.put(3L, "мар");
    map.put(4L, "апр");
    map.put(5L, "май");
    map.put(6L, "июн");
    map.put(7L, "июл");
    map.put(8L, "авг");
    map.put(9L, "сен");
    map.put(10L, "окт");
    map.put(11L, "ноя");
    map.put(12L, "дек");
    DateTimeFormatter fmt = new DateTimeFormatterBuilder()
            .appendPattern("dd ")
            .appendText(ChronoField.MONTH_OF_YEAR, map)
            .appendPattern(" yyyy")
            .toFormatter(new Locale("ru"));

 System.out.println(LocalDate.parse("12 сен 2018", fmt)); // 2018-09-12

【讨论】:

  • 我为什么要这样做?我的问题中的代码不是必须能够解析这种日期格式吗?
  • @Artsiom 如您所见,您的问题的答案是“否”。我不知道还能对你说什么
【解决方案2】:

您好,请使用这段代码:

    Locale locale = new Locale("ru", "RU");
    String pattern = "dd MMM yyyy";
    String date = "03 сен 2017";
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, locale);
    LocalDate localDate = LocalDate.parse(date, formatter);
    System.out.println(localDate);

【讨论】:

  • 是的,我尝试并且工作得很好,你能分享你的错误吗?@Eugene
  • @MohammadRezaSamadi 我猜你在 java-8 中试过了,我的错。我在 java-9/10/11 中运行它,但它不起作用
  • @Eugene 是的,我正在使用 java-8。
【解决方案3】:

有两个问题:

首先ofPattern 只是创建了一个基于模式的格式化程序,因此丢弃了语言环境:

DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
                 .withLocale(new Locale("ru", "RUS"))
                 .ofPattern("dd MMM yyyy") // <------ static method!!

ofPattern 是一个静态方法,它只是创建一个新的DateTimeFormatter 实例(请参阅下面的正确构建方法)


第二:短月份名称似乎不适合该模式:

DateTimeFormatter.ofPattern("dd MMM yyyy")
                 .withLocale(new Locale("ru", "RUS"))
.format(LocalDate.of(2018, 9, 12))

结果为@​​987654326@。 Java 需要 сент.,而不是 сен

这有效并返回2018-09-12

LocalDate.parse("12 сент. 2018", 
         DateTimeFormatter.ofPattern("dd MMM yyyy")
         .withLocale(new Locale("ru", "RUS")))

【讨论】:

  • @Eugene 感谢您的反馈。我会让这篇文章直接回答OP的问题。但是我看到您的回答在当前情况下给出了解决方案...
  • 虽然它可能无法提供 OP 想要的解决方案,但它是最好的解释答案 (+1)。
  • 在我的 Java 8 上,我得到了 12 сен 2018。在 Java 9 和 10 上:12 сент. 2018。差异必须与Java 9中从Java自己的默认语言环境数据切换到CLDR有关。无论如何,如果(并且只要)她/他正在使用Java 8(或明确使用),提问者可能不会遇到第二个问题COMPAT 语言环境数据)。
  • 关于 First - 那么如何创建格式化程序并解析诸如 '13 Сен 2018' 这样的日期值?
  • @Artsiom 我在第二部分包含了一个不同的正确方法 (DateTimeFormatter.ofPattern("dd MMM yyyy").withLocale(new Locale("ru", "RUS")))
猜你喜欢
  • 1970-01-01
  • 2015-08-14
  • 1970-01-01
  • 2019-06-06
  • 2021-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多