Zkrácení na mikrosekundy
Je zřejmé, že nemůžeme zmáčknout nanosekundy
rozlišení Instant
do mikrosekund
rozlišení datových typů MySQL DateTime
a Timestamp
.
I když nepoužívám MySQL, představuji si ovladač JDBC
je vytvořen tak, aby ignoroval nanosekundy při příjmu Instant
, zkrátí hodnotu na mikrosekundy. Doporučuji zkusit experiment, abyste viděli a možná prozkoumali zdrojový kód vašeho ovladače, který vyhovuje JDBC 4.2 a novějším.
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 ) ;
…a…
Instant instant2 = myResultSet.getObject( … , Instant.class ) ;
Specifikace JDBC 4.2
vyžaduje podporu pro OffsetDateTime
ale kupodivu nevyžaduje dva běžně používané typy, Instant
a ZonedDateTime
. Pokud váš ovladač JDBC
nepodporuje Instant
, převést.
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`.
Pak porovnejte.
Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;
Jste moudře znepokojeni hodnotami získanými z databáze, které neodpovídají původní hodnotě. Jedním z řešení, pokud je to přijatelné pro váš obchodní problém, je zkrátit jakékoli nanosekundy na mikrosekundy v původních datech. Tento přístup obecně doporučuji.
java.time třídy nabízejí truncatedTo
metoda. Předejte ChronoUnit
objekt enum k určení granularity. V tomto případě by to bylo ChronoUnit.MICROS
.
Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;
V současné době by tento přístup měl stačit, protože je nepravděpodobné, že byste ve svých datech měli nějaké nanosekundy. Mainstreamové počítače dnes nemají hardwarové hodiny schopné zachytit nanosekundy, pokud vím.
Počítání od epoch
Pokud si nemůžete dovolit ztratit jakákoliv nanosekundová data, která mohou být přítomna, použijte počítání od epochy.
Obvykle nedoporučuji sledovat datum a čas jako počet od referenčního data epochy. Ale máte několik dalších možností při ukládání hodnot na bázi nanosekund v databázi, jako je MySQL a Postgres, omezená na hodnoty založené na mikrosekundách.
Uložte pár celých čísel
Spíše než používat extrémně velký počet nanosekund od epochy, jako je 1970-01-01T00:00Z, navrhuji následovat přístup, který zvolili vnitřnosti Instant
třída:Použijte pár čísel.
Uložte počet celek sekund jako celé číslo ve vaší databázi. Ve druhém sloupci uložte jako celé číslo počet nanosekund ve zlomkové sekundě.
Tato čísla můžete snadno extrahovat/vložit z/do Instant
objekt. Pouze jednoduchý 64bitový long
jde o čísla; není potřeba BigDecimal
nebo BigInteger
. Předpokládám, že byste mohli být schopni použít 32bitový celočíselný sloupec alespoň pro jedno ze dvou čísel. Ale zvolil bych 64bitové celočíselné typy sloupců pro jednoduchost a pro přímou kompatibilitu s java.time.Instant
třídy‘ pár dlouhých.
long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;
…a…
Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;
Při chronologickém řazení budete muset provést víceúrovňové řazení, nejprve seřadit podle sloupce s celými sekundami a poté seřadit sekundárně podle sloupce se zlomkem sekundy nano.