19

我正在尝试使用 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可能是原因吗?

4

2 回答 2

19

tl;博士

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

细节

greg-449的答案对问题是正确的(使用仅日期对象作为日期时间值),但不是解决方案。

该答案使用LocalDateTime它不必要地丢弃了有关offset-from-UTC的有价值信息。ALocalDateTime不代表时间轴的特定时刻,只是关于可能时刻的模糊概念,具体取决于调整到特定时区。

+02与 UTC 的偏移量,意思是“比UTC提前两个小时”。因此,在 UTC 中,这一同时时刻的时间是 12 小时,比您的 14 小时少 2 小时。这确实代表了时间线上的特定时刻。LocalDateTime这个偏移量是你用 a而不是a 丢弃的有价值的信息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 | 输入修改: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以获取InstantOffsetDateTime. 如果没有,调用ResultSet::getTimestamp获取 a ,然后通过调用Timestamp 对象java.sql.Timestamp立即转换为 java.time 。toInstant

坚持使用 java.time 作为您的业务逻辑;简单地使用 java.sql 类型并且仅用于与数据库的交换。

于 2016-08-27T20:12:54.597 回答
12

您的代码正在使用LocalDate它只解析日期 - 而不是日期和时间,因此当解析找到日期之后的空间时,您会收到错误消息。

因此,您应该使用LocalDateTimeLocalDateTime.parse(String)期望 ISO 格式日期不是您正在使用的格式。

因此,您需要使用 aDateTimeFormatter来指定输入字符串的格式。就像是:

DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSX");
LocalDateTime result = LocalDateTime.parse(convertDate, format);
于 2016-08-19T08:13:23.797 回答