Ошибка java.time.format.DateTimeParseException: не удалось проанализировать, найден неразобранный текст по индексу 10
Я пытаюсь поставить следующую строку, используя LocalDateTime, но всегда получаю ошибку de unparsed text found:
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 в строке?
2 ответа
ТЛ; др
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 | odt: 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 кратко и только для обмена с базой данных.
Ваш код использует LocalDate
который анализирует только дату, а не дату и время, поэтому вы получаете сообщение об ошибке, когда анализ находит пробел после даты.
Так что вы должны использовать LocalDateTime
но LocalDateTime.parse(String)
ожидает дату формата ISO, которая не является тем форматом, который вы используете.
Так что вам нужно использовать DateTimeFormatter
указать формат вашей входной строки. Что-то вроде:
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSX");
LocalDateTime result = LocalDateTime.parse(convertDate, format);