2016-02-03 17 views
6

Miałem sytuacji, w której środowisko wykonawcze Java zwróciło rodzaj "odwróconych" milisekund wartości podczas odczytu dat z bazy danych (w java.sql.Date). Wartość milisekundy wynosiła w przybliżeniu tyle samo dni, ale została odliczona wstecz od roku 0.Jak działa java.sql.Date z ujemnymi datami?

Problem został rozwiązany przez ponowne uruchomienie środowiska wykonawczego Java.

Ale: dowiedziałem się, że Java obsługuje te "odwrócone" wartości prawie poprawnie z wyjątkiem dnia tygodnia.

Po uruchomieniu poniższy kod:

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

otrzymasz następujący wynik:

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

Inny przykład:

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

Wynik:

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

Podczas korzystania z konwerterów online wynik będzie różny dla danej drugiej linii. spowoduje to negatywnego daty (rok jest ujemny) blisko realnej, pozytywnej dniu:

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 

nie znalazłem żadnych informacji o tym „temacie”.

A więc, jaki jest mit za "odwróconymi" datami? Dlaczego Java obsługuje je prawie poprawnie? I jakie jest znaczenie JDBC ResultSet zwracając "odwrócone" wartości milisekund podczas wywoływania resultSet.getDate(1).getTime()?

+0

Czy mówisz o 'java.util.Date' lub' java.sql.Date'? Zdaj sobie sprawę, że zachowanie zestawu wyników JDBC zależy od sterownika, ponieważ każdy sterownik implementuje go dla swojej bazy danych. –

+0

To java.sql.Date (podklasa java.util.Date) – praisezh

+1

Nie mam pojęcia, co masz na myśli przez "odwrócony". – chrylis

Odpowiedz

1

Podczas przekazywania liczby ujemnej w konstruktorze daty jest ona traktowana jako liczba milisekund przed 1/1/1970. Javadoc mówi:

datę - milisekund od 1 stycznia 1970, 00:00:00 GMT, aby nie przekroczyć reprezentacja milisekund na rok 8099. Ujemna liczba wskazuje liczbę milisekund przed dniem 1 stycznia 1970

można zobaczyć wynik, który otrzymasz przy próbie dostarczenia Long.MIN_VALUE i Long.MAX_VALUE datę konstruktora.

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

jak ta odpowiedź stanowi pytanie? – AdamSkywalker

+0

Dzięki, wiem. Nie chodziło o ujemne milisekundy przed rokiem 1970, ale o odwrócone milisekundy przed rokiem 0. – praisezh

1

I okazało się, że Java obsługuje te "odwróconego" wartości prawie poprawnie z wyjątkiem tygodnia dzień.

W pierwszym przykładzie, dwie daty nie są takie same - jeden jest BC, a drugi AD (co wyjaśnia, dlaczego dzień tygodnia jest inny):

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 

Więc obserwacja to tylko zbieg okoliczności (jakkolwiek może być jakiś formatator daty, który zaszokował i neguje lata lub lata mogą faktycznie być negatywne w twojej bazie danych).

Różnica między przelicznikami online wynika prawdopodobnie z uwzględnienia roku 0 i/lub odmiany kalendarza użytego do obliczeń.

+0

Ale restart środowiska wykonawczego Java rozwiązał problem :-), więc nie ma błędnych wartości w bazie danych, żadnych specjalnych formatów daty w użyciu. – praisezh

+1

@praisezh Czy możesz znaleźć sposób na odtworzenie problemu? – assylias

Powiązane problemy