2016-04-05 16 views
24

Die java.util.Date Klasse hat eine Methode namens toInstant(), die die Date Instanz in eine java.time.Instant konvertiert.UnsupportedOperationException - Warum können Sie toInstant() auf einer java.sql.Date nicht aufrufen?

Die java.sql.Date-Klasse erweitert die java.util.Date Klasse, aber wenn ich versuche, toInstant() auf einem java.sql.Date zu nennen, erhalten eine UnsupportedOperationException.

Warum ist toInstant() ein nicht unterstützter Vorgang unter java.sql.Date?

Und was ist der "richtige" Weg, um eine java.sql.Date in eine java.time.Instant zu konvertieren?

Antwort

12

Überprüfen Sie die JavaDoc

Da sql.Date keine Zeitkomponente hat, gibt es keine Möglichkeit, es zu time.Instant

Diese Methode konvertiert immer eine UnsupportedOperationException wirft und sollte nicht, da SQL Datum verwendet werden Werte haben keine Zeitkomponente.

+1

Jetzt ist die Frage _why_ es wurde auf diese Weise entworfen. Man könnte sich vorstellen, dass es standardmäßig mit der Zeitangabe auf 0 gesetzt wird. Es gibt nichts in der Mailingliste. – Tunaki

+2

@Tunaki Die Logik macht mich denken, dass es ist, weil die Elternklasse 'util.Date' eine öffentliche toInstant-Methode hat, die von der Kindklasse nicht verwendet werden sollte. Anstatt "final" zu machen (um die Vererbungslogik beizubehalten), bevorzugten sie die Option, sie zu überschreiben und unbrauchbar zu machen. –

+0

@Tunaki wahrscheinlich, weil, wie Sie darauf hinweisen, jede Konvertierung in einen Instant würde einige Daten willkürlich setzen (Zeit, Zeitzone). – assylias

13

java.sql.Date unterstützt nur Datum, Monat und Jahr. Es unterstützt keine Zeitinformationen.

Deshalb java.sql.Date.toInstant() löst UnsupportedOperationException. Java 8 Instant enthält sowohl Datums- als auch Zeitinformationen.

java.util.Date enthält Datums- und Uhrzeitinformationen, also java.util.Date.toInstant() Funktioniert!

Sie können wie folgt tun:

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

Aktualisiert:

Instant.ofEpochMilli(sqlDate.getTime()); 

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

Wird das gleiche Ergebnis zurück, weil toInstant() aufrufen Instant.ofEpochMilli (getTime()) intern.

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

Was ist "richtiger"? 'Instant.ofEpochMilli (sqlDate.getTime());' oder 'new java.util.Date (sqlDate.getTime()). ToInstant();' –

+0

Sie können java.sql.Date nicht in einen Instant konvertieren Bereitstellen einer Zeitzone Der Aufruf von getTime() bei java.sql.Date ist bedeutungslos. Wie in anderen Kommentaren erwähnt, ist java.sql.Date nur ein LocalDate und repräsentiert keinen Zeitpunkt. –

+0

Ich habe nicht auf Java-SQL-Datum toInstant aufgerufen. Ich habe toInstant am java util date aufgerufen und es ist ok für den Fall. – Loc

9

Die bisher gegebenen Antworten bis auf das Detail konzentrieren sich nun, dass java.sql.Date keine Zeitinformationen hat. Das ist korrekt, aber nicht der tatsächliche oder ausreichende Grund, warum dieser Typ keine direkte Umwandlung in Instant bieten kann. Unglücklicherweise macht der documentation of Java-8 den gleichen Fehler, um Benutzer denken zu lassen, das Problem sei nur wegen fehlender Zeitinformationen.

Konzeptionell entspricht der Typ java.sql.Date einem lokalen Typ. Es modelliert ein Kalenderdatum, das in jeder Region unseres Globus unterschiedlich sein kann. Aber ein Instant ist das gleiche auf unserem Globus herum. Benutzer benötigen also eine Zeitzone oder einen Zeitzonen-Offset, um die Konvertierung durchzuführen.

Tragischerweise erbt der Typ java.sql.Date von java.util.Date, die ein globaler Typ (Instant-like) ist. Diese Vererbung steht jedoch für die Implementierungsvererbung und nicht für die Typvererbung. Ein Grund mehr, das Design dieser alten JDBC-Klassen zu überdenken.Daher ist es in der Tat möglich, den Hack zu verwenden, um die java.sql.Date über seine Methode getTime() in eine Instanz von java.util.Date zu verpacken, die schließlich direkte Umwandlung zu einem Augenblick erlaubt. Aber: Diese Konvertierung verwendet implizit die Standardzeitzone des Systems.

Also, wie man richtig auf pedantische Art und Weise konvertiert? Lassen Sie uns die documentation of Java-8 wieder betrachten hier die in die richtige Richtung:

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

Die korrekte Zuordnung zwischen java.sql.Date und java.time ist LocalDate:

LocalDate date = sqlDate.toLocalDate(); 

Wenn Sie wirklich müssen, können Sie dann eine Instant ableiten , obwohl die zusätzliche Information (Zeit) willkürlich sein wird. Zum Beispiel:

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

Ich wünschte, ich könnte zwei Antworten akzeptieren ... Dies beantwortet den zweiten Teil meiner Frage perfekt, aber die Hauptfrage war, warum Sie 'toInstant()' nicht auf 'java.sql.Date' aufrufen können, also musste ich akzeptiere [@YassinHajaj] (http://stackoverflow.com/users/5050667/yassin-hajaj) 's [antwort] (http://stackoverflow.com/a/36435570/2561365). Diese Antwort benötigt mehr Upvotes. –

Verwandte Themen