java.text.ParseException:无法解析的日期:“...”

k4r*_*j1k 5 java dayofweek simpledateformat datetime-parsing java-time

我使用此代码收到此错误:

SimpleDateFormat sdf = new SimpleDateFormat("EEEE dd MMMM HH:mm yyyy",myDateFormatSymbols);
sdf.parse("????????? 12 ??????? 07:00 2021");
Run Code Online (Sandbox Code Playgroud)

"Monday 12 April 07:00 2021"。问题是,每当我将日期从星期一更改为星期二 ( "????????") 时,我都不会收到此错误,并且代码有效。这是代码myDateFormatSymbols

private final static DateFormatSymbols myDateFormatSymbols = new DateFormatSymbols(){
        @Override
        public String[] getWeekdays(){
             return new String[]{"?????????","????????", "??????", "??????", "???????", "??????", "??????"};
        }
        @Override
        public String[] getMonths() {
            return new String[]{...};
        }
}
Run Code Online (Sandbox Code Playgroud)

所有月份和工作日都正常工作,似乎这个错误只发生在星期一。

Ole*_*.V. 5

  • 时间

  • 月份名称的独立形式

  • DateTimeFormatterBuilder.appendText(TemporalField, Map<Long, String>)

我强烈建议您使用java.time,现代 Java 日期和时间 API(底部的链接)来处理您的日期和时间工作。

您正在尝试用乌克兰语解析日期时间字符串。我们会立即期望 Java 使用ukuk-UAlocale开箱即用地执行此操作。编辑:令我惊讶的是,您的字符串使用的是 Java 认为的月份名称的独立形式(似乎我不明白月份名称的独立形式是什么意思)。要在格式中使用LLLL格式模式字符串而不是MMMM. 此外,字符串中 Friday 的名称与 Java 知道的名称不同(带有撇号的????????,正如 Basil Bourque 已经说过的,来自 CLDR)。正如您已经尝试过的那样,解决方案是指定您自己的日子名称。在 java.time 这是通过一个DateTimeFormatterBuilder及其双参数appendText方法。例如:

private static final Map<Long, String> DAY_NAMES = Map.of(1L, "?????????", 2L, "????????",
        3L, "??????", 4L, "??????", 5L, "???????", 6L, "??????", 7L, "??????");
private static final Locale UKRAINIAN = Locale.forLanguageTag("uk-UA");
private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
        .appendText(ChronoField.DAY_OF_WEEK, DAY_NAMES)
        .appendPattern(" dd LLLL HH:mm uuuu")
        .toFormatter(UKRAINIAN);
Run Code Online (Sandbox Code Playgroud)

现在格式化程序就位,解析很简单,因为它应该是:

    String stringToParse = "????????? 12 ??????? 07:00 2021";
    LocalDateTime dateTime = LocalDateTime.parse(stringToParse, FORMATTER);
    System.out.println(dateTime);
Run Code Online (Sandbox Code Playgroud)

输出:

2021-04-12T07:00

我发现我的代码比你的更清晰易读,这对代码来说很重要。没有有趣的覆盖。从 0 开始没有疯狂的月份编号。星期一是一周的第一天,因为它在您的问题和乌克兰中都是如此。

默认情况下,java.time 也会执行更好的验证。当您的字符串表示 4 月 12 日是星期一时,java.time 会检查这一点,如果不是这样,它会反对。

用乌克兰语写日期中的月份(适用于其他读者)

在写这个答案之前,我对用乌克兰语写日期一无所知。对于好奇的读者,我想通过我的搜索传递一些观察结果。

似乎使用了两种形式的月份名称:

  1. 主格,Java 称为独立形式,例如?????? 一月。这种形式通常以-??? ( -en )。
  2. Java 用作正常(非独立)形式的所有格,例如????? 一月。也许“一月”可以用作翻译?这种形式通常以-?? - 是吗?)

在互联网上,我看到了日期中使用的两种形式。我不是很确定,但可能的趋势是: 主格(独立)形式用于一个月中没有某一天的情况,有时是非正式的;当月中的某一天出现时,正式使用所有格。

链接


Yas*_*jaj 2

您可以检查 JavadocDateFormatSymbols#weekdays,不幸的是,索引处的元素0总是被忽略。

\n

我只需将其替换为空字符串即可。

\n
\n

工作日字符串。例如:“Sunday”、“Monday”等。由 8 个字符串组成的数组,按 Calendar.SUNDAY、Calendar.MONDAY 等索引。元素 weekdays[0] 被忽略。

\n
\n
\n

以下代码现在打印预期的答案

\n
DateFormatSymbols myDateFormatSymbols = new DateFormatSymbols() {\n    @Override\n    public String[] getWeekdays() {\n        return new String[]{"", "\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd1\x96\xd0\xbb\xd0\xbe\xd0\xba", "\xd0\xb2\xd1\x96\xd0\xb2\xd1\x82\xd0\xbe\xd1\x80\xd0\xbe\xd0\xba", "\xd1\x81\xd0\xb5\xd1\x80\xd0\xb5\xd0\xb4\xd0\xb0", "\xd1\x87\xd0\xb5\xd1\x82\xd0\xb2\xd0\xb5\xd1\x80", "\xd0\xbf\xd1\x8f\xd1\x82\xd0\xbd\xd0\xb8\xd1\x86\xd1\x8f", "\xd1\x81\xd1\x83\xd0\xb1\xd0\xbe\xd1\x82\xd0\xb0", "\xd0\xbd\xd0\xb5\xd0\xb4\xd1\x96\xd0\xbb\xd1\x8f"};\n    }\n\n    @Override\n    public String[] getMonths() {\n        return new String[]{"\xd0\xba\xd0\xb2\xd1\x96\xd1\x82\xd0\xb5\xd0\xbd\xd1\x8c"};\n    }\n};\n\nSimpleDateFormat sdf = new SimpleDateFormat("EEEE dd MMMM HH:mm yyyy", myDateFormatSymbols);\nSystem.out.println(sdf.parse("\xd0\xbf\xd0\xbe\xd0\xbd\xd0\xb5\xd0\xb4\xd1\x96\xd0\xbb\xd0\xbe\xd0\xba 12 \xd0\xba\xd0\xb2\xd1\x96\xd1\x82\xd0\xb5\xd0\xbd\xd1\x8c 07:00 2021")); // Tue Jan 12 07:00:00 CET 2021\n
Run Code Online (Sandbox Code Playgroud)\n