不支持操作异常-为什么可以';您不能在java.sql.Date上调用toInstant()?
不支持操作异常-为什么可以';您不能在java.sql.Date上调用toInstant()?,java,java-8,java-time,Java,Java 8,Java Time,java.util.Date类有一个名为toInstant()的方法,该方法将Date实例转换为java.time.Instant java.sql.Date类扩展了java.util.Date类,但是当我试图在java.sql.Date上调用toInstant()时,我收到一个不支持操作异常 为什么toInstant()在java.sql.Date上是不受支持的操作 什么是将java.sql.Date转换为java.time.Instant的“正确”方法 由于sql.Date没有时间组件,因此
java.util.Date
类有一个名为toInstant()
的方法,该方法将Date
实例转换为java.time.Instant
java.sql.Date
类扩展了java.util.Date
类,但是当我试图在java.sql.Date
上调用toInstant()
时,我收到一个不支持操作异常
为什么toInstant()
在java.sql.Date
上是不受支持的操作
什么是将java.sql.Date
转换为java.time.Instant
的“正确”方法
由于sql.Date
没有时间组件,因此无法将其转换为time.Instant
此方法始终引发不支持的OperationException,并且应该
无法使用,因为SQL日期值没有时间组件
仅支持日期组件(日期、月、年)。它不支持时间组件(小时、分钟、秒、毫秒)。需要日期和时间组件,因此toInstant on java.sql.Date实例引发UnsupportedOperationException异常
toInstant Java文档
这种方法总是抛出一个错误
由于SQL日期,因此不应使用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());
}
到目前为止给出的答案都集中在java.sql.Date
没有时间信息的细节上。这是正确的,但不是该类型无法直接转换为即时
的真正或充分原因。不幸的是,他们也犯了同样的错误,让用户认为问题仅仅是因为缺少时间信息
从概念上讲,类型java.sql.Date
表示本地类型。它模拟了一个日历日期,在全球任何地区都可能不同。但在全球范围内,即时
是一样的因此用户需要时区或时区偏移来进行转换。
不幸的是,类型java.sql.Date
继承自java.util.Date
,这是一种全局类型(类似即时)。然而,这种继承实际上表示实现继承,而不是类型继承。考虑这些旧JDBC类的设计将被打破的另一个原因。因此,确实可以使用hack通过其方法getTime()
将java.sql.Date
封装在java.util.Date
的实例中,从而最终允许直接转换为即时。但是:此转换隐式使用系统的默认时区
那么,如何以迂腐的方式正确地转换?让我们再考虑一下,这里指向正确的方向:
java.sql.Date sqlDate = ...;
LocalDate calendarDate = sqlDate.toLocalDate();
ZonedDateTime zdt = calendarDate.atStartOfDay(ZoneId.of("Europe/Paris"));
Instant instant = zdt.toInstant();
java.sql.Date
和java.time
之间的正确映射是LocalDate
:
LocalDate date = sqlDate.toLocalDate();
如果确实需要,则可以派生一个即时
,尽管额外的信息(时间)是任意的。例如:
Instant i = date.atStartOfDay(ZoneOffset.UTC).toInstant();
如果约会中没有时间,请将其转换为毫秒:
Instant.ofEpochMilli(date.getTime())
.atZone(ZoneId.systemDefault())
.toLocalDate();
哪个更“正确”<代码>Instant.ofEpochMilli(sqlDate.getTime())
或新建java.util.Date(sqlDate.getTime()).toInstant()代码>如果不提供时区,则无法将java.sql.Date转换为瞬间。在java.sql.Date上调用getTime()毫无意义。正如在其他评论中指出的,java.sql.Date只是一个LocalDate,并不代表时间上的瞬间。我确实在Javautil日期调用了instant,在这种情况下没有问题。现在,问题是为什么它是这样设计的。可以想象它的默认时间信息设置为0。在邮件列表中找不到任何内容。@Tunaki该逻辑使我认为这是因为父类util.Date
有一个publictoInstant
方法,子类不应使用该方法。因此,他们宁愿选择覆盖它并使其不可用,而不是使其成为最终的(保留继承逻辑)。@Tunaki可能是因为,正如您所指出的,任何转换为瞬间的操作都需要任意设置一些数据(时间、时区)。希望我能接受两个答案。。。这完美地回答了我问题的第二部分,但主要问题是为什么不能在java.sql.Date
上调用toInstant()
,因此我不得不接受的。这个答案需要更多的投票。