Trunker til mikrosekunder
Vi kan naturligvis ikke presse nanosekunderne
opløsning af en Instant
ind i mikroseconds
opløsning af MySQL-datatyperne DateTime
og Timestamp
.
Selvom jeg ikke bruger MySQL, forestiller jeg mig JDBC-driveren
er bygget til at ignorere nanosekunderne, når du modtager en Instant
, afkorter værdien til mikrosekunder. Jeg foreslår, at du prøver et eksperiment for at se, og måske undersøger kildekoden til din driver, der overholder JDBC 4.2 og nyere.
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 ) ;
…og…
Instant instant2 = myResultSet.getObject( … , Instant.class ) ;
JDBC 4.2-specifikationen
kræver understøttelse af OffsetDateTime
men kræver mærkeligt nok ikke de to mere almindeligt anvendte typer, Instant
og ZonedDateTime
. Hvis din JDBC-driver
understøtter ikke Instant
, konverter.
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`.
Sammenlign derefter.
Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;
Du er klogt bekymret over værdier hentet fra databasen, der ikke matcher den oprindelige værdi. En løsning, hvis den er acceptabel for dit forretningsproblem, er at afkorte eventuelle nanosekunder til mikrosekunder i dine originale data. Jeg anbefaler generelt denne tilgang.
java.time klasser tilbyder en truncatedTo
metode. Send en ChronoUnit
enum-objekt for at angive granulariteten. I dette tilfælde ville det være ChronoUnit.MICROS
.
Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;
I øjeblikket burde denne tilgang være tilstrækkelig, da du sandsynligvis ikke har nogen nanosekunder i dine data. Mainstream-computere i dag har ikke hardware-ure, der er i stand til at fange nanosekunder, så vidt jeg ved.
Tæl fra epoke
Hvis du ikke har råd til at miste nogen nanosekund-data, der måtte være til stede, skal du bruge en tælle-fra-epoke.
Jeg anbefaler normalt ikke at spore dato-tid som en optælling fra en epoke referencedato. Men du har få andre valg til at gemme dine nanosekund-baserede værdier i en database som MySQL og Postgres begrænset til mikrosekund-baserede værdier.
Gem par af heltal
I stedet for at bruge det ekstremt store antal nanosekunder siden en epoke som f.eks. 1970-01-01T00:00Z, foreslår jeg, at man følger den tilgang, som de interne af Instant
har taget. klasse:Brug et par af tal.
Gem et antal hele sekunder som et heltal i din database. I en anden kolonne gemmes antallet af nanosekunder i brøksekundet som et heltal.
Du kan nemt udtrække/injicere disse numre fra/til et Instant
objekt. Kun simpel 64-bit long
tal er involveret; intet behov for BigDecimal
eller BigInteger
. Jeg formoder, at du måske kan bruge en 32-bit heltalskolonne til mindst et af de to tal. Men jeg ville vælge 64-bit heltals kolonnetyper for enkelhedens skyld og for direkte kompatibilitet med java.time.Instant
klasses par longs.
long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;
…og…
Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;
Når du sorterer kronologisk, skal du udføre en sortering på flere niveauer, først sortere på hele sekunders kolonnen og derefter sortere sekundært på nanos-brøkdelen af anden kolonne.