2012-10-30 14 views
5

एक बग के बाद, मैंने देखा है कि अगर मैं java.sql.Timestamp को java.util.Date से बनाता हूं, तो कन्स्ट्रक्टर का उपयोग करके जो मिलीसेकंड लेता है, दिनांक उदाहरण हमेशा टाइमस्टैम्प के बाद होता है। यह परेशान है, क्योंकि (ए) पहले() के लिए अनुबंध एक सख्त तुलना निर्दिष्ट करता है और (बी) यदि बराबर नहीं है, तो टाइमस्टैम्प, क्योंकि इसमें नैनोसेकंड हैं, यह तिथि() के बाद हो सकता है। लेकिन परिणाम विपरीत और दोहराने योग्य हैं (जेडीके 1.6 और 1.7 के साथ, विभिन्न जेवीएम टाइमज़ोन के साथ)। दो तिथियों की तुलना सही ढंग से काम करता है, लेकिन किसी तारीख को() या बाद() से पहले कॉल करना और टाइमस्टैम्प तर्क देने से अप्रत्याशित परिणाम होते हैं।java.sql.Timestamp java.util.Date से बनाया गया, हमेशा क्यों पहले()?

नीचे दिए गए नमूना कोड में दो दिनांक और एक टाइमस्टैंप उदाहरण है, उनमें से सभी एक ही मिलीसेकंद मूल्य के साथ हैं। फिर भी एक टाइमस्टैम्प के साथ एक तिथि की तुलना करने से तारीख() Timestamp के बाद होने वाली तारीख दिखाती है।

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? 
    } 
} 

नमूना उत्पादन:

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 

अंतिम पंक्ति उत्सुक एक है।

धन्यवाद।

+0

इसे इंगित करने के लिए डीबगर का उपयोग करें। और [Timestamp API] को याद दिलाएं (http://docs.oracle.com/javase/6/docs/api/java/sql/Timestamp.html) * "[...] यह अनुशंसा की जाती है कि कोड टाइमस्टैम्प मानों को न देखे सामान्य रूप से java.util.Date के उदाहरण के रूप में। "* – Kai

+1

' d1.compareTo (ts); 'परिणाम' 1', यह दर्शाता है कि 1 नैनो अंतर या पसंद का कुछ है। ___ मुझे विश्वास है कि यह एक बग है, हां। अच्छा काम यह खोज रहा है! – XenoRo

उत्तर

6

आप आंतरिक प्रतिनिधित्व को देखो और क्या after() विधि में तुलना की जाती है, तो आप देखते हैं कि उदाहरण के लिए के लिए

millis = 1351607849957 

आप एक Date साथ

fastTime = 1351607849957 

और एक Timestamp

साथ मिल
fastTime = 1351607849000 
nanos = 957000000 

चूंकि तुलना की गई सभी चीजें fastTime भाग है, आपको अपना मनाया व्यवहार मिलता है। ऊपर @ user714965 अंक के रूप में, आपको Timestamp को Date के रूप में नहीं माना जाना चाहिए।

+0

आह, यह है। धन्यवाद। –

4

java.sql.Timestamp की API दस्तावेज़ का कहना है:

नोट: इस प्रकार का एक java.util.Date और एक अलग नैनोसेकंड मूल्य का एक समग्र है। java.util.Date घटक में केवल अभिन्न सेकंड संग्रहीत किए जाते हैं। आंशिक सेकंड - नैनो - अलग हैं।

(यह केपिल के उत्तर से सहमत है)।

यह भी कहते हैं:

Timestamp वर्ग और java.util.Date वर्ग ऊपर उल्लेख किया है के बीच मतभेद के कारण, यह है कि कोड java.util.Date का एक उदाहरण के रूप में सामान्य रूप से Timestamp मूल्यों को नहीं देख सिफारिश की है। Timestamp और java.util.Date के बीच विरासत संबंध वास्तव में कार्यान्वयन विरासत को दर्शाता है, और विरासत टाइप नहीं करता है।

इसका मतलब है कि आप एक java.util.Date, जो कि तुम क्या कर रहे है, तो आप (java.util.Date.after() को इसे पारित उस विधि की उम्मीद के रूप में Timestamp का इलाज नहीं करना चाहिए एक java.util.Date - यदि आप एक Timestamp में गुजर रहे हैं, यह इलाज के रूप में अगर यह एक है java.util.Date, जो यह टिप्पणी कहती है कि आपको नहीं करना चाहिए)।

यह मानक जावा लाइब्रेरी में खराब खराब डिज़ाइन है। यदि आपको तिथियों और समय के साथ काम करने की ज़रूरत है, तो Joda Time का उपयोग करें, जो एक बेहतर डिजाइन और अधिक शक्तिशाली लाइब्रेरी है।

+0

हां, मुझे उन मतभेदों (और असंगतताओं, विशेष रूप से बराबर()) के साथ-साथ जोडा के बारे में पता है, लेकिन मैं इस अजीब व्यवहार की व्याख्या की तलाश में हूं। –

+0

ध्यान दें कि आप 'java.sql.Timestamp' जैसी कक्षा के स्रोत कोड में खोद सकते हैं, आप इसे' src.zip' फ़ाइल में पा सकते हैं जो आपकी जेडीके स्थापना निर्देशिका में है। – Jesper

संबंधित मुद्दे