2015-11-02 10 views
66

Jedna z funkcji nowego interfejsu API Data Time w Java 8 ma być dokładnością nanosekundową. Jednak podczas drukowania bieżącej daty Czas na konsoli jak takDlaczego nowy interfejs API Data 8 Java 8 nie ma dokładności nanosekundowej?

DateTimeFormatter formatter = DateTimeFormatter 
    .ofPattern("yyyy-MM-dd'T'HH:mm:ss,nnnnnnnnnZ"); 
System.out.println(OffsetDateTime.now().format(formatter)); 

widzę tylko precyzji milisekundy: 2015-11-02T12: 33: 26,746000000 + 0100

System operacyjny wydaje się wspierać dokładność nanosekundowa. Kiedy wydrukować bieżącą datę czasu przez terminal

date -Ins 

widzę 2015-11-02T12: 33: 26,746134417 + 0100

Jak uzyskać nanosekund precyzji w Java? Używam Oracle Java 1.8.0_66 na Ubuntu 14.04 64-bit

+1

zaradzić w Javie 9. [A] świeży realizacji (https: // bugs.openjdk.java.net/browse/JDK-8068730) z ['Clock'] (https://docs.oracle.com/javase/8/docs/api/java/time/Clock.html) przechwytuje bieżący moment w rozdzielczości aż do nanosekund (w zależności od możliwości zegara sprzętowego komputera). –

Odpowiedz

101

Interfejs API java.timema ma nanosekundową precyzję. Na przykład:

DateTimeFormatter formatter = DateTimeFormatter 
    .ofPattern("yyyy-MM-dd'T'HH:mm:ss,nnnnnnnnnZ"); 
OffsetDateTime odt = OffsetDateTime.of(2015, 11, 2, 12, 38, 0, 123456789, ZoneOffset.UTC); 
System.out.println(odt.format(formatter)); 

wyjściowa:

2015-11-02T12:38:00,123456789+0000 

Jednakże, jest to wartość zwracana przez OffsetDateTime.now() zegar, który wraca do wartości, która ma tylko milisekund.

Od Clock wdrożenia w Java 8:

Realizacja zegar umieszczono tutaj opiera się na System.currentTimeMillis(). Ta metoda zapewnia niewielką lub żadną gwarancję co do dokładności zegara. Aplikacje wymagające dokładniejszego zegara muszą implementować tę klasę abstrakcyjną za pomocą innego zegara zewnętrznego, takiego jak serwer NTP.

Więc nie ma nic z natury nieprecyzyjne tutaj - tylko wdrożenie domyślny Clock użyciu System.currentTimeMillis(). Możesz potencjalnie stworzyć własną, bardziej precyzyjną podklasę. Należy jednak pamiętać, że dodanie większej precyzji bez dodawania większej dokładności dokładności prawdopodobnie nie jest bardzo przydatne. (Są chwile, kiedy może to być, co prawda ...)

+7

Ten ostatni bit jest szczególnie ważny. ['nanosleep (2)'] (http://linux.die.net/man/2/nanosleep) ma podobne problemy na standardowym sprzęcie klasy konsumenckiej, ponieważ spanie dla dokładnej liczby nanosekund obejmuje pasek błędu ~ 1 Cykl CPU, którego tak naprawdę nie da się zrobić w środowisku z wielowymiarową metodą zapobiegawczą. Mimo to wysoki poziom precyzji może być przydatny, gdy trzeba po prostu zamówić różne zdarzenia względem siebie i nie dbać o dokładne odstępy między nimi. Zakładam, że zegar rośnie monotonicznie, co mam nadzieję * jest prawdą. – Kevin

51

Aby ważny dodatek do odpowiedzi Jon Skeet, Java 9 ma dostarczyć zegar w lepszej precyzji - patrz the bug log. Tło: w wielu systemach operacyjnych (zwłaszcza w systemie Linux) dostępne są lepsze zegary.

Java SE 8 Specyfikacja java.time.Clock stwierdza, że ​​„Metody fabrycznych systemów zapewnić zegary na podstawie najlepszych dostępnych zegara systemowego
. To może używać System.currentTimeMillis() lub wyższy zegar rozdzielczości, jeśli jest dostępny. ". W JDK 8 implementacja
zegara została oparta na System.currentTimeMillis(), a ma zatem tylko rozdzielczość milisekundową. W JDK 9 implementacja
opiera się na podstawowym zegarze macierzystym, który wykorzystuje System.currentTimeMillis(), zapewniając maksymalną rozdzielczość dostępną z tego zegara.W większości systemów może to być mikrosekundy, lub czasami nawet dziesiąta mikrosekund.

Aplikacja przy założeniu, że zegar zwrócony przez tych metod fabrycznych systemu zawsze będą miały precyzji milisekund i aktywnie zależy na nim, może dlatego muszą być aktualizowane w celu brać pod uwagę możliwość większej rozdzielczości , tak jak było
określone w dokumentacji API.

Należy również zauważyć, przycisk (egzotycznych) fakt, że drugi precyzja nie będzie istnieć w pobliżu przestępnych sekund - nawet w Javie 9.

+0

Czy jest więcej informacji o tym, dlaczego druga precyzja nie istnieje w pobliżu sekund przestępnych? Czy to dlatego, że istnieje [wiele sposobów na ich wdrożenie] (https://en.wikipedia.org/wiki/Leap_second#Workarounds_for_leap_second_issues) (np. Smuga)? – Thunderforge

+5

@Thunderforge Wyrażenie takie jak 'ChronoUnit.SECONDS.between (instant1, instant2)' nie może nigdy liczyć sekund przestępnych. Konstruktorzy 'java.time' postanowili ukryć sekundy przestępne i udawać, że każda minuta składa się z 60 sekund. Ich specyfikacja oficjalnie upoważnia UTC-SLS, a prawdziwa implementacja w JDK jest de facto podobna do POSIX, a nie UTC-SLS - po prostu ignorując sekundy przestępne. Wszystkie znane zegary systemu operacyjnego (jako baza 'Clock.systemUTC()' zachowują się w ten sam sposób lub stosują pewien rodzaj resetowania zegara lub przeskakiwania s. SI-secs nie są modelowane.Jeśli poważnie szukasz prawdziwego wsparcia dla seksu skoku, rozważ moje lib Time4J. –