tl;博士
org.threeten.bp.OffsetDateTime odt =
OffsetDateTime.parse(
"2012-02-12T09:08:13.123456-0400",
org.threeten.bp.format.DateTimeFormatter.ofPattern( "yyyy-MM-dd'T'HH:mm:ssZ" ) // Specify pattern as workaround for Java 8 bug in failing to parse if optional colon is not present.
)
;
使用 java.time
您应该检索一个对象,一个日期时间对象,特别是一个 java.time 对象,而不是从您的数据库中接收一个字符串。
java.time 类取代了麻烦的旧日期时间类,包括java.sql.Timestamp。如果您的JDBC driver 支持 JDBC 4.2 及更高版本,您可以直接传递和接收 java.time 对象。
Instant
Instant 类表示UTC 中时间轴上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。所以这相当于java.sql.Timestamp,包括对您输入数据的六位数微秒的支持,因此根据您的问题的要求不会丢失精度。
Instant instant = myResultSet.getObject( … , Instant.class ) ;
instant.toString(): 2012-02-12T13:08:13.123456Z
ZonedDateTime
如果您想通过特定地区挂钟时间的镜头看到同一时刻,请应用 ZoneId 以获取 ZonedDateTime 对象。
ZoneId z = ZoneId.of( "America/St_Thomas" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2012-02-12T09:08:13.123456-04:00[美国/St_Thomas]
OffsetDateTime
关于如何将字符串2012-02-12T09:08:13.123456-0400 理解为日期时间值的直接问题,请解析为OffsetDateTime。
时区的名称格式为continent/region,表示过去、现在和未来因夏令时 (DST) 等异常情况导致的区域偏移量变化的历史记录。我们知道您的字符串的时区,所以我们使用OffsetDateTime 而不是ZonedDateTime。
OffsetDateTime odt = OffsetDateTime.parse( "2012-02-12T09:08:13.123456-0400" ) ;
嗯,上面的那行代码应该 可以工作,但是在Java 8 中,在解析缺少小时和分钟之间的可选冒号字符的偏移时存在一个小错误。所以 Java 8 中的 -04:00 将解析但不会解析 -0400。 Java 9 中修复的错误。您的 String 确实符合 java.time 类中默认使用的日期时间格式的 ISO 8601 标准。提示:通常最好始终使用冒号、小时/分钟和填充零来格式化偏移量——我见过其他协议和库只需要这种完整格式。
在您迁移到 Java 9 之前,请明确指定格式化模式,而不是依赖隐式默认模式,作为解决此错误的方法。
OffsetDateTime odt =
OffsetDateTime.parse(
"2012-02-12T09:08:13.123456-0400",
DateTimeFormatter.ofPattern( "yyyy-MM-dd'T'HH:mm:ssZ" ) // Specify pattern as workaround for Java 8 bug in failing to parse if optional colon is not present.
)
;
转换
如果您的 JDBC 驱动程序尚未与 JDBC 4.2 兼容,请检索 java.sql.Timestamp 对象,仅供简要使用。使用添加到旧日期时间类的新方法立即转换为 java.time。
java.sql.Timestamp ts = myResultSet.getTimestamp( … ) ;
Instant instant = ts.toInstant();
继续在 java.time 类中执行您的业务逻辑。要将日期时间发送回数据库,请将 Instant 转换为 java.sql.Timestamp。
myPreparedStatement.setTimestamp( … , java.sql.Timestamp.from( instant ) ) ;
Java 6 和 7
在 Java 6 和 7 中,上述概念仍然适用,但 java.time 不是内置的。请改用ThreeTen-Backport 库。要获得,请参阅下面的项目符号。
在 Java 7 中,您不能使用 JDBC 4.2 功能。所以我们不能通过 JDBC 驱动直接从数据库中访问 java.time 对象。如上所示,我们必须从Instant 转换为java.sql.Timestamp。调用实用方法DateTimeUtils.toInstant(Timestamp sqlTimestamp) & DateTimeUtils.toSqlTimestamp(Instant instant)。
java.sql.Timestamp ts = myResultSet.getTimestamp( … ) ;
Instant instant = DateTimeUtils.toInstant( ts ) ;
……和……
java.sql.Timestamp ts = DateTimeUtils.toSqlTimestamp( instant ) ;
myPreparedStatement.setTimestamp( … , ts ) ;
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。