如何更改 JDK8 中的 DateFormatSymbols 以解决与 JDK7(属格月份名称)的不兼容问题?

Jak*_*ski 6 incompatibility datetime-format java-8

正如 Xaerxess 在本主题中发现的那样:Month name in genitive (Polish locale) with Joda-Time DateTimeFormatter in JDK8 DateFormatSymbols.getInstance(new Locale("pl", "PL")).getMonths() 默认返回所有格中的月份名称。以前的 Java 版本以主格形式返回月份名称。例如,使用“dd-MMMM-yyyy”模式的 SimpleDateFormat 格式在 JDK8 中与在 JDK6 或 7 中给出不同的结果。

这是一个很大的变化,我的一些旧应用程序无法使用新的月份名称正常工作。我正在寻找一种解决方案来更改 Locale PL 的全局默认月份名称。

我尝试使用 DateFormatSymbols.getInstance().setMonths(new String[] {..}),但它在全局范围内不起作用。

如果我能找到使用 Java 代码更改默认月份名称的解决方案,我可以在应用程序初始化时添加此代码,而无需更正整个应用程序。在我的例子中,我只是简单地使用 load-on-startup 选项将 servlet 添加到我的 Web 应用程序中。

或者也许您对如何在这种情况下使 Java 8 兼容有不同的想法?也许我可以在启动时传递给 jvm 的参数/选项?

pan*_*adb 4

我遇到过同样的问题。在所有十亿个标准中,我的客户决定使用所有大写字母来打破默认解析器的月份。所以我的约会看起来像:

02-DEC-15
Run Code Online (Sandbox Code Playgroud)

现在Java时间可以解析“Dec”,但不能解析“DEC”。烦人..我搜索了一段时间,找到了这个问题的java8替代品。

您可以通过以下方式向格式化程序添加自定义内容:

public static void main(String[] args) {
    String test = "02-DEC-15";

    Map<Long, String> lookup = new HashMap<>();
    lookup.put(1L, "JAN");
    lookup.put(2L, "FEB");
    lookup.put(3L, "MAR");
    lookup.put(4L, "APR");
    lookup.put(5L, "MAY");
    lookup.put(6L, "JUN");
    lookup.put(7L, "JUL");
    lookup.put(8L, "AUF");
    lookup.put(9L, "SEP");
    lookup.put(10L, "OCT");
    lookup.put(11L, "NOV");
    lookup.put(12L, "DEC");

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                                      .appendPattern("dd-")
                                      .appendText(ChronoField.MONTH_OF_YEAR, lookup)
                                      .appendPattern("-yy")
                                      .toFormatter();

    LocalDate parse = LocalDate.parse(test,formatter);
    System.out.println(parse);
}
Run Code Online (Sandbox Code Playgroud)

这有点棘手,因为它的行为与我预期的不同。以下是需要考虑的几点:

每个追加调用都会添加一个新的解析器实例,如果不起作用,则将按顺序调用该实例,严格失败。例如,如果您采用上面的示例并认为您可以添加月份,则说:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                                  .appendPattern("dd-MMM-yy")
                                  .appendText(ChronoField.MONTH_OF_YEAR, lookup)
                                  .toFormatter();
Run Code Online (Sandbox Code Playgroud)

这将失败,因为该模式为您的格式化程序添加了多个解析器:

dd
-
MMM
-
yy
Run Code Online (Sandbox Code Playgroud)

在末尾添加查找将不起作用,因为 MMM 已经使您的解析上下文失败。

因此,每个步骤都可以单独添加。看着:

月日#PARSER

这最终帮助我找到了正确的解决方案。无论如何,使用生成器您可以构造您想要的任何奇怪的非标准解析器。然而,请记住对每个认为自己可以想出另一种方式来表示需要释放到这个世界的约会的人大喊大叫。

我希望这能让某人免于一些心痛。

阿图尔

编辑:所以我再次半忽略了这个问题。我认为没有默认的方式,除非您自己注册一个提供商。然而,这对我来说似乎有点不对。我认为解析的工作方式是拥有您使用的解析器的静态实例。这是关于查看例如 java 时间中的默认解析器是如何实现的。因此,只需在启动时创建自定义解析器并在整个应用程序中引用它进行解析即可。