Truncar a microsegundos
Obviamente no podemos exprimir los nanosegundos
resolución de un Instant
en los microsegundos
resolución de los tipos de datos MySQL DateTime
y Timestamp
.
Si bien no uso MySQL, imagino el controlador JDBC
está diseñado para ignorar los nanosegundos al recibir un Instant
, truncando el valor a microsegundos. Le sugiero que pruebe un experimento para ver, y quizás examine el código fuente de su controlador que cumple con JDBC 4.2 y posterior.
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 ) ;
…y…
Instant instant2 = myResultSet.getObject( … , Instant.class ) ;
Las especificaciones JDBC 4.2
requiere soporte para OffsetDateTime
pero curiosamente no requiere los dos tipos más utilizados, Instant
y ZonedDateTime
. Si su controlador JDBC
no es compatible con Instant
, convertir.
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`.
Luego compare.
Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;
Sabiamente, le preocupa que los valores extraídos de la base de datos no coincidan con el valor original. Una solución, si es aceptable para su problema comercial, es truncar los nanosegundos a microsegundos en sus datos originales. Recomiendo este enfoque en general.
El java.tiempo las clases ofrecen un truncatedTo
método. Pase una ChronoUnit
objeto enum para especificar la granularidad. En este caso, sería ChronoUnit.MICROS
.
Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;
Actualmente, este enfoque debería ser suficiente, ya que es poco probable que tenga nanosegundos en sus datos. Las computadoras convencionales de hoy en día no cuentan con relojes de hardware capaces de capturar nanosegundos, que yo sepa.
Cuenta desde la época
Si no puede permitirse el lujo de perder los datos de nanosegundos que puedan estar presentes, use un conteo desde la época.
Por lo general, recomiendo no rastrear la fecha y la hora como un conteo a partir de una fecha de referencia de época. Pero tiene pocas opciones para almacenar sus valores basados en nanosegundos en una base de datos como MySQL y Postgres limitada a valores basados en microsegundos.
Almacenar par de enteros
En lugar de usar la cantidad extremadamente grande de nanosegundos desde una época como 1970-01-01T00:00Z, sugiero seguir el enfoque adoptado por las partes internas del Instant
clase:Usa un par de números.
Almacenar un número de enteros segundos como un número entero en su base de datos. En una segunda columna, almacene como un número entero el número de nanosegundos en la fracción de segundo.
Puede extraer/inyectar fácilmente estos números desde/hacia un Instant
objeto. Solo long
simple de 64 bits los números están involucrados; no es necesario BigDecimal
o BigInteger
. Supongo que podría usar una columna de enteros de 32 bits para al menos uno de los dos números. Pero elegiría tipos de columna de enteros de 64 bits por simplicidad y por compatibilidad directa con java.time.Instant
par de largos de la clase.
long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;
…y…
Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;
Al ordenar cronológicamente, deberá realizar una ordenación de niveles múltiples, ordenando primero en la columna de segundos completos y luego ordenando en segundo lugar en la columna de fracción de segundo de nanos.