2013-03-26 22 views
10

Ciao Ho un frammento di codice come questo:java.sql.Timestamp bug di confronto?

Date d1 = new java.sql.Timestamp(new Date().getTime()); 
Thread.sleep(10); 
Date d2 = new java.sql.Timestamp(new Date().getTime()); 
System.out.println("Date1: " + d1); 
System.out.println("Date2: " + d2); 
System.out.println("Comparing times d1.t < d2.t: " + (d1.getTime() < d2.getTime())); 
System.out.println("Comparing dates d1.before(d2): " + (d1.before(d2))); 

L'output è simile al seguente:

Date1: 2013-03-26 11:04:01.093 
Date2: 2013-03-26 11:04:01.103 
Comparing times d1.t < d2.t: true 
Comparing dates d1.before(d2): false 

Cosa c'è di sbagliato con questa classe java.sql.Timestamp?

Sì, ho visto questo:

Nota: Questo tipo è un composto di un java.util.Date e un valore nanosecondi separata. Solo i secondi interi sono memorizzati nel componente java.util.Date. I secondi frazionari - i nanos - sono separati. Il metodo Timestamp.equals (Object) non restituisce mai true quando viene passato un valore di tipo java.util.Date perché il componente nanos di una data è sconosciuto. Di conseguenza, il metodo Timestamp.equals (Object) non è simmetrico rispetto al metodo java.util.Date.equals (Object). Inoltre, il metodo hashcode utilizza l'implementazione java.util.Date sottostante e quindi non include i nanos nel suo calcolo.

causa delle differenze tra la classe Timestamp e la classe java.util.Date sopra menzionato, si raccomanda che il codice non visualizzare valori timestamp genericamente come un'istanza java.util.Date. La relazione di ereditarietà tra Timestamp e java.util.Date indica in realtà l'ereditarietà dell'implementazione e non l'ereditarietà del tipo.

Ma è per Data < -> Rapporto di data e ora.

Nel mio esempio ho solo timestamp, ed ancora il comportamento è inaspettato ..

UPDATE: RISPOSTA

Il motivo per cui questo accade è che before() metodo è sovraccarico, non sovrascritto in java.sql.Timestamp. Mi aspettavo un comportamento 'override'. Il modo corretto per confrontare i timestamp è avere le variabili del Timestamp, non le Date.

Questo è ancora una decisione cattiva progettazione nel nucleo di Java, in quanto eredità dovrebbe significaretimestamp è-un Data, senza alcuna penalità e le eccezioni ..

+0

credo ho trovato il problema in un altro post. Per favore [recensione] (http://stackoverflow.com/a/13141377/1758149). Il problema è che non si dovrebbe trattare un 'TimeStamp' come una data. – RyPope

risposta

2

Provare a utilizzare Timestamp anziché Date e funzionerà.

Timestamp d1 = new java.sql.Timestamp(new Date().getTime()); 

Timestamp e Date entrambi hanno proprio implementazione del metodo before. Controllalo.

3

Bene, sembra come un sotto-documentata caratteristica.

I metodi before e after di Timestamp sembrano comparare fino al secondo, ma non tenendo conto della parte dei millisecondi. Prova ad eseguirlo fino a quando entrambi gli TimeStamp cadono in secondi distinti e il confronto funziona come previsto (incrementa il sonno a 500 per renderlo più semplice).

A proposito, il metodo compareTo tiene conto dei millisecondi, quindi è possibile utilizzarlo.

1

Se si chiama il metodo Timestamp.before(Timestamp), si otterrà il risultato previsto.

Ma apparentemente l'uso di uno Timestamp come Date sarà un disordine tutto intorno. È necessario utilizzare Timestamp come Timestampstaticamente.

0

Come accennato qui

timestamp is a thin wrapper

Un timestamp aggiunge semplicemente la capacità di tenere il frazionaria valore dei secondi SQL TIMESTAMP (con una precisione del nanosecondo in cui il problema nel tuo caso è derivanti)