Truncar para microssegundos
Obviamente, não podemos espremer os nanossegundos resolução de um
Instant
nos microssegundos
resolução dos tipos de dados MySQL DateTime
e Timestamp
. Embora eu não use MySQL, imagino o driver JDBC é construído para ignorar os nanossegundos ao receber um
Instant
, truncando o valor para microssegundos. Sugiro que você faça um experimento para ver e talvez examine o código-fonte do seu driver que está em conformidade com o JDBC 4.2 e 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 ) ;
…e…
Instant instant2 = myResultSet.getObject( … , Instant.class ) ;
A especificação JDBC 4.2 requer suporte para
OffsetDateTime
mas estranhamente não requer os dois tipos mais usados, Instant
e ZonedDateTime
. Se o seu driver JDBC
não suporta Instant
, converter. 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`.
Então compare.
Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;
Você sabiamente se preocupa com os valores extraídos do banco de dados que não correspondem ao valor original. Uma solução, se aceitável para o seu problema de negócios, é truncar quaisquer nanossegundos para microssegundos em seus dados originais. Eu recomendo essa abordagem em geral.
O java.time classes oferecem um
truncatedTo
método. Passe um ChronoUnit
enum objeto para especificar a granularidade. Nesse caso, seria ChronoUnit.MICROS
. Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;
Atualmente, essa abordagem deve ser suficiente, pois é improvável que você tenha nanossegundos em seus dados. Os computadores convencionais de hoje não possuem relógios de hardware capazes de capturar nanossegundos, até onde eu sei.
Contagem a partir da época
Se você não puder perder nenhum dado de nanossegundos que possa estar presente, use uma contagem de época.
Eu geralmente não recomendo o rastreamento de data e hora como uma contagem de uma data de referência de época. Mas você tem poucas outras opções para armazenar seus valores baseados em nanossegundos em um banco de dados, como MySQL e Postgres, limitado a valores baseados em microssegundos.
Armazenar par de inteiros
Em vez de usar o número extremamente grande de nanossegundos desde uma época como 1970-01-01T00:00Z, sugiro seguir a abordagem adotada pelos internos do
Instant
classe:use um par de números. Armazenar um número de inteiros segundos como um inteiro em seu banco de dados. Em uma segunda coluna, armazene como um inteiro o número de nanossegundos no segundo fracionário.
Você pode facilmente extrair/injetar esses números de/para um
Instant
objeto. Apenas long
simples de 64 bits números estão envolvidos; não há necessidade de BigDecimal
ou BigInteger
. Suponho que você possa usar uma coluna inteira de 32 bits para pelo menos um dos dois números. Mas eu escolheria tipos de colunas inteiras de 64 bits por simplicidade e compatibilidade direta com o java.time.Instant
par de longs da classe. long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;
…e…
Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;
Ao classificar cronologicamente, você precisará fazer uma classificação em vários níveis, classificando primeiro na coluna inteira de segundos e depois classificando secundariamente na coluna nanos de fração de segundo.