Làm cách nào để chuyển đổi java.sql.timestamp sang LocalDate (java8) java.time?


Câu trả lời:


195

Bạn có thể làm:

timeStamp.toLocalDateTime().toLocalDate();

Lưu ý rằng timestamp.toLocalDateTime() sẽ sử dụng Clock.systemDefaultZone()múi giờ để thực hiện chuyển đổi. Điều này có thể hoặc không thể là những gì bạn muốn.


1
Nó đã được thêm vào trong Java 8.
assylias

54
Chỉ cần một lưu ý, timestamp.toLocalDateTime()phương thức sẽ sử dụng múi giờ systemDefault để thực hiện chuyển đổi. Điều này có thể hoặc không thể là những gì bạn muốn.
jacobhyphenated

1
@jacobhyphenated vui lòng gửi câu trả lời bằng múi giờ rõ ràng. Cảm ơn!
dùng482745

Nhận xét của @ jacobhyphenated là cực kỳ quan trọng ở đây, do đó số lượng upvote cho nó. Xem câu trả lời của tôi để biết chi tiết stackoverflow.com/a/57101544/2032701
Ruslan

@jacobhyphenated, LocalDateTimeluôn sử dụng múi giờ mặc định của hệ thống. Đó là "Địa phương" nghĩa là gì trong tên của nó.
M. Prokhorov

20

Câu trả lời được chấp nhận là không lý tưởng, vì vậy tôi quyết định thêm 2 xu của mình

timeStamp.toLocalDateTime().toLocalDate();

nói chung là một giải pháp tồi , tôi thậm chí không chắc tại sao họ lại thêm phương thức này vào JDK vì nó khiến mọi thứ thực sự khó hiểu bằng cách thực hiện chuyển đổi ngầm bằng múi giờ hệ thống. Thông thường khi chỉ sử dụng các lớp ngày java8, lập trình viên buộc phải chỉ định múi giờ là một điều tốt.

Giải pháp tốt là

timestamp.toInstant().atZone(zoneId).toLocalDate()

Trong đó ZoneId là múi giờ bạn muốn sử dụng, thường là ZoneId.systemDefault () nếu bạn muốn sử dụng múi giờ hệ thống của mình hoặc một số múi giờ được mã hóa cứng như Zone Offerset.UTC

Cách tiếp cận chung nên là

  1. Thoát khỏi các lớp ngày java8 mới bằng cách sử dụng một lớp có liên quan trực tiếp, ví dụ như trong trường hợp của chúng tôi java.time.Instant liên quan trực tiếp đến java.sql.Timestamp , tức là không cần chuyển đổi múi giờ giữa chúng.
  2. Sử dụng các phương thức được thiết kế tốt trong lớp java8 này để làm điều đúng đắn. Trong trường hợp của chúng tôi, atZone (areaId) đã nói rõ rằng chúng tôi đang thực hiện chuyển đổi và sử dụng múi giờ cụ thể cho nó.

1
Tôi không đồng ý. Dấu thời gian (và cả Ngày) không có bất kỳ thông tin khu vực nào. LocalDate không có bất kỳ thông tin khu vực nào vì vậy hai cái này tương đương nhau. Chuyển đổi giữa chúng có thể được thực hiện độc lập với bất kỳ khu vực cụ thể. Chuyển đổi sang ZiatedDateTime trước khi chuyển đổi sang LocalDate sẽ thêm vào múi giờ và sau đó tắt lại - bạn rất có thể gặp phải lỗi khó chịu khi tìm thấy theo cách đó.
AutomatedMike

5
@AutomatedMike Dấu thời gian (và cả Ngày) thể hiện một thời điểm trong UTC. LocalDate không đại diện cho một điểm trong thời gian, mà là thời gian như được thấy trên đồng hồ treo tường. Vui lòng đọc javadocs của họ. "Chuyển đổi giữa chúng có thể được thực hiện độc lập với bất kỳ vùng cụ thể nào" - không đúng , Dấu thời gian mới (0L) .toLocalDateTime () trả về "1970-01-01T03: 00" cho múi giờ Moscow của tôi. Kết quả có thể khác nhau đối với múi giờ của bạn.
Ruslan

1
@AutomatedMike Ngay cả khi bạn tách thời gian bằng cách thực hiện toLocalDate (), thật dễ dàng để chứng minh rằng ngày có thể sai nếu Timestamp có thời gian vào khoảng nửa đêm, ví dụ như Timestamp mới (1000 * 60 * 60 * 23) .toLocalDateTime (). () trả về "1970-01-02" cho múi giờ Moscow của tôi khi đó là "1970-01-01" trong UTC.
Ruslan

1
@AutomatedMike "thêm vào múi giờ và sau đó lại tắt" - điểm không phải là thêm và xóa múi giờ, mà là chuyển đổi giữa các khái niệm khác nhau bằng cách sử dụng múi giờ rõ ràng . Điều này trái ngược với các ví dụ về hai nhận xét trước đây của tôi trong đó một múi giờ được áp dụng ngầm .
Ruslan

7

Tôi sẽ mở rộng câu trả lời @assylias để tính đến múi giờ. Có ít nhất hai cách để lấy LocalDateTime cho múi giờ cụ thể.

Bạn có thể sử dụng múi giờ setDefault cho toàn bộ ứng dụng. Nó nên được gọi trước bất kỳ dấu thời gian nào -> java.time convert:

public static void main(String... args) {
    TimeZone utcTimeZone = TimeZone.getTimeZone("UTC");
    TimeZone.setDefault(utcTimeZone);
    ...
    timestamp.toLocalDateTime().toLocalDate();
}

Hoặc bạn có thể sử dụng chuỗi toInstant.atZone:

timestamp.toInstant()
        .atZone(ZoneId.of("UTC"))
        .toLocalDate();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.