2012-10-30 28 views
5

Sau một lỗi, tôi đã nhận thấy rằng nếu tôi tạo một java.sql.Timestamp từ một java.util.Date, bằng cách sử dụng hàm tạo mất mili giây, cá thể Date luôn luôn sau() Dấu thời gian. Điều này là khó hiểu, vì (a) hợp đồng cho trước() xác định một so sánh nghiêm ngặt và (b) nếu không bằng nhau, Dấu thời gian, bởi vì nó có nano giây, có thể là sau() ngày. Nhưng các kết quả ngược lại và lặp lại (với JDK 1.6 và 1.7, với các múi giờ JVM khác nhau). So sánh hai Ngày hoạt động chính xác, nhưng gọi trước() hoặc after() trên một ngày và đưa ra một đối số Dấu thời gian có kết quả không mong muốn.java.sql.Timestamp được tạo từ java.util.Date, tại sao luôn luôn trước() nó?

Mã mẫu bên dưới có hai trường hợp Ngày và một Dấu thời gian, tất cả chúng có cùng giá trị mili giây. Tuy nhiên, so sánh một ngày với dấu thời gian hiển thị ngày để sau() Dấu thời gian.

import java.util.Date; 
import java.sql.Timestamp; 

public class X extends Date { 

    public static void main(String[] args) { 
     Date d1 = new Date(); 
     Date d2 = new Date(d1.getTime()); 
     Timestamp t = new Timestamp (d1.getTime()); 
     System.out.println ("date1 = " + d1 + " (" + d1.getTime() + ")"); 
     System.out.println ("date2 = " + d2 + " (" + d2.getTime() + ")"); 
     System.out.println ("timestamp = " + t + " (" + t.getTime() + ")"); 
     System.out.println ("d1 before d2: " + d1.before(d2)); 
     System.out.println ("d1 after d2: " + d1.after(d2)); 
     System.out.println ("d1 before ts: " + d1.before(t)); 
     System.out.println ("d1 after ts: " + d1.after(t)); //why true? 
    } 
} 

Mẫu đầu ra:

C:\>\Java\jdk1.7.0_05\bin\java X 
date1 = Tue Oct 30 10:15:59 EDT 2012 (1351606559812) 
date2 = Tue Oct 30 10:15:59 EDT 2012 (1351606559812) 
timestamp = 2012-10-30 10:15:59.812 (1351606559812) 
d1 before d2: false 
d1 after d2: false 
d1 before ts: false 
d1 after ts: true 

Dòng cuối cùng là một tò mò.

Cảm ơn bạn.

+0

Sử dụng trình gỡ lỗi để chỉ ra điều đó. Và nhắc nhở [Timestamp API] (http://docs.oracle.com/javase/6/docs/api/java/sql/Timestamp.html) * "[...] khuyên rằng mã không xem giá trị Dấu thời gian một cách tổng quát như một thể hiện của java.util.Date. "* – Kai

+1

' d1.compareTo (ts); 'kết quả' 1', cho biết có sự khác biệt 1 nano hoặc một cái gì đó tương tự. ___ Tôi tin rằng đó là một lỗi, vâng. Tốt lắm, tìm việc đó! – XenoRo

Trả lời

6

Nếu bạn nhìn vào các đại diện bên trong và những gì được so sánh trong phương pháp after(), bạn thấy rằng ví dụ cho

millis = 1351607849957 

bạn nhận được một Date với

fastTime = 1351607849957 

Timestamp với

fastTime = 1351607849000 
nanos = 957000000 

Vì tất cả những gì được so sánh là phần fastTime, bạn sẽ nhận được hành vi được quan sát của mình. Vì @ user714965 chỉ ra ở trên, bạn không được coi là TimestampDate.

+0

Ah, đây là nó. Cảm ơn bạn. –

4

Các tài liệu API của java.sql.Timestamp nói:

Lưu ý: loại này là một hỗn hợp của một java.util.Date và một giá trị nano giây riêng biệt. Chỉ số giây tích phân được lưu trữ trong thành phần java.util.Date. Các giây phân số - các nanô - là riêng biệt.

(Điều đó đồng ý với câu trả lời của Keppil).

Nó cũng nói:

Do sự khác nhau giữa các lớp Timestamp và lớp java.util.Date đề cập ở trên, nó được khuyến khích mã mà không xem Timestamp giá trị tổng quát như một thể hiện của java.util.Date. Mối quan hệ kế thừa giữa Timestampjava.util.Date thực sự biểu thị thừa kế triển khai và không loại thừa kế.

Điều đó có nghĩa bạn không nên đối xử với Timestamp như một java.util.Date, đó là những gì bạn đang làm nếu bạn vượt qua nó để java.util.Date.after() (phương pháp mà hy vọng một java.util.Date - bạn đang đi trong một Timestamp, xử lý nó như thể nó là một java.util.Date, nhận xét này cho biết bạn không nên làm).

Đây là thiết kế không hợp lệ trong thư viện Java chuẩn. Nếu bạn cần làm việc với ngày tháng và thời gian, hãy sử dụng Joda Time, một thư viện được thiết kế tốt hơn và mạnh mẽ hơn nhiều.

+0

Vâng, tôi biết về những khác biệt đó (và không tương thích, đặc biệt là bằng equals()) cũng như Joda, nhưng tôi đang tìm kiếm một lời giải thích về hành vi kỳ quặc này. –

+0

Lưu ý rằng bạn có thể tìm hiểu mã nguồn của một lớp như 'java.sql.Timestamp', bạn có thể tìm thấy nó trong tệp' src.zip' nằm trong thư mục cài đặt JDK của bạn. – Jesper

Các vấn đề liên quan