Auf Mikrosekunden kürzen
Offensichtlich können wir die Nanosekunden
nicht quetschen Auflösung eines Instant
in die Mikrosekunden
Auflösung der MySQL-Datentypen DateTime
und Timestamp
.
Obwohl ich MySQL nicht verwende, stelle ich mir den JDBC-Treiber
vor wurde entwickelt, um die Nanosekunden beim Empfang eines Instant
zu ignorieren , wodurch der Wert auf Mikrosekunden gekürzt wird. Ich schlage vor, dass Sie ein Experiment durchführen, um den Quellcode Ihres Treibers zu sehen und vielleicht zu untersuchen, der mit JDBC 4.2 und höher kompatibel ist.
Instant instant = Instant.now().with( ChronoField.NANO_OF_SECOND , 123_456_789L ) ; //Set the fractional second to a spefic number of nanoseconds.
myPreparedStatement.setObject( … , instant ) ;
…und…
Instant instant2 = myResultSet.getObject( … , Instant.class ) ;
Die JDBC 4.2-Spezifikation
erfordert Unterstützung für OffsetDateTime
erfordert aber seltsamerweise nicht die beiden häufiger verwendeten Typen Instant
und ZonedDateTime
. Wenn Ihr JDBC-Treiber
unterstützt Instant
nicht , konvertieren.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ; // Use `OffsetDateTime` if your JDBC driver does not support `Instant`.
Instant instant2 = odt.toInstant() ; // Convert from `OffsetDateTime` to `Instant`.
Dann vergleichen.
Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;
Sie sind vernünftigerweise besorgt darüber, dass aus der Datenbank gezogene Werte nicht mit dem ursprünglichen Wert übereinstimmen. Eine Lösung, sofern dies für Ihr Geschäftsproblem akzeptabel ist, besteht darin, alle Nanosekunden in Ihren Originaldaten auf Mikrosekunden zu kürzen. Ich empfehle diesen Ansatz allgemein.
Die java.time Klassen bieten einen truncatedTo
Methode. Übergeben Sie eine ChronoUnit
enum-Objekt, um die Granularität anzugeben. In diesem Fall wäre das ChronoUnit.MICROS
.
Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;
Derzeit sollte dieser Ansatz ausreichen, da Sie wahrscheinlich keine Nanosekunden in Ihren Daten haben. Mainstream-Computer haben heute keine Hardware-Uhren, die Nanosekunden erfassen können, soweit ich weiß.
Zählung ab Epoche
Wenn Sie es sich nicht leisten können, eventuell vorhandene Nanosekundendaten zu verlieren, verwenden Sie eine Zählung ab Epoche.
Ich rate normalerweise davon ab, Datum und Uhrzeit als Zählung von einem Epochenbezugsdatum zu verfolgen. Aber Sie haben nur wenige andere Möglichkeiten, Ihre Nanosekunden-basierten Werte in einer Datenbank wie MySQL und Postgres zu speichern, die auf Mikrosekunden-basierte Werte beschränkt sind.
Ganzzahlpaar speichern
Anstatt die extrem große Anzahl von Nanosekunden seit einer Epoche wie 1970-01-01T00:00Z zu verwenden, schlage ich vor, dem Ansatz zu folgen, der von den Interna des Instant
verfolgt wird Klasse:Verwenden Sie ein Paar von Zahlen.
Speichern Sie eine Anzahl von ganzen Sekunden als Integer in Ihrer Datenbank. Speichern Sie in einer zweiten Spalte als Ganzzahl die Anzahl der Nanosekunden im Bruchteil einer Sekunde.
Sie können diese Zahlen einfach aus/in einen Instant
extrahieren/injizieren Objekt. Nur einfache 64-Bit long
Zahlen sind beteiligt; keine Notwendigkeit für BigDecimal
oder BigInteger
. Ich nehme an, Sie können möglicherweise eine 32-Bit-Ganzzahlspalte für mindestens eine der beiden Zahlen verwenden. Aber ich würde der Einfachheit halber und für die direkte Kompatibilität mit java.time.Instant
64-Bit-Integer-Spaltentypen wählen Klasse’ Paar Longs.
long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;
…und…
Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;
Wenn Sie chronologisch sortieren, müssen Sie eine mehrstufige Sortierung durchführen, zuerst nach der Spalte „ganze Sekunden“ und dann sekundär nach der Spalte „Nanos Bruchteile von Sekunden“.