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

Convert java.sql.Timestamp to Java 8 ZonedDateTime?

将 Joda 时间迁移到 Java8

乔达:

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")));

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

使用以下内容:

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

您需要先使用 ZoneId appropriate to the region (you may try with ZoneId.systemDefault()

有关各种 Java-Time API 之间差异的详细信息,请参阅

tl;博士

要跟踪历史时刻,请使用 Instant as the type of your class member variable. Specifically, this moment is seen as a date and time-of-day in 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 does not require support for Instant (a moment in UTC). If your driver does not support that class, switch to 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). 

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

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 has nothing to do with time zone, an orthogonal issue. The code above might be for a business person from Québec who is traveling in New Zealand. She wants to see the wall-clock time used by the kiwis,但她更喜欢阅读以母语法语显示的文本。时区和地区都是最好留给演示的问题;通常最好在其余代码中使用 UTC。因此,我们将成员变量 createdAt 定义为 Instant,根据定义,Instant 始终采用 UTC。

避免java.sql.Timestamp

  • java.sql.Timestampjava.sql.Datejava.util.DateCalendar 都是非常麻烦的旧日期时间 classes 的一部分多年前被 java.time classes.
  • 取代
  • Joda-Time 现在也被 java.time class 所取代,如项目网站首页所述。

java.time

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

Instant

使用 Instant class 将当前时刻发送到数据库。 Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds(最多九 (9) 位小数)。

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

并检索。

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

ZonedDateTime

要通过特定地区(时区)人们使用的挂钟时间的镜头看到同一时刻,请应用 ZoneId to get a ZonedDateTime

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

LocalDateTime 不是片刻

.toLocalDateTime().

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


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

Joda-Time项目,现在处于维护模式,建议迁移到java.timeclasses.

您可以直接与您的数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes。 Hibernate 5 和 JPA 2.2 支持 java.time.

在哪里获取 java.time classes?

这似乎有效:-

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