Java 8 ZonedDateTime 或 OffsetDateTime 替换 Joda DateTime

Java 8 ZonedDateTime or OffsetDateTime to replace Joda DateTime

在 Java8 之前,我使用 Joda 的 DateTime class 来包含时区信息,我可以轻松地在 DateTime 和 sql [=15] 之间进行转换=].

迁移到 Java8 后,我应该替换哪个 class? OffsetDateTimeZonedDateTime?

此外,我尝试使用 OffsetDateTime,但它似乎无法从 sql Timestamp.

构造回 OffsetDateTime

对于 Joda DateTimeTimestamp 转换器,代码如下:

val joda = DateTime.now()
val sqlJoda = new Timestamp(joda.getMillis)
val jodaBack = new DateTime(sqlJoda)

但是 Java8,

val java8 = OffsetDateTime.now()
val sqlJava8 = new Timestamp(java8.toInstant.toEpochMilli)
val java8Back = ???

有人对此有一些想法吗?看来乔达DateTime真的不错

使用 java.time 中的 Java 8 API 您可以执行以下操作:

long ms_since_epoch = 1_500_000_000_000L;
Instant instant = Instant.ofEpochMilli(ms_since_epoch);

// convert milliseconds in UTC to date
OffsetDateTime dateUTC = OffsetDateTime.ofInstant(instant, ZoneOffset.UTC);

使用您的约定:

val java8 = OffsetDateTime.now()
val sqlJava8 = new Timestamp(java8.toInstant.toEpochMilli)
val java8Back = OffsetDateTime.ofInstant(sqlJava8.toInstant(), ZoneOffset.UTC);

您可以使用 ZonedDateTime。这是我用来来回转换为 Timestamp 的一些示例代码。

public ZonedDateTime from(Timestamp timestamp) {
    if (timestamp == null) {
        return null;
    }
    final ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(timestamp.toInstant(), ZoneId.of("UTC"));
    return zonedDateTime;
}

public Timestamp to(ZonedDateTime zonedDateTime) {
    if (zonedDateTime == null) {
        return null;
    }
    final Timestamp timestamp = Timestamp.valueOf(zonedDateTime.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime());
    return timestamp;
}

请注意,我在数据库中以 UTC 格式存储日期时间。

我假设您的数据库类型是 timestamp with time zone。如果它是 timestamp without timezone 您将需要不同的类型/转换机制。

JDBC 4.2 spec 建议将 timestamp with time zone 映射到 OffsetDateTime。以下是如何在 OffsetDateTimejava.sql.Timestamp.

之间进行转换
  • OffsetDateTimeTimestamp:

    Timestamp ts = ...;
    OffsetDateTime odt = OffsetDateTime.ofInstant(ts.toInstant(), ZoneId.systemDefault());
    
  • TimestampOffsetDateTime:

    OffsetDateTime odt = ...;
    Timestamp ts = Timestamp.from(odt.toInstant());