Ошибка - исправлена в Java 9.
Об этой проблеме уже сообщалось в JDK-bug-log. Стивен Коулборн упоминает в качестве обходного решения следующее решение:
DateTimeFormatter dtf =
new DateTimeFormatterBuilder()
.appendPattern("yyyyMMddHHmmss")
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
.toFormatter();
Примечание. Этот обходной путь не распространяется на ваш вариант использования, состоящий только из двух символов шаблона SS. Корректировка может заключаться только в использовании других полей, таких как MICRO_OF_SECOND (6 раз SSSSSS) или NANO_OF_SECOND (9 раз SSSSSSSSS). Для двух цифр после дробной части см. Мое обновление ниже.
@PeterLawrey О значении символа шаблона S см. эту документацию < / а>:
Дробь: выводит поле наносекунды как доли секунды. Значение наносекунды состоит из девяти цифр, таким образом, количество букв шаблона составляет от 1 до 9. Если оно меньше 9, то значение наносекунды усекается, и выводятся только самые старшие цифры. При синтаксическом анализе в строгом режиме количество анализируемых цифр должно соответствовать количеству букв шаблона. При синтаксическом анализе в мягком режиме количество анализируемых цифр должно быть не меньше количества букв шаблона, до 9 цифр.
Итак, мы видим, что S означает любую долю секунды (включая наносекунду), а не только миллисекунды. Более того, дробная часть, к сожалению, в настоящий момент не подходит для синтаксического анализа смежных значений.
РЕДАКТИРОВАТЬ:
В качестве фона сделаем несколько замечаний о синтаксическом анализе смежных значений. Пока поля разделены литералами, такими как десятичная точка или разделители частей времени (двоеточие), интерпретация полей в тексте, который нужно проанализировать, несложна, потому что синтаксический анализатор легко знает, когда остановиться, то есть когда часть поля завершена и когда начинается следующее поле. Следовательно, синтаксический анализатор JSR-310 может обработать текстовую последовательность, если вы укажете десятичную точку.
Но если у вас есть последовательность соседних цифр, охватывающая несколько полей, возникают некоторые трудности с реализацией. Чтобы синтаксический анализатор знал, когда поле останавливается в тексте, необходимо заранее проинструктировать синтаксический анализатор, что данное поле представлено цифровыми символами фиксированной ширины. Это работает со всеми appendValue(...)
-методами, которые предполагают числовые представления.
К сожалению, JSR-310 не удалось сделать это также с дробной частью (appendFraction(...)
). Если вы поищете ключевое слово, смежное с javadoc класса DateTimeFormatterBuilder
, то обнаружите, что эта функция реализована ТОЛЬКО с помощью appendValue(...)
-методов. Обратите внимание, что спецификация для шаблона буквы S немного отличается, но внутренне делегирует appendFraction()
-method. Я предполагаю, что нам придется по крайней мере ждать до Java 9 (как сообщается в JDK-bug-log или позже ???), пока дробные части не смогут управлять синтаксическим анализом смежных значений.
Обновление от 25 ноября 2015 г .:
Следующий код, использующий только две цифры дробной части, не работает и неверно интерпретирует миллисекундную часть:
DateTimeFormatter dtf =
new DateTimeFormatterBuilder()
.appendPattern("yyyyMMddHHmmss")
.appendValue(ChronoField.MILLI_OF_SECOND, 2)
.toFormatter();
String input = "2011120312345655";
LocalDateTime ldt = LocalDateTime.parse(input, dtf);
System.out.println(ldt); // 2011-12-03T12:34:56.055
Обходной путь
String input = "2011120312345655";
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");
Date d = sdf.parse(input);
System.out.println(d.toInstant()); // 2011-12-03T12:34:56.055Z
не работает, потому что SimpleDateFormat
тоже неправильно интерпретирует дробь, как в современном примере (см. вывод, 55 мс вместо 550 мс).
Что остается в качестве решения, - это либо недоопределенное долгое ожидание до Java 9 (или новее?), Либо написание собственного хака, либо использование сторонних библиотек в качестве решения.
Решение на основе грязного взлома:
String input = "2011120312345655";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
int len = input.length();
LocalDateTime ldt = LocalDateTime.parse(input.substring(0, len - 2), dtf);
int millis = Integer.parseInt(input.substring(len - 2)) * 10;
ldt = ldt.plus(millis, ChronoUnit.MILLIS);
System.out.println(ldt); // 2011-12-03T12:34:56.550
Решение с использованием Joda-Time:
String input = "2011120312345655";
DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyyMMddHHmmssSS");
System.out.println(dtf.parseLocalDateTime(input)); // 2011-12-03T12:34:56.550
Решение с использованием моей библиотеки Time4J:
String input = "2011120312345655";
ChronoFormatter<PlainTimestamp> f =
ChronoFormatter.ofTimestampPattern("yyyyMMddHHmmssSS", PatternType.CLDR, Locale.ROOT);
System.out.println(f.parse(input)); // 2011-12-03T12:34:56.550
Обновление от 29 апреля 2016 г .:
Как видно из упомянутой выше проблемы JDK, теперь она помечена как решенная - для Java 9.
person
Meno Hochschild
schedule
24.03.2014
java-time
, не увидятjava.time
, и в разных местах существует ужасное сочетание тегов, которые используют один вместо другого. Если вы думаете, что тег с точкой будет более полезен, давайте полностью удалим другой тег, чтобы устранить двусмысленность. - person Charles   schedule 25.03.2014