Ошибка java.time.format.DateTimeParseException: не удалось проанализировать, неразобранный текст найден в индексе 10

Я пытаюсь передать следующую строку, используя LocalDateTime, но всегда получаю сообщение об ошибке:

Error java.time.format.DateTimeParseException: Text '2016-08-18 14:27:15.103+02' could not be parsed, unparsed text found at index 10

Вот моя строка: convertDate: '2016-08-18 14:27:15.103+02'

И мой код:

public static LocalDate conversorStringToLocalDateTime(String convertDate) throws ParseException {
    LocalDate dateTime =LocalDate.parse(convertDate);
    return dateTime;
}

Я думаю, это не слишком сложно, но я не могу увидеть ошибку. Может ли быть причиной +02 в строке?


person Asier Pomposo    schedule 19.08.2016    source источник
comment
Я думаю, это пробел между датой и временем. Это пробел или неразрывный пробел? Если ваша строка исходит из какой-то формы, это может быть символ, отличный от пробела.   -  person Elzo Valugi    schedule 19.08.2016
comment
Он взят из базы данных Postgre.   -  person Asier Pomposo    schedule 19.08.2016


Ответы (2)


tl;dr

OffsetDateTime odt = OffsetDateTime.parse ( "2016-08-18 14:27:15.103+02" , DateTimeFormatter.ofPattern ( "yyyy-MM-dd HH:mm:ss.SSSX" ) ) ;

Подробности

Ответ от greg-449 верен в отношении проблемы (с использованием объекта только для даты для значения даты и времени), но не решение.

В этом ответе используется LocalDateTime, который без необходимости отбрасывает ценные информация о смещении от UTC. LocalDateTime не представляет конкретный момент на временной шкале, а лишь смутное представление о возможных моментах в зависимости от адаптации к определенному часовому поясу.

+02 – это смещение от UTC, означающее "на два часа раньше UTC». Таким образом, в UTC время суток для этого одновременного момента составляет 12 часов, что на 2 часа меньше, чем ваши 14 часов. Это действительно представляет определенный момент на временной шкале. Это смещение представляет собой ценную информацию, которую вы выбрасываете с помощью LocalDateTime, а не OffsetDateTime.

Формат вашей строки в формате SQL, который близок к стандартному формату ISO 8601. Просто замените ПРОБЕЛ в середине на T. Классы java.time по умолчанию используют форматы ISO 8601, поэтому нет необходимости указывать шаблон форматирования.

String input = "2016-08-18 14:27:15.103+02";
String inputModified = input.replace ( " " , "T" );

К сожалению, в Java 8 есть ошибка при синтаксическом анализе значений смещения, сокращенных до часа, или значений смещения без двоеточия между часами и минутами. Исправлено в Java 9. Но в Java 8 нам нужно настроить ввод.

// Workaround for Java 8 where 2-digit offset fails parsing. Fixed in Java 9.
int lengthOfAbbreviatedOffset = 3;
if ( inputModified.indexOf ( "+" ) == ( inputModified.length () - lengthOfAbbreviatedOffset ) ) {
    // If third character from end is a PLUS SIGN, append ':00'.
    inputModified = inputModified + ":00";
}
if ( inputModified.indexOf ( "-" ) == ( inputModified.length () - lengthOfAbbreviatedOffset ) ) {
    // If third character from end is a PLUS SIGN, append ':00'.
    inputModified = inputModified + ":00";
}

Теперь разбираем.

OffsetDateTime odt = OffsetDateTime.parse ( inputModified );

Дамп на консоль. Обратите внимание, как мы преобразовали +02 в +02:00.

System.out.println ( "input: " + input + " | inputModified: " + inputModified + " | odt: " + odt );

ввод: 2016-08-18 14:27:15.103+02 | inputModified: 2016-08-18T14:27:15.103+02:00 | раз: 2016-08-18T14:27:15.103+02:00

Или укажите шаблон форматирования. При использовании этого шаблона форматирования ошибка синтаксического анализа смещения не возникает.

    DateTimeFormatter f = DateTimeFormatter.ofPattern ( "yyyy-MM-dd HH:mm:ss.SSSX" );
    OffsetDateTime odt = OffsetDateTime.parse ( input , f );

База данных

Исходя из Postgres, вы должны получать значение как объект даты и времени, а не строку.

Если ваш драйвер JDBC соответствует JDBC 4.2, вы можете вызвать ResultSet::getObject, чтобы получить Instant или OffsetDateTime. Если нет, вызовите ResultSet::getTimestamp, чтобы получить java.sql.Timestamp, затем немедленно преобразуйте в java.time, вызвав toInstant для объекта Timestamp.

Придерживайтесь java.time для вашей бизнес-логики; используйте типы java.sql кратко и только для обмена с базой данных.

person Basil Bourque    schedule 27.08.2016

Ваш код использует LocalDate, который анализирует только дату, а не дату и время, поэтому вы получаете сообщение об ошибке, когда анализ находит пробел после даты.

Таким образом, вы должны использовать LocalDateTime, но LocalDateTime.parse(String) ожидает дату в формате ISO, который не является форматом, который вы используете.

Поэтому вам нужно использовать DateTimeFormatter, чтобы указать формат вашей входной строки. Что-то вроде:

DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSX");
LocalDateTime result = LocalDateTime.parse(convertDate, format);
person greg-449    schedule 19.08.2016
comment
Да!!! Это сработало!!! Я также пытался использовать LocalDateTime раньше, но с изношенным DateTimeFormatter. Спасибо :) - person Asier Pomposo; 19.08.2016