tl; dr
java.util.Date.from( // Transfer the moment in UTC, truncating any microseconds or nanoseconds to milliseconds.
Instant.now() ; // Capture current moment in UTC, with resolution as fine as nanoseconds.
)
Mặc dù không có điểm nào trong đoạn mã trên. Cả hai java.util.Date
và Instant
đại diện cho một thời điểm trong UTC, luôn luôn ở UTC. Mã trên có tác dụng tương tự như:
new java.util.Date() // Capture current moment in UTC.
Không có lợi ích ở đây để sử dụng ZonedDateTime
. Nếu bạn đã có a ZonedDateTime
, hãy điều chỉnh thành UTC bằng cách giải nén a Instant
.
java.util.Date.from( // Truncates any micros/nanos.
myZonedDateTime.toInstant() // Adjust to UTC. Same moment, same point on the timeline, different wall-clock time.
)
Câu trả lời khác đúng
Câu trả lời của ssoltanid giải quyết chính xác câu hỏi cụ thể của bạn, làm thế nào để chuyển đổi một đối tượng java.time mới ( ZonedDateTime
) thành một java.util.Date
đối tượng cũ . Trích xuất Instant
từ ZonedDateTime và chuyển đến java.util.Date.from()
.
Mất dữ liệu
Lưu ý rằng bạn sẽ bị mất dữ liệu , vì Instant
theo dõi nano giây kể từ kỷ nguyên trong khi java.util.Date
theo dõi mili giây kể từ kỷ nguyên.
Câu hỏi và nhận xét của bạn nêu ra các vấn đề khác.
Giữ máy chủ ở UTC
Máy chủ của bạn nên đặt hệ điều hành chủ của chúng thành UTC như một phương pháp hay nhất nói chung. JVM chọn cài đặt HĐH máy chủ này làm múi giờ mặc định của nó, trong các triển khai Java mà tôi biết.
Chỉ định múi giờ
Nhưng bạn không nên dựa vào múi giờ mặc định hiện tại của JVM. Thay vì chọn cài đặt máy chủ, một cờ được thông qua khi khởi chạy JVM có thể đặt múi giờ khác. Thậm chí tệ hơn: Bất kỳ mã nào trong bất kỳ chuỗi nào của bất kỳ ứng dụng nào vào bất kỳ lúc nào đều có thể thực hiện lệnh gọi java.util.TimeZone::setDefault
để thay đổi mặc định đó trong thời gian chạy!
Timestamp
Loại Cassandra
Bất kỳ cơ sở dữ liệu và trình điều khiển tốt nào sẽ tự động xử lý việc điều chỉnh ngày-giờ đã qua thành UTC để lưu trữ. Tôi không sử dụng Cassandra, nhưng nó dường như có một số hỗ trợ thô sơ cho ngày-giờ. Tài liệu cho biết Timestamp
loại của nó là số phần nghìn giây từ cùng một kỷ nguyên (thời điểm đầu tiên của năm 1970 theo giờ UTC).
ISO 8601
Hơn nữa, Cassandra chấp nhận đầu vào chuỗi ở các định dạng tiêu chuẩn ISO 8601 . May mắn thay, java.time sử dụng các định dạng ISO 8601 làm định dạng mặc định để phân tích cú pháp / tạo chuỗi. Việc triển khai Instant
lớp học toString
sẽ hoạt động tốt.
Độ chính xác: Mili giây so với Nanosecord
Nhưng trước tiên, chúng ta cần giảm độ chính xác nano giây của ZonedDateTime xuống mili giây. Một cách là tạo Instant mới bằng cách sử dụng mili giây. May mắn thay, java.time có một số phương pháp tiện dụng để chuyển đổi sang và từ mili giây.
Mã mẫu
Đây là một số mã ví dụ trong Java 8 Update 60.
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
…
Instant instant = zdt.toInstant();
Instant instantTruncatedToMilliseconds = Instant.ofEpochMilli( instant.toEpochMilli() );
String fodderForCassandra = instantTruncatedToMilliseconds.toString(); // Example: 2015-08-18T06:36:40.321Z
Hoặc theo tài liệu trình điều khiển Java Cassandra này , bạn có thể vượt qua một java.util.Date
phiên bản (không nên nhầm lẫn với java.sqlDate
). Vì vậy, bạn có thể tạo ngày tháng năm từ đó instantTruncatedToMilliseconds
trong đoạn mã trên.
java.util.Date dateForCassandra = java.util.Date.from( instantTruncatedToMilliseconds );
Nếu làm điều này thường xuyên, bạn có thể tạo một lớp lót.
java.util.Date dateForCassandra = java.util.Date.from( zdt.toInstant() );
Nhưng sẽ gọn gàng hơn nếu tạo ra một phương thức tiện ích nhỏ.
static public java.util.Date toJavaUtilDateFromZonedDateTime ( ZonedDateTime zdt ) {
Instant instant = zdt.toInstant();
// Data-loss, going from nanosecond resolution to milliseconds.
java.util.Date utilDate = java.util.Date.from( instant ) ;
return utilDate;
}
Lưu ý sự khác biệt trong tất cả mã này so với trong Câu hỏi. Mã của Câu hỏi đang cố gắng điều chỉnh múi giờ của phiên bản ZonedDateTime thành UTC. Nhưng điều đó là không cần thiết. Về mặt khái niệm:
ZonedDateTime = Instant + ZoneId
Chúng tôi chỉ trích xuất phần Instant, phần này đã có trong UTC (về cơ bản là UTC, hãy đọc tài liệu lớp để biết chi tiết chính xác).
Giới thiệu về java.time
Các java.time khung được xây dựng vào Java 8 và sau đó. Những lớp học thay thế cái cũ phiền hà di sản lớp học ngày thời gian như java.util.Date
, Calendar
, & SimpleDateFormat
.
Các Joda thời gian dự án, bây giờ trong chế độ bảo trì , khuyên chuyển đổi sang các java.time lớp.
Để tìm hiểu thêm, hãy xem Hướng dẫn Oracle . Và tìm kiếm Stack Overflow để có nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310 .
Bạn có thể trao đổi các đối tượng java.time trực tiếp với cơ sở dữ liệu của mình. Sử dụng trình điều khiển JDBC tương thích với JDBC 4.2 trở lên. Không cần chuỗi, không cần java.sql.*
lớp.
Lấy các lớp java.time ở đâu?
Các ThreeTen-Extra dự án mở rộng java.time với các lớp bổ sung. Dự án này là cơ sở chứng minh cho những bổ sung có thể có trong tương lai cho java.time. Bạn có thể tìm thấy một số các lớp học hữu ích ở đây chẳng hạn như Interval
, YearWeek
, YearQuarter
, và nhiều hơn nữa .
java.util.Date
vàjava.sql.Date
.