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
以获取Instant
或OffsetDateTime
. 如果没有,调用ResultSet::getTimestamp
获取 a ,然后通过调用Timestamp 对象java.sql.Timestamp
立即转换为 java.time 。toInstant
坚持使用 java.time 作为您的业务逻辑;简单地使用 java.sql 类型并且仅用于与数据库的交换。