SimpleDateFormat with German Locale - Java 8 vs Java 10+

血红的双手。 提交于 2019-11-29 00:52:38

I don’t say it’s a nice solution, but it seems to be a way through.

    Map<Long, String> dayOfWeekTexts = Map.of(1L, "Mo", 2L, "Di", 
            3L, "Mi", 4L, "Do", 5L, "Fr", 6L, "Sa", 7L, "So");
    Map<Long, String> monthTexts = Map.ofEntries(Map.entry(1L, "Jan"), 
            Map.entry(2L, "Feb"), Map.entry(3L, "Mär"), Map.entry(4L, "Apr"),
            Map.entry(5L, "Mai"), Map.entry(6L, "Jun"), Map.entry(7L, "Jul"),
            Map.entry(8L, "Aug"), Map.entry(9L, "Sep"), Map.entry(10L, "Okt"),
            Map.entry(11L, "Nov"), Map.entry(12L, "Dez"));

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendText(ChronoField.DAY_OF_WEEK, dayOfWeekTexts)
            .appendLiteral(' ')
            .appendText(ChronoField.MONTH_OF_YEAR, monthTexts)
            .appendPattern(" dd HH:mm:ss z Z yyyy")
            .toFormatter(Locale.GERMANY);

    String toParse = "Mo Aug 18 11:25:26 MESZ +0200 2014";
    OffsetDateTime odt = OffsetDateTime.parse(toParse, formatter);
    System.out.println(odt);
    ZonedDateTime zdt = ZonedDateTime.parse(toParse, formatter);
    System.out.println(zdt);

Output running on my Oracle JDK 10.0.1:

2014-08-18T11:25:26+02:00
2014-08-18T11:25:26+02:00[Europe/Berlin]

Then again, no nice solution may exist.

java.time, the modern Java date and time API, allows us to specify texts to use for fields for both formatting and parsing. So I exploit that for both day of week and for month, specifying the abbreviations without dot that were used with the old COMPAT or JRE locale data. I have used the Java 9 Map.of and Map.ofEntries for building the maps we need. If this is to work in Java 8 too, you must find some other way to populate the two maps, I trust you to do that.

If you do need an old-fashioned java.util.Date (likely in a legacy code base), convert like this:

    Date date = Date.from(odt.toInstant());
    System.out.println("As legacy Date: " + date);

Output in my time zone (Europe/Copenhagen, probably roughly agrees with yours):

As legacy Date: Mon Aug 18 11:25:26 CEST 2014

Suggestion for a strategy

I am thinking that if that were me, I’d consider proceeding this way:

  1. Wait. Set the relevant system property from within Java: System.setProperty("java.locale.providers", "COMPAT,CLDR"); so it won’t be forgot in any environment. The COMPAT locale data have been around since 1.0 (I believe, at least close), so a lot of code out there depends on it (not only yours). The name was changed from JRE to COMPAT in Java 9. To me this may sound like a plan to keep the data around for quite a while still. According to the early access documentation it will still be available in Java 11 (the next “long term support” Java version) and with no deprecation warning or the like. And should it be removed in some future Java version, you will probably be able to find out soon enough that you can deal with the problem before upgrading.
  2. Use my solution above.
  3. Use the locale service provider interface that Basil Bourque linked to. There is no doubt that this is the nice solution in case the COMPAT data should be removed some unknown time in the future. You may even be able to copy the COMPAT locale data into your own files so they can’t take them away from you, only check if there are copyright issues before you do so. The reason why I mention the nice solution last is you said you aren’t happy with having to set a system property in every possible environment where your program may run. As far as I can tell, using your own locale data through the locale service provider interface will still require you to set the same system property (only to a different value).

Just to mention: SimpleDateFormat is an old way to format dates which BTW is not thread safe. Since Java 8 there are new packages called java.time and java.time.format and you should use those to work with dates. For your purposes you should use class DateTimeFormatter.

The formatted value in java 8 was Fr Juni 15 00:20:21 MESZ +0900 2018 But it changed to Fr. Juni 15 00:20:21 MESZ +0900 2018 EEE includes . THIS IS COMPATIBILITY ISSUE and it does not matter that older versions of code do not work in newer versions.(Sorry for translator) If date string is yours, you should add dot for new version users. Or make users use Java 8 to use your software.

It can make the software slower, using substring method is also good.

    String toParse = "Mo Aug 18 11:25:26 MESZ +0200 2014";
    String str = toParse.substring(0, 2) + "." + toParse.substring(2);
    String pattern = "EEE MMM dd HH:mm:ss z Z yyyy";

    DateFormat dateFormatter = new SimpleDateFormat(pattern, Locale.GERMANY);
    System.out.println(dateFormatter.format(System.currentTimeMillis()));
    Date date = dateFormatter.parse(str);

Sorry again for my bad English.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!