将java.sql.Timestamp转换为Java 8 ZonedDateTime?tl;博士避免java.sql.Timestamp 关于 java.time

2022-09-01 22:19:40

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

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


答案 1

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 不需要支持即时(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`.

请注意,区域设置与时区无关,时区是一个正交问题。上述代码可能适用于在新西兰旅行的魁北克商务人士。她想看看她周围的新西兰人使用的挂钟时间,但她更喜欢用她的母语法语阅读它的文本显示。时区和区域设置都是最好只由演示的问题;通常最好在代码的其余部分使用 UTC。因此,我们将成员变量定义为 ,根据定义始终处于 UTC 状态。createdAtInstantInstant

避免java.sql.Timestamp

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

java.time

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

Instant

使用类将当前时刻发送到数据库。Instant 类以 UTC 格式表示时间轴上的某个时刻,分辨率为纳秒(最多九 (9) 位小数)。Instant

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.DateCalendarSimpleDateFormat

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

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

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

从哪里获取 java.time 类?


答案 2

这似乎有效:-

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

推荐