2013-03-26 28 views
10

Witam Mam fragment kodu:Błąd porównania java.sql.Timestamp?

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))); 

Wyjście wygląda tak:

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 

Co jest złego w tej klasie java.sql.Timestamp?

Tak, widziałem to:

Uwaga: Ten typ jest złożony z java.util.Date oraz oddzielną wartość nanosekund. Tylko integralne sekundy są przechowywane w komponencie java.util.Date. Ułamkowe sekundy - nanosy - są oddzielne. Metoda Timestamp.equals (Object) nigdy nie zwraca wartości true po podaniu wartości typu java.util.Date, ponieważ składnik nanosowy daty jest nieznany. W rezultacie metoda Timestamp.equals (Object) nie jest symetryczna w stosunku do metody java.util.Date.equals (Object). Ponadto metoda hashcode wykorzystuje podstawową implementację java.util.Date i dlatego nie uwzględnia w obliczeniach nanometrów.

Z powodu różnic między klasą Timestamp a wspomnianą wyżej klasą java.util.Date, zaleca się, aby kod nie wyświetlał wartości datownika generalnie jako instancji java.util.Date. Relacja dziedziczenia między znacznikiem czasu i java.util.Date naprawdę oznacza dziedziczenie implementacji, a nie dziedziczenie typu.

Ale to dla daty < -> Relacja czasowa.

W moim przykładzie mam tylko Znaczniki czasu, a mimo to zachowanie jest nieoczekiwane ..

UPDATE: ODPOWIEDŹ

Powodem takiej sytuacji jest fakt, że before() metoda jest przeciążony, nie nadpisane w java.sql.Timestamp. Spodziewałem się zachowania "przesłonięcia". Poprawnym sposobem porównywania sygnatur czasowych jest posiadanie zmiennych datownika, a nie dat.

To wciąż słaba decyzja projektowa w rdzeniu Java, ponieważ dziedziczenie powinny oznaczać datownik to-Date, bez kar i wyjątki ..

+0

wierzę znalazłem problem w innym poście. Proszę [recenzja] (http://stackoverflow.com/a/13141377/1758149). Problem polega na tym, że nie powinno się traktować "TimeStamp" jako daty. – RyPope

Odpowiedz

2

Spróbuj użyć Timestamp zamiast Date i będzie działać.

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

Timestamp i Date oba mają własną implementację metody before. Sprawdź to.

3

Cóż, wydaje się, jako niedostatecznie udokumentowane cecha.

Wydaje się, że metody before i są porównywane do drugiej, ale nie uwzględniają części milisekund. Spróbuj uruchomić go tak długo, aż TimeStamp spadnie do różnych sekund, a porównanie działa zgodnie z oczekiwaniami (zwiększ spoczynek do 500, aby ułatwić).

Nawiasem mówiąc, metoda compareTo bierze pod uwagę milisekundy, więc możesz użyć tego zamiast tego.

1

Jeśli zadzwonisz do metody Timestamp.before(Timestamp), uzyskasz oczekiwany wynik.

Ale najwyraźniej używanie Timestamp jako Date będzie zbędnym problemem. Musisz użyć Timestamp jako Timestampstatycznie.

0

Jak wspomniano tutaj

timestamp is a thin wrapper

znacznik czasu po prostu dodaje możliwość trzymania SQL TIMESTAMP ułamkową wartość sekund (z dokładnością do nanosekund, gdzie problem w przypadku powstaje)

Powiązane problemy