繁体   English   中英

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

[英]Convert java.sql.Timestamp to Java 8 ZonedDateTime?

将 Joda 时间迁移到 Java 8

乔达:

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

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

tl;博士

要跟踪历史中的某个时刻,请使用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). 

Java(现代和传统)和标准 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与时区无关,这是一个正交问题。 上面的代码可能适用于在新西兰旅行的魁北克商务人士。 她想看看周围的新西兰人使用的挂钟时间,但她更喜欢阅读以她的母语法语显示的文字显示。 时区和区域设置都是最好仅用于演示的问题; 通常最好在其余代码中使用 UTC。 因此,我们将成员变量createdAt定义为Instant ,并且Instant根据定义始终使用 UTC。

避免java.sql.Timestamp

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

时间

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

Instant

使用Instant类将当前时刻发送到数据库。 Instant类表示UTC时间轴上的一个时刻,分辨率为纳秒(最多九 (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 及更高版本中。 这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar ,和SimpleDateFormat

要了解更多信息,请参阅Oracle 教程 并在 Stack Overflow 上搜索许多示例和解释。 规范是JSR 310

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

您可以直接与您的数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC 驱动程序 不需要字符串,不需要java.sql.*类。 Hibernate 5 & JPA 2.2 支持java.time

从哪里获得 java.time 类?

这似乎有效:-

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

使用以下内容:

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

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

有关各种 Java-Time API 之间差异的更多详细信息,请参阅这个很好的答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM