java.time
Я полностью согласен с комментариями, рекомендующими java.time, современный API даты и времени Java, для вашей работы с датой и временем.
Используйте это средство форматирования:
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("dd.MMMuuuu HH:mm:ss", Locale.GERMAN);
Do:
LocalDateTime dateTime = LocalDateTime.parse("01.Jan.2017 00:47:13", FORMATTER);
System.out.println(dateTime);
Вывод при запуске на Java 11 с немецкой локалью:
2017-01-01T00:47:13
Вы можете спросить, почему по сравнению с вашей строкой шаблона формата я пропустил вторую точку? В Java 11 (и, вероятно, рядом с версиями Java, возможно, начиная с Java 9–16) немецкие сокращения месяцев имеют точку для обозначения аббревиатуры, поэтому Jan.
для января (январь) и т. Д. Таким образом, в моем формате MMM
соответствует Jan.
, а затем uuuu
соответствует 2017 г.
Для более полного рассказа Java получает данные о локали, включая сокращения месяцев, используемые в разных регионах, из четырех источников, и не все источники согласны с тем, как выглядят сокращения месяцев на немецком языке. Начиная с Java 9, значение по умолчанию - CLDR,COMPAT
, что означает, что предпочтительны данные языкового стандарта из CLDR, репозитория данных общего языкового стандарта Unicode. В том числе и упомянутые мной точки. Вы можете получить разные результаты, задав для системного свойства java.locale-providers
значение, которое не начинается с CLDR
.
Что пошло не так в вашем коде?
Я уже дал вам подсказку: в некоторых версиях Java сокращенные обозначения месяцев на немецком языке отмечены точкой. Итак, в вашем примере с точками в качестве разделителей ваш SimpleDateFormat
сопоставил dd.MMM
(без второй точки) с 01.Jan.
(со второй точкой). В соответствии с форматом теперь должна появиться точка, но поскольку эта точка уже была использована, SimpleDateFOrmat
посмотрел на 2017
, решил, что это не точка, и выдал исключение, которое вы видели.
По-настоящему удивительное поведение было в вашем первом примере, когда SimpleDateFormat
смог проанализировать 01-Jan-2017 00:47:13
без точек, хотя считает, что сокращение месяца должно заканчиваться точкой. Я видел буквально сотни примеров удивительного поведения SimpleDateFormat
раньше, но никогда не видел ничего подобного этому.
И все эти сюрпризы заставляют меня сказать: всеми способами избегайте использования SimpleDateFormat
.
Если вы настроены скептически, я вас не виню. Итак, чтобы продемонстрировать:
SimpleDateFormat formatter = new SimpleDateFormat("MMMyyyy", Locale.GERMAN);
System.out.println(formatter.format(0L));
System.out.println(formatter.parse("Jan2017"));
System.out.println(formatter.parse("Jan.2017"));
Вывод, все еще на Java 11:
Jan.1970
Sun Jan 01 00:00:00 CET 2017
Sun Jan 01 00:00:00 CET 2017
Мы видим, что SimpleDateFormat
форматирует месяц с помощью точки и может анализировать строки как с точками, так и без них.
Это еще не все.
SimpleDateFormat formatter = new SimpleDateFormat("MMM", Locale.GERMAN);
System.out.println(formatter.format(0L));
Вывод:
Jan
На этот раз аббревиатура месяца была отформатирована без точки. Я понятия не имел, что происходит. Повторяю, забудьте о запутанном классе SimpleDateFormat
. Это печально известный возмутитель спокойствия.
Ссылки
03.05.2021