tl;博士
OffsetDateTime odt = OffsetDateTime.parse ( "2016-08-18 14:27:15.103+02" , DateTimeFormatter.ofPattern ( "yyyy-MM-dd HH:mm:ss.SSSX" ) ) ;
详情
Answer by greg-449 是正确的(使用仅日期对象作为日期时间值)但不是解决方案。
该答案使用LocalDateTime,这会不必要地丢弃有关offset-from-UTC 的有价值信息。 LocalDateTime 确实不代表时间轴上的特定时刻,只是根据适应特定时区的可能时刻的模糊概念。
+02 是offset-from-UTC,意思是“比UTC 提前两个小时”。因此,在 UTC 中,这一同时时刻的时间是 12 小时,比您的 14 小时少 2 小时。这确实代表时间轴上的特定时刻。此偏移量是您使用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 |输入修改: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,然后通过在Timestamp 对象上调用toInstant 立即转换为java.time。
为您的业务逻辑坚持使用 java.time;简单地使用 java.sql 类型,并且仅用于与数据库的交换。