tl; dr
Làm cách nào để chuyển đổi java.util.Date thành java.sql.Date?
Đừng. Cả hai lớp đều lỗi thời.
- Sử dụng các lớp java.time thay vì kế thừa
java.util.Date
& java.sql.Date
với JDBC 4.2 trở lên.
- Chuyển đổi sang / từ java.time nếu hoạt động liên tục với mã chưa được cập nhật thành java.time.
Ví dụ truy vấn với PreparedStatement
.
myPreparedStatement.setObject(
… , // Specify the ordinal number of which argument in SQL statement.
myJavaUtilDate.toInstant() // Convert from legacy class `java.util.Date` (a moment in UTC) to a modern `java.time.Instant` (a moment in UTC).
.atZone( ZoneId.of( "Africa/Tunis" ) ) // Adjust from UTC to a particular time zone, to determine a date. Instantiating a `ZonedDateTime`.
.toLocalDate() // Extract a date-only `java.time.LocalDate` object from the date-time `ZonedDateTime` object.
)
Thay thế:
Instant
thay vì java.util.Date
cả hai đại diện cho một khoảnh khắc trong UTC. nhưng bây giờ với nano giây thay vì mili giây.
LocalDate
thay vì java.sql.Date
Cả hai đại diện cho một giá trị chỉ ngày mà không có thời gian trong ngày và không có múi giờ.
Chi tiết
Nếu bạn đang cố gắng làm việc với các giá trị chỉ ngày (không có thời gian trong ngày, không có múi giờ), hãy sử dụng LocalDate
lớp thay vì java.util.Date
.
java.time
Trong Java 8 trở lên, các lớp thời gian cũ rắc rối được gói cùng với các phiên bản đầu tiên của Java đã được thay thế bởi gói java.time mới . Xem Hướng dẫn của Oracle . Phần lớn chức năng đã được chuyển sang Java 6 & 7 trong ThreeTen-Backport và được điều chỉnh phù hợp hơn với Android trong ThreeTenABP .
Một kiểu dữ liệu SQL DATE
có nghĩa là chỉ ngày, không có thời gian trong ngày và không có múi giờ. Java chưa bao giờ có một lớp chính xác như vậy cho đến khi java.time.LocalDate
ở Java 8. Hãy tạo ra một giá trị như vậy bằng cách lấy ngày hôm nay theo một múi giờ cụ thể (múi giờ rất quan trọng trong việc xác định một ngày là một ngày mới khởi đầu sớm hơn ở Paris so với ở Montréal, thí dụ).
LocalDate todayLocalDate = LocalDate.now( ZoneId.of( "America/Montreal" ) ); // Use proper "continent/region" time zone names; never use 3-4 letter codes like "EST" or "IST".
Tại thời điểm này, chúng tôi có thể được thực hiện. Nếu bạn điều khiển JDBC Tuân JDBC 4.2 đặc tả , bạn sẽ có thể vượt qua một LocalDate
qua setObject
trên PreparedStatement
để lưu trữ vào một lĩnh vực SQL DATE.
myPreparedStatement.setObject( 1 , localDate );
Tương tự, sử dụng ResultSet::getObject
để tìm nạp từ cột DATE SQL đến một LocalDate
đối tượng Java . Việc chỉ định lớp trong đối số thứ hai làm cho mã của bạn an toàn .
LocalDate localDate = ResultSet.getObject( 1 , LocalDate.class );
Nói cách khác, toàn bộ Câu hỏi này không liên quan theo JDBC 4.2 trở lên.
Nếu trình điều khiển JDBC của bạn không thực hiện theo cách này, bạn cần quay lại chuyển đổi sang các loại java.sql.
Chuyển đổi sang java.sql.Date
Để chuyển đổi, sử dụng các phương thức mới được thêm vào các lớp thời gian cũ. Chúng ta có thể gọi java.sql.Date.valueOf(…)
để chuyển đổi a LocalDate
.
java.sql.Date sqlDate = java.sql.Date.valueOf( todayLocalDate );
Và đi theo hướng khác.
LocalDate localDate = sqlDate.toLocalDate();
Chuyển đổi từ java.util.Date
Mặc dù bạn nên tránh sử dụng các lớp thời gian cũ, bạn có thể bị buộc phải làm việc với mã hiện có. Nếu vậy, bạn có thể chuyển đổi sang / từ java.time.
Đi qua Instant
lớp, đại diện cho một khoảnh khắc trên dòng thời gian trong UTC. An Instant
là ý tưởng tương tự như a java.util.Date
. Nhưng lưu ý rằng Instant
có độ phân giải lên tới nano giây trong khi java.util.Date
chỉ có độ phân giải mili giây .
Để chuyển đổi, sử dụng các phương thức mới được thêm vào các lớp cũ. Ví dụ, java.util.Date.from( Instant )
và java.util.Date::toInstant
.
Instant instant = myUtilDate.toInstant();
Để xác định một ngày, chúng ta cần bối cảnh của múi giờ. Đối với bất kỳ thời điểm nào, ngày thay đổi trên toàn cầu theo múi giờ. Áp dụng a ZoneId
để có được a ZonedDateTime
.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
LocalDate localDate = zdt.toLocalDate();
† Các java.sql.Date giả vờ lớp là ngày-chỉ mà không có một ngày thời gian-of-nhưng thực sự làm một thời gian trong ngày, điều chỉnh đến một thời gian nửa đêm. Gây nhầm lẫn? Vâng, các lớp thời gian cũ là một mớ hỗn độn.
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 .