Cắt ngắn thành micro giây
Rõ ràng là chúng ta không thể sử dụng nano giây
độ phân giải của Instant
vào micro giây
độ phân giải của kiểu dữ liệu MySQL DateTime
và Timestamp
.
Trong khi tôi không sử dụng MySQL, tôi tưởng tượng ra trình điều khiển JDBC
được xây dựng để bỏ qua nano giây khi nhận được Instant
, cắt ngắn giá trị thành micro giây. Tôi khuyên bạn nên thử một thử nghiệm để xem và có thể kiểm tra mã nguồn của trình điều khiển của bạn có tuân thủ JDBC 4.2 trở lên không.
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 ) ;
… Và…
Instant instant2 = myResultSet.getObject( … , Instant.class ) ;
Thông số kỹ thuật JDBC 4.2
yêu cầu hỗ trợ cho OffsetDateTime
nhưng kỳ lạ là không yêu cầu hai loại thường được sử dụng hơn, Instant
và ZonedDateTime
. Nếu trình điều khiển JDBC
của bạn không hỗ trợ Instant
, chuyển đổi.
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`.
Sau đó so sánh.
Boolean result = instant.equals( instant2 ) ;
System.out.println( "instant: " + instant + " equals instant2: = " + instant2 + " is: " + result ) ;
Bạn lo lắng một cách khôn ngoan về các giá trị được rút ra từ cơ sở dữ liệu không khớp với giá trị ban đầu. Một giải pháp, nếu có thể chấp nhận được đối với vấn đề kinh doanh của bạn, là cắt ngắn bất kỳ nano giây nào thành micro giây trong dữ liệu gốc của bạn. Tôi khuyến nghị cách tiếp cận này nói chung.
java.time các lớp cung cấp truncatedTo
phương pháp. Chuyển ChronoUnit
đối tượng enum để chỉ định mức độ chi tiết. Trong trường hợp này, đó sẽ là ChronoUnit.MICROS
.
Instant instant = Instant().now().truncatedTo( ChronoUnit.MICROS ) ;
Hiện tại, cách tiếp cận này sẽ đủ vì bạn không có khả năng có bất kỳ nano giây nào trong dữ liệu của mình. Theo tôi biết, các máy tính phổ thông ngày nay không có đồng hồ phần cứng có khả năng bắt nano giây.
Đếm từ kỷ nguyên
Nếu bạn không đủ khả năng để mất bất kỳ dữ liệu nano giây nào có thể có, hãy sử dụng đếm từ kỷ nguyên.
Tôi thường khuyên bạn không nên theo dõi ngày-giờ dưới dạng số đếm từ ngày tham chiếu kỷ nguyên. Nhưng bạn có một số lựa chọn khác trong việc lưu trữ các giá trị dựa trên nano giây của mình trong cơ sở dữ liệu như MySQL và Postgres được giới hạn ở các giá trị dựa trên micro giây.
Lưu trữ cặp số nguyên
Thay vì sử dụng số lượng nano giây cực lớn kể từ một kỷ nguyên chẳng hạn như 1970-01-01T00:00Z, tôi khuyên bạn nên làm theo phương pháp được thực hiện bởi bên trong của Instant
lớp:Sử dụng một cặp trong số các con số.
Lưu trữ một số toàn bộ giây dưới dạng số nguyên trong cơ sở dữ liệu của bạn. Trong cột thứ hai lưu trữ dưới dạng số nguyên, số nano giây trong giây phân số.
Bạn có thể dễ dàng trích xuất / đưa các số này vào / vào Instant
vật. Chỉ long
64-bit đơn giản các con số có liên quan; không cần BigDecimal
hoặc BigInteger
. Tôi cho rằng bạn có thể sử dụng cột số nguyên 32 bit cho ít nhất một trong hai số. Nhưng tôi sẽ chọn các loại cột số nguyên 64-bit để đơn giản và tương thích trực tiếp với java.time.Instant
đôi long của lớp.
long seconds = instant.getEpochSecond() ;
long nanos = instant.getNano() ;
… Và…
Instant instant = Instant.ofEpochSecond( seconds , nanos ) ;
Khi sắp xếp theo thứ tự thời gian, bạn sẽ cần thực hiện sắp xếp nhiều cấp, trước tiên sắp xếp trên toàn bộ cột giây và sau đó sắp xếp thứ hai trên cột phần giây nano.