Tronca a microsecondi
Ovviamente non possiamo spremere i nanosecondi
risoluzione di un Instant
nei microsecondi
risoluzione dei tipi di dati MySQL DateTime
e Timestamp
.
Anche se non utilizzo MySQL, immagino il driver JDBC
è costruito per ignorare i nanosecondi quando si riceve un Instant
, troncando il valore in microsecondi. Ti suggerisco di provare un esperimento per vedere e magari esaminare il codice sorgente del tuo driver conforme a JDBC 4.2 e versioni successive.
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 ) ;
…e…
Instant instant2 = myResultSet.getObject( … , Instant.class ) ;
Le specifiche JDBC 4.2
richiede il supporto per OffsetDateTime
ma stranamente non richiede i due tipi più comunemente usati, Instant
e ZonedDateTime
. Se il tuo driver JDBC
non supporta Instant
, converti.
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`.
Quindi confronta.
Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;
Sei saggiamente preoccupato per i valori estratti dal database che non corrispondono al valore originale. Una soluzione, se accettabile per il tuo problema aziendale, è troncare qualsiasi nanosecondo a microsecondi nei dati originali. Consiglio questo approccio in generale.
Il java.time le classi offrono un truncatedTo
metodo. Passa un ChronoUnit
enum per specificare la granularità. In questo caso, sarebbe ChronoUnit.MICROS
.
Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;
Attualmente questo approccio dovrebbe essere sufficiente poiché è improbabile che tu abbia nanosecondi nei tuoi dati. I computer tradizionali oggi non sfoggiano orologi hardware in grado di catturare nanosecondi, per quanto ne so.
Conta dall'epoca
Se non puoi permetterti di perdere i dati di nanosecondi eventualmente presenti, utilizza un conteggio dall'epoca.
Di solito sconsiglio di tracciare la data e l'ora come conteggio da una data di riferimento di epoca. Ma hai poche altre scelte per archiviare i tuoi valori basati su nanosecondi in un database come MySQL e Postgres limitati a valori basati su microsecondi.
Memorizza coppia di numeri interi
Piuttosto che utilizzare il numero estremamente elevato di nanosecondi da un'epoca come 1970-01-01T00:00Z, suggerisco di seguire l'approccio adottato dagli interni di Instant
classe:usa una coppia di numeri.
Archivia un certo numero di interi secondi come numero intero nel database. In una seconda colonna memorizza come numero intero il numero di nanosecondi nel secondo frazionario.
Puoi facilmente estrarre/iniettare questi numeri da/in un Instant
oggetto. Solo semplice long
a 64 bit i numeri sono coinvolti; non c'è bisogno di BigDecimal
o BigInteger
. Suppongo che potresti essere in grado di utilizzare una colonna intera a 32 bit per almeno uno dei due numeri. Ma sceglierei tipi di colonne intere a 64 bit per semplicità e per compatibilità diretta con java.time.Instant
coppia di long della classe.
long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;
…e…
Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;
Quando esegui l'ordinamento cronologico, dovrai eseguire un ordinamento a più livelli, ordinando prima sull'intera colonna dei secondi e quindi ordinando secondariamente sulla colonna della frazione di secondo nanos.