UnsupportedOperationException - 为什么不能在java.sql.Date上调用onInstant()?

时间:2016-04-05 19:35:05

标签: java java-8 java-time

java.util.Date类有一个名为toInstant()的方法,可将Date个实例转换为java.time.Instant

java.sql.Date课程扩展了java.util.Date课程,但当我尝试在toInstant()上致电java.sql.Date时,我收到了UnsupportedOperationException

为什么toInstant()上的java.sql.Date操作不受支持?

java.sql.Date转换为java.time.Instant的“正确”方式是什么?

5 个答案:

答案 0 :(得分:33)

java.sql.Datejava.time之间的正确映射为LocalDate

LocalDate date = sqlDate.toLocalDate();

如果您真的必须,那么您可以派生Instant,但额外信息(时间)将是任意的。例如:

Instant i = date.atStartOfDay(ZoneOffset.UTC).toInstant();

答案 1 :(得分:23)

检查JavaDoc

由于sql.Date没有时间成分,因此无法将其转换为time.Instant

  

此方法始终抛出UnsupportedOperationException并且应该   不能使用,因为SQL Date值没有时间组件。

答案 2 :(得分:22)

java.sql.Date只有Date组件(日期,月份和年份)。它没有Date&时间成分。 toInstant需要Date / Time组件,因此java.sql.Date实例上的toInstant抛出UnsupportedOperationException异常。

java.util.Date或java.sql.Timestamp同时具有日期/时间组件,因此toInstant()可以工作!

你可以这样做:

// Time is 00:00:00.000

new java.util.Date(sqlDate.getTime()).toInstant() 

<强>更新

Instant.ofEpochMilli(sqlDate.getTime());

// OR
new java.util.Date(sqlDate.getTime()).toInstant();

将返回相同的结果,因为toInstant()在内部调用Instant.ofEpochMilli(getTime())。

public Instant toInstant() {
    return Instant.ofEpochMilli(getTime());
}

答案 3 :(得分:13)

到目前为止给出的答案直到现在都集中在java.sql.Date没有时间信息的细节上。这是正确的,但不是这种类型无法直接转换为Instant的真实或充分理由。不幸的是,documentation of Java-8确实犯了同样的错误,让用户认为问题仅仅是因为缺少时间信息。

从概念上讲,类型java.sql.Date表示本地类型。它模拟了一个日历日期,它可以在我们全球任何地区都不同。但Instant在我们的地球上是相同的。 因此用户需要时区或时区偏移来进行转换。

可悲的是,类型java.sql.Date继承自java.util.Date,这是一种全局类型(类似即时)。但是,此继承实际上表示实现继承,而不是类型继承。考虑破坏这些旧JDBC类的设计的另一个原因。因此,确实可以使用hack通过其java.sql.Date方法将getTime()包装在java.util.Date的实例中,最终允许直接转换为瞬间。但是:此转换隐式使用系统的默认时区。

那么如何以迂腐的方式正确转换呢?让我们再次考虑documentation of Java-8这里指向正确的方向:

java.sql.Date sqlDate = ...;
LocalDate calendarDate = sqlDate.toLocalDate();
ZonedDateTime zdt = calendarDate.atStartOfDay(ZoneId.of("Europe/Paris"));
Instant instant = zdt.toInstant();

答案 4 :(得分:3)

如果您的日期中没有时间 - 将其转换为毫秒:

Instant.ofEpochMilli(date.getTime())
   .atZone(ZoneId.systemDefault())
   .toLocalDate();