Отрязване до микросекунди
Очевидно не можем да стиснем наносекунди
разделителна способност на Instant
в микросекунди
разделителна способност на типовете данни на MySQL DateTime
и Timestamp
.
Въпреки че не използвам MySQL, си представям JDBC драйвер
е създаден да игнорира наносекундите при получаване на Instant
, съкращавайки стойността до микросекунди. Предлагам ви да опитате експеримент, за да видите и може би да разгледате изходния код на вашия драйвер, който отговаря на JDBC 4.2 и по-нови версии.
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 ) ;
…и…
Instant instant2 = myResultSet.getObject( … , Instant.class ) ;
Спецификация на JDBC 4.2
изисква поддръжка за OffsetDateTime
но странно не изисква двата по-често използвани типа, Instant
и ZonedDateTime
. Ако вашият JDBC драйвер
не поддържа Instant
, конвертирайте.
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`.
След това сравнете.
Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;
Разумно сте загрижени за стойностите, извлечени от базата данни, които не съвпадат с оригиналната стойност. Едно решение, ако е приемливо за вашия бизнес проблем, е да съкратите всички наносекунди до микросекунди в оригиналните си данни. Препоръчвам този подход като цяло.
java.time класовете предлагат truncatedTo
метод. Предайте ChronoUnit
enum обект, за да посочите детайлността. В този случай това би било ChronoUnit.MICROS
.
Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;
Понастоящем този подход би трябвало да е достатъчен, тъй като е малко вероятно да имате наносекунди във вашите данни. Основните компютри днес не разполагат с хардуерни часовници, способни да улавят наносекунди, доколкото знам.
Брой от епоха
Ако не можете да си позволите да загубите каквито и да е наносекундни данни, които може да присъстват, използвайте отброяване от епоха.
Обикновено препоръчвам да не проследявате дата-време като броене от референтна дата за епоха. Но имате няколко други възможности за съхранение на базираните на наносекунди стойности в база данни като MySQL и Postgres, ограничено до стойности, базирани на микросекунди.
Съхраняване на двойка цели числа
Вместо да използвам изключително големия брой наносекунди от епоха като 1970-01-01T00:00Z, предлагам да следвате подхода, възприет от вътрешните елементи на Instant
клас:Използвайте чифт от числа.
Съхранявайте няколко цели секунди като цяло число във вашата база данни. Във втора колона съхранявайте като цяло число броя наносекунди в частната секунда.
Можете лесно да извлечете/инжектирате тези числа от/в Instant
обект. Само обикновен 64-битов long
участват числа; няма нужда от BigDecimal
или BigInteger
. Предполагам, че може да успеете да използвате 32-битова целочислена колона за поне едно от двете числа. Но бих избрал 64-битови типове целочислени колони за простота и за директна съвместимост с java.time.Instant
клас’ чифт дълги.
long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;
…и…
Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;
Когато сортирате хронологично, ще трябва да извършите сортиране на няколко нива, като първо сортирате по цялата колона за секунди и след това вторично по колоната с нанос части от секундата.