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
的“正确”方式是什么?
答案 0 :(得分:33)
java.sql.Date
和java.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();