UnsupportedOperationException - Why can't you call toInstant() on a java.sql.Date?

梦想与她 提交于 2019-11-29 10:33:19

问题


The java.util.Date class has a method called toInstant() that converts the Date instance to a java.time.Instant.

The java.sql.Date class extends the java.util.Date class, but when I attempt to call toInstant() on a java.sql.Date, I receive an UnsupportedOperationException.

Why is toInstant() an unsupported operation on java.sql.Date?

And what is the "correct" way to convert a java.sql.Date to a java.time.Instant?


回答1:


Check the JavaDoc

Since sql.Date does not have a time component, there is no possibility to convert it to time.Instant

This method always throws an UnsupportedOperationException and should not be used because SQL Date values do not have a time component.




回答2:


The correct mapping between java.sql.Date and java.time is LocalDate:

LocalDate date = sqlDate.toLocalDate();

If you really must, you can then derive an Instant, although the extra information (time) will be arbitrary. For example:

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



回答3:


java.sql.Date supports only Date components (date, month, year). It does NOT support time components (hour, minute, second, millisecond). toInstant requires both Date and Time components so toInstant on java.sql.Date instance throws UnsupportedOperationException exception.

toInstant Java doc

This method always throws an UnsupportedOperationException and should not be used because SQL Date values do not have a time component.

java.util.Date OR java.sql.Timestamp has both Date/Time components so toInstant() works!

You can do like this:

// Time is 00:00:00.000

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

Updated:

Instant.ofEpochMilli(sqlDate.getTime());

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

Will return the same result because toInstant() call Instant.ofEpochMilli(getTime()) internally.

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



回答4:


The answers given so far until now concentrate on the detail that java.sql.Date has no time information. That is correct but not the real or sufficient reason why this type cannot offer a direct conversion to Instant. Unfortunatly the documentation of Java-8 does make the same mistake to let users think the problem is just because of missing time information.

Conceptually, the type java.sql.Date represents a local type. It models a calendar date which can be different in any region of our globe. But an Instant is the same on our globe around. So users need a timezone or a timezone offset to do the conversion.

Tragically, the type java.sql.Date inherits from java.util.Date which is a global type (instant-like). However, this inheritance really denotes implementation inheritance, and not type inheritance. One more reason to consider the design of these old JDBC-classes to be broken. Therefore it is indeed possible to use the hack to wrap the java.sql.Date via its method getTime() inside an instance of java.util.Date which finally allows direct conversion to an instant. But: This conversion implicitly uses the default timezone of the system.

So how to correctly convert in a pedantic way? Let's consider the documentation of Java-8 again which here points into the right direction:

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


来源:https://stackoverflow.com/questions/36435492/unsupportedoperationexception-why-cant-you-call-toinstant-on-a-java-sql-dat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!