2012-11-06 32 views
26

Próbuję pobrać wartości datownika z bazy danych, przekonwertować je do Kalendarza i przekonwertować je z powrotem do datownika, ale tracą one swoją dokładność.Konwertowanie pliku java.sql.Timestamp na java.util.Calendar bez utraty precyzji

Oto kod do odtworzenia problemu

import java.sql.Timestamp; 
import java.util.Calendar; 

public class Test { 
    public static void main(String[] args) 
    { 
     Timestamp timestamp = new Timestamp(112, 10, 5, 15, 39, 11, 801000000); 
     System.out.println("BEFORE "+timestamp.toString()); 
     Calendar calendar = Calendar.getInstance(); 
     calendar.setTimeInMillis(timestamp.getTime()); 
     timestamp = new Timestamp(calendar.getTimeInMillis()); 
     System.out.println("AFTER "+timestamp.toString()); 
    } 
} 

Oto przykładowy wynik konwersji

BEFORE 2012-10-18 14:30:13.362001 
AFTER 2012-10-18 14:30:13.362 

Traci precyzji. Co mam zrobić, aby zachować wartość dziesiętną taką, jaka jest?

+0

Próbowałem tego w moim ide, ale nie otrzymałem takiego wyniku, za każdym razem, gdy drukuje to samo - 'Calendar calendar = Calendar.getInstance(); \t \t Znacznik czasu znacznika = nowy znacznik czasu (nowa data(). GetTime()); \t \t System.out.println ("1 ->" + znacznik czasu); // \t \t Thread.currentThread(). Sleep (1000); \t \t calendar.setTimeInMillis (timestamp.getTime()); \t \t timestamp = new Timestamp (calendar.getTimeInMillis()); \t System.out.println ("2 ->" + znacznik czasu); ' –

+0

Czy możesz podać więcej kontekstu? Skąd bierzesz te znaczniki czasu, w jaki sposób je generujesz? – axtavt

+0

Zaktualizowałem przykład, przepraszam, że fałszywy wynik był moją winą. – William

Odpowiedz

25

ustawiasz czas w milisekundach , ale twoja precyzja wejściowy w mikrosekund, więc oczywiście masz zamiar stracić żadnej precyzyjnej drobniejsze niż milisekund.

Kalendarz nie obsługuje drobniejszej szczegółowości niż milisekundy. Nie ma żadnego obejścia.

+0

Co to jest obejście? – William

+2

@William Nie ma ani jednego. Zobacz edytowaną odpowiedź. – Bohemian

+0

I nie ma też żadnej alternatywnej klasy? – William

8

java.time

W Javie 8 i później mamy rozwiązanie: nowy java.time ramy jest zbudowany w zdefiniowanym przez JSR 310 inspirowany Joda-Time, rozszerzone przez projekt ThreeTen-Extra.. Ta struktura ma rozdzielczość . To wystarczy, aby obsłużyć stare wartości java.util.Date, wartości Joda-Time, obie są milliseconds. I wystarczy obsłużyć microseconds używany przez niektóre bazy danych, takie jak Postgres. Niektóre bazy danych, takie jak H2, używają nanosekund. Tak więc java.time może obsłużyć to wszystko, lub przynajmniej wszystkie główne nurty. Jedynymi wyjątkami byłyby niszowe sytuacje naukowe lub inżynieryjne.

Image

Z Java 8, stare klasy dostał nowe metody konwersji do/z java.time. Na stronie java.sql.Timestamp użyj nowych metod: toInstant i fromInstant. Klasa Instant zawiera liczbę nanosekund z epoki, pierwszą chwilę 1970 UTC (w zasadzie zobacz dokumentację klasy dla szczegółów).

Od Instant można uzyskać obiekt ZonedDateTime.

java.sql.Timestamp ts = myResultSet.getTimestamp(1); 
Instant instant = ts.toInstant(); 
ZoneId zoneId = ZoneId.of("America/Montreal"); 
ZonedDateTime zdt = instant.atZone(zoneId); 
Powiązane problemy