Các câu trả lời khác là chính xác, đặc biệt là câu trả lời java.time của arganzheng . Như một số đề cập, bạn nên tránh các lớp java.util.Date/.CalWiki cũ vì chúng được thiết kế kém, khó hiểu và rắc rối. Chúng đã được thay thế bởi các lớp java.time.
Hãy để tôi thêm ghi chú về chiến lược xung quanh việc xử lý nửa đêm và khoảng thời gian .
Mở một nửa
Trong công việc thời gian, các khoảng thời gian thường được xác định bằng cách sử dụng phương pháp tiếp cận Half Half Open. Trong cách tiếp cận này, sự khởi đầu là bao gồm trong khi kết thúc là độc quyền . Điều này giải quyết vấn đề và nếu được sử dụng một cách nhất quán làm cho lý do về việc xử lý thời gian ngày của bạn dễ dàng hơn nhiều.
Một vấn đề được giải quyết là xác định cuối ngày. Là khoảnh khắc cuối cùng trong ngày 23:59:59.999
( mili giây )? Có lẽ, trong lớp java.util.Date (từ Java sớm nhất; rắc rối - tránh lớp này!) Và trong thư viện Joda-Time rất thành công . Nhưng trong các phần mềm khác, chẳng hạn như cơ sở dữ liệu như Postgres, khoảnh khắc cuối cùng sẽ là 23:59:59.999999
( micro giây ). Nhưng trong các phần mềm khác như khung java.time (được tích hợp vào Java 8 trở lên, kế thừa Joda-Time) và trong một số cơ sở dữ liệu như Cơ sở dữ liệu H2 , khoảnh khắc cuối cùng có thể là 23:59.59.999999999
( nano giây ). Thay vì chia tóc, hãy nghĩ về khoảnh khắc đầu tiên, không phải khoảnh khắc cuối cùng.
Trong Half-Open, một ngày chạy từ khoảnh khắc đầu tiên của một ngày và đi lên nhưng không bao gồm khoảnh khắc đầu tiên của ngày tiếp theo. Vì vậy, thay vì nghĩ như thế này:
Từ hôm nay lúc 00:00 sáng (nửa đêm sáng sớm) đến 12:00 tối (nửa đêm nay).
Hãy nghĩ như thế này
từ khoảnh khắc đầu tiên của ngày hôm nay chạy đến nhưng không bao gồm khoảnh khắc đầu tiên của ngày mai:
(> = 00:00:00.0
hôm nay VÀ < 00:00:00.0
ngày mai)
Trong công việc cơ sở dữ liệu, cách tiếp cận này có nghĩa là không sử dụng BETWEEN
toán tử trong SQL.
Ngày bắt đầu
Hơn nữa, khoảnh khắc đầu tiên trong ngày không phải lúc nào cũng là thời gian trong ngày 00:00:00.0
. Thời gian tiết kiệm ánh sáng ban ngày (DST) ở một số múi giờ, và có thể là sự bất thường khác, có thể có nghĩa là một thời gian khác nhau bắt đầu một ngày.
Vì vậy, hãy để các lớp java.time thực hiện công việc xác định bắt đầu một ngày bằng một cuộc gọi đến LocalDate::atStartOfDay( ZoneId )
. Vì vậy, chúng ta phải đi vòng qua LocalDate
và quay lại ZonedDateTime
như bạn có thể thấy trong mã ví dụ này.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );
ZonedDateTime todayStart = now.toLocalDate().atStartOfDay( zoneId );
ZonedDateTime tomorrowStart = todayStart.plusDays( 1 );
Lưu ý việc vượt qua tùy chọn ZoneId
. Nếu bỏ qua múi giờ mặc định hiện tại của JVM của bạn sẽ được áp dụng hoàn toàn. Tốt hơn để được rõ ràng.
Múi giờ là rất quan trọng để làm việc thời gian. Câu hỏi và một số câu trả lời khác có khả năng thiếu sót vì không có ý thức xử lý múi giờ.
Đổi
Nếu bạn phải sử dụng java.util.Date hoặc .CalWiki, hãy tìm các phương thức chuyển đổi mới được thêm vào các lớp cũ đó.
java.util.Date utilDate = java.util.Date.from( todayStart.toInstant() );
java.util.GregorianCalendar gregCal = java.util.GregorianCalendar.from( todayStart );
Khoảng thời gian
Nhân tiện, nếu bạn đang làm nhiều việc với khoảng thời gian, hãy xem:
Duration
Period
Interval
Các Interval
lớp học được tìm thấy trong ThreeTen-Extra dự án, một mở rộng của khuôn khổ java.time. Dự án này là nền tảng chứng minh cho những bổ sung có thể có trong tương lai cho java.time.
Interval todayMontreal = Interval.of( todayStart.toInstant() , tomorrowStart.toInstant() );
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, xem Hướng dẫn Oracle . Và tìm kiếm Stack Overflow cho 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 bạn. 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.
Nơi để có được các lớp java.time?
Các ThreeTen-Extra dự án mở rộng java.time với các lớp bổ sung. Dự án này là một nền tảng chứng minh cho các bổ sung có thể 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 .