tl;博士
对于TIMESTAMP WITHOUT TIME ZONE类型的数据库列。
myPreparedStatement // As of JDBC 4.2, send/receive java.time objects to/from your database.
.setObject( // Call `PreparedStatement::setObject` and `ResultSet::getObject` for java.time objects.
… , // Fill-in to indicate which placeholder in SQL statement.
LocalDateTime.of( // Represent a date with time-of-day, but lacking in zone/offset so NOT a moment, NOT a point on the timeline.
LocalDate.parse( "2018-01-23" ) , // Parse the date-only value.
LocalTime.parse( "21:54" ) // Parse the time-of-day.
) // Returns a `LocalDateTime` object.
)
对于TIMESTAMP WITH TIME ZONE类型的数据库列。
myPreparedStatement // As of JDBC 4.2, send/receive java.time objects to/from your database.
.setObject( // Call `PreparedStatement::setObject` and `ResultSet::getObject` for java.time objects.
… , // Fill-in to indicate which placeholder in SQL statement.
LocalDateTime.of( // Represent a date with time-of-day, but lacking in zone/offset so NOT a moment, NOT a point on the timeline.
LocalDate.parse( "2018-01-23" ) , // Parse the date-only value.
LocalTime.parse( "21:54" ) // Parse the time-of-day.
) // Returns a `LocalDateTime` object.
.atZone( // Assign a time zone to make a moment.
ZoneId.of( "Pacific/Auckland" ) // Real time zones have a proper name in `Continent/Region` format. Never use 2-4 letter pseudo-zones such as `PDT`, `IST`, `CST`, etc.
) // Returns a `ZonedDateTime` object.
.toOffsetDateTime() // Strip out the time zone, leaving only a mere offset-from-UTC (a number of hours-minutes-seconds). Returns a `OffsetDateTime` object.
.withOffsetSameInstant( // Adjust the offset-from-UTC to UTC itself (an offset of zero). Same moment, different wall-clock time.
ZoneOffset.UTC
) // Returns another `OffsetDateTime` object.
)
java.time
现代方法使用 java.time 类,多年前取代了可怕的旧遗留类(Calendar、Date、SimpleDateFormat 等)。
LocalDate
LocalDate 类表示仅日期值,没有时间,也没有 time zone 或 offset-from-UTC。
文本中仅日期值的常见 SQL 格式是 YYYY-MM-DD。这也是 ISO 8601 标准定义的格式。 java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。所以不需要指定格式模式。
LocalDate ld = LocalDate.parse( "2018-01-23" ) ;
类似于 HH:MM 格式的字符串,表示一天中的小时和分钟。
LocalTime lt = LocalTime.parse( "21:54" ) ;
结合日期和时间。
LocalDateTime ldt = LocalDateTime.of( ld , lt ) ;
ldt.toString(): 2018-01-23T21:54
请注意,LocalDateTime,故意缺少任何时区概念或与 UTC 的偏移,不是片刻,不是在时间线。因此,只适合在类似于 SQL 标准 TIMESTAMP WITHOUT TIME ZONE 的数据类型的列中保存到数据库。
JDBC 4.2
从 JDBC 4.2 开始,我们可以通过 setObject 和 getObject 直接与数据库交换 java.time 对象。
myPreparedStatement.setObject( … , ldt ) ;
检索。
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
ZonedDateTime
如果您想处理时间轴上的时刻、实际点,请使用适当的 Java 类(Instant、OffsetDateTime、ZonedDateTime)。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
OffsetDateTime
现在我们有时间了。通常在移动日期(例如传输到数据库)时最好关注 UTC。
OffsetDateTime odtUtc = zdt.toOffsetDateTime().withOffset( ZoneOffset.UTC ) ;
发送到数据库。
myPreparedStatement.setObject( … , odtUtc ) ;
检索。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
关于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 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。