错误 java.time.format.DateTimeParseException:无法解析,在索引 10 处找到未解析的文本

Error java.time.format.DateTimeParseException: could not be parsed, unparsed text found at index 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 可能是原因吗?

您的代码使用的 LocalDate 仅解析日期 - 而不是日期和时间,因此当解析发现日期后的 space 时您会收到错误消息。

所以你应该使用 LocalDateTimeLocalDateTime.parse(String) 需要一个 ISO 格式的日期,这不是你正在使用的格式。

因此您需要使用 DateTimeFormatter 来指定输入字符串的格式。类似于:

DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSX");
LocalDateTime result = LocalDateTime.parse(convertDate, format);

tl;博士

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

详情

关于问题(使用日期时间值使用仅限日期的对象)是正确的,但解决方案不正确。

该答案使用 LocalDateTime which unnecessarily throws away valuable information about the offset-from-UTCLocalDateTime 代表时间轴上的特定时刻,只是对可能的时刻的模糊概念,具体取决于调整到特定时区。

+02 是一个 offset-from-UTC meaning “two hours ahead of UTC”。所以在 UTC 中,这个同时时刻的时间是 12 小时,比你的 14 小时少 2 小时。这个确实代表了时间轴上的一个特定时刻。此偏移量是您使用 LocalDateTime 而不是 OffsetDateTime 丢弃的有价值的信息。

您的字符串格式为 SQL 格式,接近于标准 ISO 8601 格式。只需将中间的 SPACE 替换为 T。 java.time 类 默认使用 ISO 8601 格式,因此无需指定格式模式。

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

不幸的是,Java 8 在解析缩写为小时的偏移值或省略小时和分钟之间的冒号的偏移值时存在错误。在Java9中固定。但是在Java8中,我们需要调整输入。

// 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 );

input: 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 以获得 InstantOffsetDateTime。如果不是,则调用 ResultSet::getTimestamp 以获得 java.sql.Timestamp,然后通过调用 Timestamp 对象上的 toInstant 立即转换为 java.time。

坚持使用 java.time 作为您的业务逻辑;短暂使用 java.sql 类型,仅用于与数据库交换。