Câu trả lời ngắn:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
Giải thích: (dựa trên câu hỏi này về LocalDate
)
Mặc dù tên của nó, java.util.Date
đại diện cho một tức thời trên dòng thời gian, không phải là "ngày". Dữ liệu thực tế được lưu trữ trong đối tượng là một long
phần nghìn giây kể từ 1970-01-01T00: 00Z (nửa đêm khi bắt đầu 1970 GMT / UTC).
Lớp tương đương với java.util.Date
trong JSR-310 là Instant
, do đó, có các phương thức thuận tiện để cung cấp chuyển đổi sang và chuyển đổi:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
Một java.util.Date
thể hiện không có khái niệm về múi giờ. Điều này có vẻ lạ nếu bạn gọi toString()
trên a java.util.Date
, vì toString
nó liên quan đến múi giờ. Tuy nhiên, phương thức đó thực sự sử dụng múi giờ mặc định của Java một cách nhanh chóng để cung cấp chuỗi. Múi giờ không phải là một phần của trạng thái thực tế java.util.Date
.
An Instant
cũng không chứa bất kỳ thông tin nào về múi giờ. Vì vậy, để chuyển đổi từ Instant
ngày sang giờ địa phương, cần phải chỉ định múi giờ. Đây có thể là vùng mặc định - ZoneId.systemDefault()
- hoặc có thể là múi giờ mà ứng dụng của bạn kiểm soát, chẳng hạn như múi giờ từ tùy chọn của người dùng. LocalDateTime
có một phương thức nhà máy thuận tiện, mất cả thời gian và thời gian:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Ngược lại, LocalDateTime
múi giờ được chỉ định bằng cách gọi atZone(ZoneId)
phương thức. Sau ZonedDateTime
đó có thể được chuyển đổi trực tiếp thành Instant
:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
Lưu ý rằng việc chuyển đổi từ LocalDateTime
sang ZonedDateTime
có khả năng giới thiệu hành vi không mong muốn. Điều này là do không phải mọi ngày giờ địa phương đều tồn tại do Giờ tiết kiệm ánh sáng ban ngày. Vào mùa thu / mùa thu, có một sự trùng lặp trong dòng thời gian địa phương nơi cùng một ngày giờ địa phương xảy ra hai lần. Vào mùa xuân, có một khoảng trống, nơi một giờ biến mất. Xem Javadoc atZone(ZoneId)
để biết thêm định nghĩa về việc chuyển đổi sẽ làm gì.
Tóm tắt, nếu bạn đi khứ hồi từ a java.util.Date
đến a LocalDateTime
và quay lại, java.util.Date
bạn có thể kết thúc với một tức thì khác do Giờ tiết kiệm ánh sáng ban ngày.
Thông tin bổ sung: Có một sự khác biệt khác sẽ ảnh hưởng đến ngày rất cũ. java.util.Date
sử dụng lịch thay đổi vào ngày 15 tháng 10 năm 1582, với ngày trước đó sử dụng lịch Julian thay vì lịch Gregorian. Ngược lại, java.time.*
sử dụng hệ thống lịch ISO (tương đương với Gregorian) cho mọi thời đại. Trong hầu hết các trường hợp sử dụng, hệ thống lịch ISO là những gì bạn muốn, nhưng bạn có thể thấy các hiệu ứng kỳ lạ khi so sánh ngày trước năm 1582.