2016-02-03 25 views
6

Tôi đã có một tình huống mà thời gian chạy Java trả về các giá trị mili giây "đảo ngược" khi đọc ngày tháng từ cơ sở dữ liệu (trong java.sql.Date). Giá trị mili giây xấp xỉ cùng một số ngày, nhưng được tính ngược từ năm 0.java.sql.Date hoạt động như thế nào với ngày tháng âm?

Sự cố đã được giải quyết bằng cách khởi động lại thời gian chạy Java.

Nhưng: Tôi phát hiện ra rằng Java xử lý các giá trị "đảo ngược" này gần như chính xác trừ ngày trong tuần.

Khi bạn chạy đoạn mã sau:

System.out.println(new java.util.Date(253402214400000l)); 
System.out.println(new java.util.Date(-377648784000000l)); 

Bạn sẽ nhận được kết quả như sau:

Fri Dec 31 01:00:00 CET 9999 
Tue Dec 31 01:00:00 CET 9999 

Một ví dụ khác:

System.out.println(new java.util.Date(-294192000000l)); 
System.out.println(new java.util.Date(-123967324800000l)); 

Kết quả:

Mon Sep 05 01:00:00 CET 1960 
Mon Sep 05 01:00:00 CET 1960 

Khi sử dụng trình chuyển đổi trực tuyến, kết quả sẽ khác với dòng thứ hai cụ thể. Nó sẽ dẫn đến một ngày âm (năm âm) gần ngày thực, tích cực:

Example1: 
253402214400000 = Fri Dec 31 9999 01:00:00 
-377648784000000 = Tue Oct 15 -9998 02:00:00 

Example 2: 
-294192000000 = Mon Sep 05 1960 02:00:00 
-123967324800000 = Mon Aug 19 -1959 02:00:00 

Tôi chưa tìm thấy bất kỳ thông tin nào về "chủ đề" này.

Vì vậy, bí ẩn đằng sau những ngày "đảo ngược" là gì? Tại sao Java xử lý chúng gần như chính xác? Và ý nghĩa của một JDBC ResultSet trả lại giá trị "mili giây" ngược lại khi gọi resultSet.getDate(1).getTime() là gì?

+0

Bạn đang nói về 'java.util.Date' hoặc' java.sql.Date'? Nhận ra rằng hành vi của một tập kết quả JDBC là trình điều khiển cụ thể, vì mỗi trình điều khiển thực hiện nó cho cơ sở dữ liệu cụ thể của chúng. –

+0

Đó là một java.sql.Date (lớp con của java.util.Date) – praisezh

+1

Tôi không biết ý bạn là gì bởi "đảo ngược". – chrylis

Trả lời

1

Khi bạn đang chuyển một số âm trong hàm tạo ngày thì nó được coi là số mili giây trước ngày 1/1/1970. Các Javadoc nói:

ngày - mili giây kể từ 01 Tháng Một 1970, 00:00:00 giờ không quá các mili giây đại diện cho năm 8099. Một số âm cho biết số mili giây trước ngày 01 tháng 1 , 1970,

bạn có thể xem kết quả mà bạn nhận được khi bạn cố gắng để cung cấp các Long.MIN_VALUELong.MAX_VALUE trong constructor ngày.

DateFormat df = new SimpleDateFormat("d MMM yyyy G, HH:mm:ss.S Z"); 
System.out.println(df.format(new Date(Long.MIN_VALUE))); 
System.out.println(df.format(new Date(Long.MAX_VALUE))); 

Ideone Demo

+0

cách này trả lời một câu hỏi? – AdamSkywalker

+0

Cảm ơn, tôi biết. Câu hỏi không phải là về giá trị mili giây âm trước năm 1970, nhưng về giá trị mili giây ngược trước năm 0. – praisezh

1

tôi phát hiện ra rằng Java xử lý các giá trị "đảo ngược" gần như chính xác, ngoại trừ các ngày trong tuần.

Trong ví dụ đầu tiên của bạn, hai ngày không giống nhau - một là BC và một trong những AD khác (điều này giải thích lý do tại sao ngày nào trong tuần là khác nhau):

Date d1 = new Date(253402214400000l); 
Date d2 = new Date(-377648784000000l); 
DateFormat fmt = new SimpleDateFormat("yyyy G"); 
System.out.println(fmt.format(d1)); //9999 AD 
System.out.println(fmt.format(d2)); //9999 BC 

Vì vậy, quan sát của bạn chỉ là trùng hợp ngẫu nhiên (tuy nhiên có thể có một trình định dạng ngày nào đó đã biến mất và phủ nhận những năm hoặc năm thực sự có thể âm trong cơ sở dữ liệu của bạn).

Sự khác biệt với trình chuyển đổi trực tuyến có thể là do cách tính năm 0 và/hoặc các biến thể trong lịch được sử dụng để tính toán.

+0

Nhưng khởi động lại thời gian chạy Java đã giải quyết được vấn đề :-) vì vậy không có giá trị sai trong cơ sở dữ liệu, không có định dạng ngày đặc biệt nào được sử dụng. – praisezh

+1

@praisezh Bạn có thể tìm cách tái tạo vấn đề không? – assylias

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