将java.sql.Timestamp转换为Java 8 ZonedDateTime吗?

时间:2018-07-16 18:52:07

标签: java sql java-8 java-time zoneddatetime

将Joda时间迁移到Java 8

Joda:

UserObject user = new UserObject()
user.setCreatedAt(new DateTime(rs.getTimestamp("columnName")));`

迁移到Java 8

这是我的代码;它确实可以编译;我怀疑它是否有效:

ZonedDateTime.ofInstant(rs.getTimestamp("columnName").toLocalDateTime().toInstant(ZoneOffset.UTC),ZoneId.of("UTC")));

在某些情况下,日期是错误的。有什么建议吗?

3 个答案:

答案 0 :(得分:7)

tl; dr

要跟踪历史记录,请使用Instant作为类成员变量的类型。具体来说,此刻被视为UTC中的日期和时间。

public class UserObject() {
    Instant createdAt ;
    …
    public void setCreatedAt( Instant instantArg ) {
        this.createdAt = instantArg ;
    {
}

用法,捕获当前时刻。

UserObject user = new UserObject() ;
user.setCreatedAt( Instant.now() ) ;

用法,从数据库中填充值。

UserObject user = new UserObject() ;
Instant instant = myResultSet.getObject( "when_created" , Instant.class ) ;
user.setCreatedAt( instant ) ;

JDBC 4.2不需要支持Instant(在UTC中是一刻)。如果您的驱动程序不支持该类,请切换至OffsetDateTime

UserObject user = new UserObject() ;
OffsetDateTime odt = myResultSet.getObject( "when_created" , OffsetDateTime.class ) ;  
user.setCreatedAt( odt.toInstant() ) ;  // Convert from an `OffsetDateTime` (for any offset-from-UTC) to `Instant` (always in UTC). 

Table of date-time types in Java (both modern and legacy) and in standard SQL.

呈现给用户,已针对用户界面进行本地化。

user               // Your business object.
.getCreatedAt()    // Returns a `Instant` object.
.atZone(           // Adjust from UTC to a time zone. Same moment, same point on the timeline, different wall-clock time.
    ZoneId.of( "Pacific/Auckland" )  // Specify the user’s desired/expected time zone.
)                  // Returns a `ZonedDateTime` object. 
.format(           // Generate a `String` representing the value of date-time object.
    DateTimeFormatter.ofLocalizedDateTime(
        FormatStyle.FULL   // Specify how long or abbreviated the string.
    )
    .withLocale(   // Specify `Locale` to determine human language and cultural norms for localization.
        Locale.CANADA_FRENCH 
    )
)                  // Returns a `String`.

请注意,Locale与时区无关,这是一个正交的问题。上面的代码可能适用于Québec中来往New Zealand的商务人士。她想看看周围的kiwis所使用的挂钟时间,但是她更喜欢用她的母语法语阅读其文字显示。时区和区域设置都是最好只留给演讲的问题;通常最好在其余代码中使用UTC。因此,我们将成员变量createdAt定义为Instant,根据定义,Instant始终使用UTC。

避免使用java.sql.Timestamp

  • java.sql.Timestamp以及java.sql.Datejava.util.DateCalendar都是几年前被< em> java.time 类。
  • 如项目站点首页所述,
  • Joda-Time现在也被 java.time 类所取代。

java.time

JDBC 4.2起,我们可以直接与数据库交换 java.time 对象。

Instant

使用Instant类将当前时刻发送到数据库。 Instant类表示UTC中时间轴上的时刻,分辨率为nanoseconds(十进制小数的九(9)位)。

Instant instant = Instant.now() ;  // Capture the current moment in UTC.
myPreparedStatement.setObject( … , instant ) ;

和检索。

Instant instant = myResultSet.getObject( … , Instant.class ) ;

ZonedDateTime

要通过特定区域(时区)的人们所使用的挂钟时间来查看同一时刻,请应用ZoneId以获得ZonedDateTime

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

LocalDateTime暂时不是

  

.toLocalDateTime()。

代表特定时间点时,切勿参与LocalDateTime 课堂。该类故意缺少任何时区或从UTC偏移的概念。因此,它不能表示时刻,不是时间线上的一点。关于沿大约26-27小时(时区的范围)内的潜在时刻,这是一个模糊的想法。


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

答案 1 :(得分:2)

这似乎可行:-

ZonedDateTime.ofInstant(rs.getTimestamp("columnname").toInstant(), ZoneId.of("UTC"))

答案 2 :(得分:1)

使用以下内容:

rs.getTimestamp("columnName").toInstant()
    .atZone(ZoneId.[appropriate-zone-ID-here])

您需要使用适合该地区的ZoneId(可以尝试使用ZoneId.systemDefault()作为开始)。

有关各种Java-Time API之间差异的更多详细信息,请参见this great answer