简体   繁体   English

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

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

Migrating Joda time to Java 8将 Joda 时间迁移到 Java 8

Joda:乔达:

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

Migrating to Java 8迁移到 Java 8

This is my code;这是我的代码; it does compile;它确实可以编译; I am doubtful if it works:我怀疑它是否有效:

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

In some cases, the date is wrong.在某些情况下,日期是错误的。 Any advice?有什么建议吗?

tl;dr tl;博士

To track a moment in history, use Instant as the type of your class member variable.要跟踪历史中的某个时刻,请使用Instant作为类成员变量的类型。 Specifically, this moment is seen as a date and time-of-day in UTC .具体而言,这一时刻被视为UTC 中的日期和时间。

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

Usage, capturing the current moment.用法,捕捉当前时刻。

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

Usage, populating value from database.用法,从数据库填充值。

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). JDBC 4.2不需要支持Instant (UTC 时间)。 If your driver does not support that class, switch to OffsetDateTime which is required.如果您的驱动程序不支持该类,请切换到所需的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 中的日期时间类型表。

Present to the user, localized for the user-interface.呈现给用户,针对用户界面进行了本地化。

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

Notice that Locale has nothing to do with time zone, an orthogonal issue.请注意, Locale与时区无关,这是一个正交问题。 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 around her, but she prefers to read its textual display in her native French.她想看看周围的新西兰人使用的挂钟时间,但她更喜欢阅读以她的母语法语显示的文字显示。 Both time zone and locale are issues best left to presentation only;时区和区域设置都是最好仅用于演示的问题; generally best to use UTC in the rest of your code.通常最好在其余代码中使用 UTC。 Thus, we defined our member variable createdAt as an Instant , with Instant always being in UTC by definition.因此,我们将成员变量createdAt定义为Instant ,并且Instant根据定义始终使用 UTC。

Avoid java.sql.Timestamp避免java.sql.Timestamp

  • The java.sql.Timestamp , along with java.sql.Date , java.util.Date , and Calendar are all part of the terribly troublesome old date-time classes that were supplanted years ago by the java.time classes. java.sql.Timestamp以及java.sql.Datejava.util.DateCalendar都是多年前被java.time类取代的非常麻烦的旧日期时间类的一部分
  • Joda-Time too is now supplanted by the java.time classes, as stated in the front page of the project's site. Joda-Time现在也被java.time类取代,如项目站点的首页所述。

java.time时间

As of JDBC 4.2 and later, we can directly exchange java.time objects with the database.JDBC 4.2及更高版本开始,我们可以直接与数据库交换java.time对象。

Instant

Send the current moment to the database using Instant class.使用Instant类将当前时刻发送到数据库。 The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction). Instant类表示UTC时间轴上的一个时刻,分辨率为纳秒(最多九 (9) 位小数)。

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

And retrieval.和检索。

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

ZonedDateTime

To see that same moment through the lens of the wall-clock time used by the people of a particular region (a time zone), apply a ZoneId to get a ZonedDateTime .要通过特定地区(时区)的人们使用的挂钟时间的镜头查看同一时刻,请应用ZoneId以获取ZonedDateTime

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

LocalDateTime is not a moment LocalDateTime不是片刻

.toLocalDateTime(). .toLocalDateTime()。

Never involve LocalDateTime class when representing a specific moment in time.在表示特定时刻时,切勿涉及LocalDateTime类。 The class purposely lacks any concept of time zone or offset-from-UTC.该类故意缺少时区或UTC 偏移量的任何概念。 As such, it cannot represent a moment, is not a point on the timeline.因此,它不能代表一个时刻,也不是时间线上的一个点。 It is a vague idea about potential moments along a range of about 26-27 hours (the range of time zones).这是关于大约 26-27 小时范围内(时区范围)的潜在时刻的模糊概念。


About java.time关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于 Java 8 及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat .这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar ,和SimpleDateFormat

To learn more, see the Oracle Tutorial .要了解更多信息,请参阅Oracle 教程 And search Stack Overflow for many examples and explanations.并在 Stack Overflow 上搜索许多示例和解释。 Specification is JSR 310 .规范是JSR 310

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes.现在处于维护模式Joda-Time项目建议迁移到java.time类。

You may exchange java.time objects directly with your database.您可以直接与您的数据库交换java.time对象。 Use a JDBC driver compliant with JDBC 4.2 or later.使用符合JDBC 4.2或更高版本的JDBC 驱动程序 No need for strings, no need for java.sql.* classes.不需要字符串,不需要java.sql.*类。 Hibernate 5 & JPA 2.2 support java.time . Hibernate 5 & JPA 2.2 支持java.time

Where to obtain the java.time classes?从哪里获得 java.time 类?

这似乎有效:-

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

Use the following:使用以下内容:

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

You need to use aZoneId appropriate to the region (you may try with ZoneId.systemDefault() for a start).您需要使用适合该地区的ZoneId (您可以尝试使用ZoneId.systemDefault()开始)。

For more details about the differences between various Java-Time APIs, see this great answer .有关各种 Java-Time API 之间差异的更多详细信息,请参阅这个很好的答案

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

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