Ответ 1
Я не считаю его хорошим решением, но, похоже, это путь.
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);
Результат, выполняемый на моем Oracle JDK 10.0.1:
2014-08-18T11:25:26+02:00
2014-08-18T11:25:26+02:00[Europe/Berlin]
Опять же, никакого хорошего решения не существует.
java.time
, современный API дат и времени Java, позволяет нам указывать тексты для полей для форматирования и разбора. Поэтому я использую это как для дня недели, так и для месяца, указывая аббревиатуры без точки, которые использовались со старыми данными локали COMPAT или JRE. Я использовал Java 9 Map.of
и Map.ofEntries
для создания необходимых нам карт. Если это тоже будет работать на Java 8, вы должны найти другой способ заполнить две карты, я надеюсь, вы это сделаете.
Если вам нужен старомодный java.util.Date
(вероятно, в старой базе кода), конвертировать вот так:
Date date = Date.from(odt.toInstant());
System.out.println("As legacy Date: " + date);
Вывод в моем часовом поясе (Европа/Копенгаген, возможно, примерно согласуется с вашим):
As legacy Date: Mon Aug 18 11:25:26 CEST 2014
Предложение стратегии
Я думаю, что если бы это был я, Id подумал о продолжении этого:
- Подождите. Установите соответствующее системное свойство из Java:
System.setProperty("java.locale.providers", "COMPAT,CLDR");
поэтому он не будет забыт в любой среде. Данные локали COMPAT существуют с 1.0 (я считаю, по крайней мере, близко), поэтому от этого зависит много кода (а не только от вас). Имя было изменено с JRE на COMPAT в Java 9. Для меня это может показаться планом сохранения данных в течение довольно долгого времени. Согласно ранней документации по доступу, он по-прежнему будет доступен в Java 11 (следующая "долгосрочная поддержка" Java-версии) и без предупреждения об устаревании или тому подобное. И если он будет удален в какой-то будущей версии Java, вы, вероятно, сможете быстро узнать, что можете решить проблему до обновления. - Используйте мое решение выше.
- Используйте интерфейс поставщика услуг локали, с которым связан Василий Бурк. Нет сомнений в том, что это хорошее решение в случае, если данные COMPAT должны быть удалены с неизвестного времени в будущем. Вы даже можете копировать данные локали COMPAT в свои собственные файлы, чтобы они не могли отнять их у вас, а только проверьте, есть ли проблемы с авторским правом до того, как вы это сделаете. Причина, по которой я упоминаю хорошее решение в последний раз, - вы сказали, что вам не нравится устанавливать системное свойство в любой возможной среде, где может работать ваша программа. Насколько я могу судить, использование ваших собственных данных локали через интерфейс поставщика локальных сетей по-прежнему потребует установки того же системного свойства (только для другого значения).