Afkappen tot microseconden
Het is duidelijk dat we de nanoseconden
niet kunnen persen resolutie van een Instant
in de microseconden
resolutie van de MySQL-gegevenstypen DateTime
en Timestamp
.
Hoewel ik MySQL niet gebruik, stel ik me de JDBC-stuurprogramma
voor is gebouwd om de nanoseconden te negeren bij het ontvangen van een Instant
, waarbij de waarde wordt afgekapt tot microseconden. Ik stel voor dat u een experiment probeert om de broncode van uw stuurprogramma te bekijken en misschien te onderzoeken die voldoet aan JDBC 4.2 en hoger.
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 ) ;
…en…
Instant instant2 = myResultSet.getObject( … , Instant.class ) ;
De JDBC 4.2-specificatie
vereist ondersteuning voor OffsetDateTime
maar vereist vreemd genoeg niet de twee meest gebruikte typen, Instant
en ZonedDateTime
. Als uw JDBC-stuurprogramma
ondersteunt Instant
niet , converteren.
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`.
Vergelijk dan.
Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;
U maakt zich wijselijk zorgen over waarden uit de database die niet overeenkomen met de oorspronkelijke waarde. Een oplossing, indien acceptabel voor uw zakelijke probleem, is om eventuele nanoseconden in microseconden in uw oorspronkelijke gegevens af te kappen. Ik raad deze aanpak in het algemeen aan.
De java.time klassen bieden een truncatedTo
methode. Geef een ChronoUnit
door enum object om de granulariteit op te geven. In dit geval is dat ChronoUnit.MICROS
.
Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;
Momenteel zou deze benadering moeten volstaan, aangezien het onwaarschijnlijk is dat u nanoseconden in uw gegevens zult hebben. Reguliere computers hebben tegenwoordig geen hardwareklokken die nanoseconden kunnen vastleggen, voor zover ik weet.
Tellen vanaf tijdperk
Als je het je niet kunt veroorloven om eventuele nanoseconde gegevens te verliezen, gebruik dan een telling vanaf tijdperk.
Ik raad het meestal af om datum-tijd te volgen als een telling vanaf een epoche-referentiedatum. Maar u hebt weinig andere keuzes bij het opslaan van uw op nanoseconden gebaseerde waarden in een database zoals MySQL en Postgres die beperkt is tot op microseconden gebaseerde waarden.
Bewaar paar gehele getallen
In plaats van het extreem grote aantal nanoseconden te gebruiken sinds een tijdperk zoals 1970-01-01T00:00Z, raad ik aan de benadering te volgen die is gevolgd door de interne onderdelen van de Instant
klasse:gebruik een paar aantal cijfers.
Bewaar een aantal hele seconden als een geheel getal in uw database. Sla in een tweede kolom als een geheel getal het aantal nanoseconden in de fractionele seconde op.
U kunt deze nummers eenvoudig extraheren/injecteren van/naar een Instant
voorwerp. Alleen eenvoudige 64-bits long
cijfers zijn betrokken; geen behoefte aan BigDecimal
of BigInteger
. Ik veronderstel dat je een 32-bits integerkolom kunt gebruiken voor ten minste één van de twee getallen. Maar ik zou kiezen voor 64-bits integer-kolomtypen voor eenvoud en voor directe compatibiliteit met de java.time.Instant
klasse' paar longs.
long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;
…en…
Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;
Als u chronologisch sorteert, moet u sorteren op meerdere niveaus, eerst sorteren op de hele secondenkolom en vervolgens secundair sorteren op de nanos-fractie-van-secondekolom.