Należy pamiętać, że zegary komputerowe nie są ustawione nigdzie w pobliżu tego poziomu dokładności - dwa zegary na różnych komputerach zwykle różnią się o co najmniej kilka milisekund, chyba że włożysz trochę wysiłku w skonfigurowanie procedury synchronizacji o wysokiej dokładności (kiedy coś takiego jest nawet fizycznie możliwe). Nie mogę sobie wyobrazić, jaki byłby sens znajomości czasu komputera z dokładnością do mikrosekundy. (Jeśli próbujesz zmierzyć interwał dokładnie na jednym komputerze, to na pewno jest to całkowicie rozsądne, ale nie potrzebujesz pełnego znacznika czasu.)
David Z
2
Ponadto niektóre wersje systemu Unix / Linux zwracają tylko 1 milisekundę lub 10 milisekund szczegółowości w polu mikrosekund.
Stephen C
Pośrednim sposobem jest użycie JDBC , jeśli jest podłączony do bazy danych, takiej jak Postgres, która rejestruje bieżący czas w mikrosekundach.
Basil Bourque
2
Java 9 i późniejsze:Instant.now()
Basil Bourque
Użyj funkcji Instant, aby obliczyć mikrosekundy od Epoki: val instant = Instant.now();val currentTimeMicros = instant.getEpochSecond() * 1000_000 + instant.getNano() / 1000;
Michael M.,
Odpowiedzi:
149
Nie, Java nie ma takiej możliwości.
Ma System.nanoTime (), ale to po prostu daje przesunięcie w stosunku do wcześniej znanego czasu. Więc chociaż nie możesz wziąć z tego absolutnej liczby, możesz użyć jej do pomiaru precyzji nanosekundowej (lub wyższej).
Zauważ, że JavaDoc mówi, że chociaż zapewnia to precyzję nanosekundową, nie oznacza to dokładności nanosekundowej. Więc weź odpowiednio duży moduł wartości zwracanej.
Można by przypuszczać, że powodem, dla którego Java nie ma metody getTimeInMicroseconds (), są: 1) dokładność niedostępna na wielu platformach, 2) zwracanie milisekundowej dokładności w wywołaniu mikrosekundowym prowadzi do problemów z przenośnością aplikacji.
Stephen C
9
W Linuksie System.nanoTime () wywołuje clock_gettime (CLOCK_MONOTONIC, _). Brian Oxley sięgnął do kodu źródłowego Javy, aby znaleźć ten samorodek.
David Weber,
8
Ta odpowiedź jest teraz nieaktualna . Implementacje OpenJDK i Oracle Java 9 są wyposażone w nową implementację, Clockktóra umożliwia uchwycenie bieżącego momentu z rozdzielczością dokładniejszą niż milisekundy. Na MacBooku Pro Retina otrzymuję aktualny czas w mikrosekundach (sześć cyfr części dziesiętnej). Rzeczywiste wyniki i dokładność zależą od sprzętu zegarowego komputera głównego.
Basil Bourque
1
@BasilBourque wiele systemów nadal działa na Javie 8 lub nawet wcześniej, ponieważ nie ma potrzeby ich migracji. Chociaż odpowiedź jest nieaktualna, nadal jest przydatna.
Dragas
1
@Dragas Właściwie należałoby je przenieść… aby uzyskać aktualny czas w mikrosekundach, zgodnie z tym pytaniem.
Basil Bourque
81
tl; dr
Java 9 i nowsze: rozdzielczość do nanosekund podczas rejestrowania bieżącego momentu. To 9 cyfr ułamka dziesiętnego.
Instant// Represent a moment in UTC. .now()// Capture the current moment. Returns a `Instant` object. .truncatedTo(// Lop off the finer part of this moment. ChronoUnit.MICROS // Granularity to which we are truncating. )// Returns another `Instant` object rather than changing the original, per the immutable objects pattern.
2017-12-23T12: 34: 56.123456Z
W praktyce zobaczysz uchwycone tylko mikrosekundy, .nowponieważ współczesne konwencjonalne zegary sprzętu komputerowego nie są dokładne w nanosekundach .
Detale
Pozostałe odpowiedzi są nieco nieaktualne od wersji Java 8.
java.time
Java 8 i nowsze są dostarczane ze strukturą java.time . Te nowe klasy zastępują wadliwe, kłopotliwe klasy daty i czasu dostarczane z najwcześniejszymi wersjami języka Java, takie jak java.util.Date/.Calendar i java.text.SimpleDateFormat. Framework definiuje JSR 310, zainspirowany Joda-Time , rozszerzony o projekt ThreeTen-Extra.
Klasy w java.time są rozwiązywane do nanosekund , znacznie dokładniejszych niż milisekundy używane zarówno przez stare klasy daty i godziny, jak i przez Joda-Time. I dokładniejszy niż mikrosekundy zadane w pytaniu.
Clock Realizacja
Chociaż klasy java.time obsługują dane reprezentujące wartości w nanosekundach, klasy nie generują jeszcze wartości w nanosekundach. Te now()metody użyć tego samego starego zegara jako realizację dawnych klas data-czasowych System.currentTimeMillis(). Mamy nowy Clockinterfejs w java.time, ale implementacja tego interfejsu to ten sam stary zegar milisekundowy.
Więc możesz sformatować tekstową reprezentację wyniku, ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )aby zobaczyć dziewięć cyfr ułamka sekundy, ale tylko pierwsze trzy cyfry będą miały liczby takie jak ta:
2017-12-23T12:34:56.789000000Z
Nowy zegar w Javie 9
Implementacje OpenJDK i Oracle Java 9 mają nową domyślną Clockimplementację z większą szczegółowością, aż do pełnej nanosekundowej możliwości klas java.time.
Na MacBooku Pro (Retina, 15-calowym, koniec 2013 r.) Z macOS Sierra otrzymuję aktualny moment w mikrosekundach (do sześciu cyfr ułamka dziesiętnego).
2017-12-23T12:34:56.123456Z
Zegar sprzętowy
Pamiętaj, że nawet przy nowej, lepszej Clockimplementacji, wyniki mogą się różnić w zależności od komputera. Java jest zależna od zegara sprzętu komputerowego, aby poznać aktualny moment.
Rozdzielczość zegarów sprzętowe są bardzo zróżnicowane. Na przykład, jeśli zegar sprzętowy konkretnego komputera obsługuje dokładność tylko w mikrosekundach , wszelkie wygenerowane wartości daty i godziny będą miały tylko sześć cyfr ułamka sekundy, a ostatnie trzy cyfry będą zerami.
Dokładność zegarów sprzętowe są bardzo zróżnicowane. Tylko dlatego, że zegar generuje wartość z kilkoma cyframi dziesiętnego ułamka sekundy, cyfry te mogą być niedokładne, tylko przybliżone, odbiegające od rzeczywistego czasu, które można odczytać z zegara atomowego . Innymi słowy, tylko dlatego, że widzisz kilka cyfr po prawej stronie znaku dziesiętnego, nie oznacza, że możesz ufać, że czas, który upłynął między takimi odczytami, będzie zgodny z tym minutowym stopniem.
Mogą rozwiązywać się do nanosekund, ale nadal są oparte na System.currentTimeMillis, więc na końcu dodają po prostu kilka zer. W ogóle nie pomaga, jeśli próbujesz uzyskać czas w mikro / nano sekundach, użytkownik może po prostu ręcznie dodać 0s do milisekund.
annedroiid
@annedroiid Omówiłem to w mojej odpowiedzi. W Javie 8 możesz przechowywać momenty z rozdzielczością nanosekund, ale uchwycenie aktualnego momentu jest tylko w milisekundach. Naprawiono w Javie 9 dzięki nowej implementacji Clock. Mimo to w Javie 8 klasy java.time są przydatne do przechowywania wartości przechwyconych przez inne źródła, takie jak mikrosekundy, w bazie danych Postgres. Uważaj jednak na niedokładność wartości w zakresie mikrosekund i nanosekund; Zwykły sprzęt komputerowy może nie mieć dokładnego czasu śledzenia zegara sprzętowego. Wartość zawierająca sześć lub dziewięć cyfr ułamka sekundy może nie być prawdą.
@Roland Tak, teraz naprawione, dzięki. Do Twojej wiadomości, na Stack Overflow zapraszamy do bezpośredniej edycji odpowiedzi w celu naprawienia takiego błędu.
long start =System.nanoTime();// do stufflong end =System.nanoTime();long microseconds =(end - start)/1000;
aby uzyskać czas w nanosekundach, ale jest to miara ściśle względna. Nie ma absolutnego znaczenia. Przydaje się tylko do porównania z innymi nanoczasami, aby zmierzyć, jak długo coś trwało.
Jak już wskazywały inne plakaty; Twój zegar systemowy prawdopodobnie nie jest zsynchronizowany do mikrosekund z rzeczywistym czasem światowym. Niemniej jednak znaczniki czasu z dokładnością do mikrosekund są przydatne jako hybryda zarówno do wskazywania aktualnego czasu ściany, jak i do pomiaru / profilowania czasu trwania rzeczy.
Oznaczam wszystkie zdarzenia / wiadomości zapisane w plikach dziennika za pomocą sygnatur czasowych, takich jak „2012-10-21 19: 13: 45.267128”. Wskazują one zarówno kiedy to się wydarzyło (czas „ściany”), jak i mogą być również użyte do pomiaru czasu trwania między tym a następnym zdarzeniem w pliku dziennika (względna różnica w mikrosekundach).
Aby to osiągnąć, musisz połączyć System.currentTimeMillis () z System.nanoTime () i od tego momentu pracować wyłącznie z System.nanoTime (). Przykładowy kod:
/**
* Class to generate timestamps with microsecond precision
* For example: MicroTimestamp.INSTANCE.get() = "2012-10-21 19:13:45.267128"
*/publicenumMicroTimestamp{ INSTANCE ;privatelong startDate ;privatelong startNanoseconds ;privateSimpleDateFormat dateFormat ;privateMicroTimestamp(){this.startDate =System.currentTimeMillis();this.startNanoseconds =System.nanoTime();this.dateFormat =newSimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");}publicString get(){long microSeconds =(System.nanoTime()-this.startNanoseconds)/1000;long date =this.startDate +(microSeconds/1000);returnthis.dateFormat.format(date)+String.format("%03d", microSeconds %1000);}}
Pomysł jest dobry, ale od czasu do czasu musisz ponownie zsynchronizować. Czas systemowy (currentTime) i zegar procesora (nanoTime) NIE są zsynchronizowane, ponieważ często są oparte na różnych zegarach sprzętowych. Ponadto serwer czasu systemu operacyjnego ponownie synchronizuje zegar systemowy z zewnętrznym źródłem czasu, jeśli jest dostępne. Dlatego Twoja pozornie bardzo precyzyjna klasa będzie generować znaczniki czasu, które mogą być dalekie!
h2stein
3
Ten kod nie wydaje się być bezpieczny dla wątków. Dwa jednoczesne połączenia MicroTimestamp.INSTANCE.get()mogą być problematyczne.
Ahmed,
@Ahmed Dlaczego uważasz, że kod nie jest bezpieczny dla wątków? W get()metodzie nie ma nic , co aktualizowałoby zmienne składowe; używa tylko tymczasowych zmiennych lokalnych.
Jason Smith
6
Możesz utworzyć komponent, który określa przesunięcie między System.nanoTime () i System.currentTimeMillis () i efektywnie uzyskać nanosekundy od epoki.
Jeśli interesuje Cię Linux: Jeśli wyłowisz kod źródłowy do „currentTimeMillis ()”, zobaczysz, że wywołanie tej metody w Linuksie powoduje cofnięcie się o mikrosekundę. Jednak Java skraca następnie mikrosekundy i zwraca milisekundy. Dzieje się tak częściowo dlatego, że Java musi być wieloplatformowa, więc dostarczanie metod specjalnie dla Linuksa było wielkim nie-nie w tamtych czasach (pamiętajcie, że obsługa linków miękkich od wersji 1.6 wstecz ?!) Dzieje się tak również dlatego, że chociaż zegar w Linuksie może zwracać mikrosekundy, niekoniecznie oznacza to, że będzie dobry do sprawdzania czasu. Na poziomach mikrosekund musisz wiedzieć, że NTP nie wyrównuje twojego czasu i że twój zegar nie dryfował zbytnio podczas wywołań metod.
Oznacza to, że teoretycznie w systemie Linux można napisać opakowanie JNI, które jest takie samo jak w pakiecie System, ale nie skracać mikrosekund.
„szybkie i brudne” rozwiązanie, które ostatecznie wybrałem:
TimeUnit.NANOSECONDS.toMicros(System.nanoTime());
AKTUALIZACJA:
Początkowo korzystałem z System.nanoTime, ale potem odkryłem, że powinien być używany tylko przez upływający czas, ostatecznie zmieniłem kod, aby działał z milisekundami lub w niektórych miejscach używam:
Doc wyraźnie mówi się nie używać System.nanoTimena upływ czasu: „Metoda ta może być stosowana tylko do mierzenia upływu czasu i nie jest związana z żadnym innym pojęciem systemu lub upływ czasu.”
Basil Bourque
1
@BasilBourque masz rację, po napisaniu tego w końcu dowiedziałem się i zmieniłem kod, ale zapomniałem tutaj zaktualizować, dzięki za komentarz!
keisar
2
Obsługa języka Java w mikrosekundach przez TimeUnitwyliczenie.
To nie jest poprawne, otrzymasz czas w rozdzielczości / długości MICRO, ale sam czas będzie zawsze tylko z dokładnością MILI (co oznacza, że ostatnie 3 cyfry będą zawsze równe 0).
Michalsx
0
Jeśli zamierzasz używać go w systemie czasu rzeczywistego, być może java nie jest najlepszym wyborem, aby uzyskać znacznik czasu. Ale jeśli zamierzasz użyć klucza if dla unikalnego klucza, odpowiedź Jasona Smitha wystarczy. Ale na wszelki wypadek, aby przewidzieć, że 2 elementy otrzymają ten sam znacznik czasu (jest to możliwe, jeśli te 2 zostały przetworzone prawie jednocześnie), możesz zapętlić, aż ostatni znacznik czasu nie będzie równy bieżącemu znacznikowi czasu.
Niepoprawna odpowiedź. Klasa java.util.Date ma rozdzielczość w milisekundach, a nie mikrosekundach określoną w pytaniu. Utworzenie java.sql.Timestamp nie powoduje wyrzucenia dodatkowych danych z powietrza.
Instant.now()
val instant = Instant.now();
val currentTimeMicros = instant.getEpochSecond() * 1000_000 + instant.getNano() / 1000;
Odpowiedzi:
Nie, Java nie ma takiej możliwości.
Ma System.nanoTime (), ale to po prostu daje przesunięcie w stosunku do wcześniej znanego czasu. Więc chociaż nie możesz wziąć z tego absolutnej liczby, możesz użyć jej do pomiaru precyzji nanosekundowej (lub wyższej).
Zauważ, że JavaDoc mówi, że chociaż zapewnia to precyzję nanosekundową, nie oznacza to dokładności nanosekundowej. Więc weź odpowiednio duży moduł wartości zwracanej.
źródło
Clock
która umożliwia uchwycenie bieżącego momentu z rozdzielczością dokładniejszą niż milisekundy. Na MacBooku Pro Retina otrzymuję aktualny czas w mikrosekundach (sześć cyfr części dziesiętnej). Rzeczywiste wyniki i dokładność zależą od sprzętu zegarowego komputera głównego.tl; dr
Java 9 i nowsze: rozdzielczość do nanosekund podczas rejestrowania bieżącego momentu. To 9 cyfr ułamka dziesiętnego.
Aby ograniczyć do mikrosekund , obetnij .
W praktyce zobaczysz uchwycone tylko mikrosekundy,
.now
ponieważ współczesne konwencjonalne zegary sprzętu komputerowego nie są dokładne w nanosekundach .Detale
Pozostałe odpowiedzi są nieco nieaktualne od wersji Java 8.
java.time
Java 8 i nowsze są dostarczane ze strukturą java.time . Te nowe klasy zastępują wadliwe, kłopotliwe klasy daty i czasu dostarczane z najwcześniejszymi wersjami języka Java, takie jak java.util.Date/.Calendar i java.text.SimpleDateFormat. Framework definiuje JSR 310, zainspirowany Joda-Time , rozszerzony o projekt ThreeTen-Extra.
Klasy w java.time są rozwiązywane do nanosekund , znacznie dokładniejszych niż milisekundy używane zarówno przez stare klasy daty i godziny, jak i przez Joda-Time. I dokładniejszy niż mikrosekundy zadane w pytaniu.
Clock
RealizacjaChociaż klasy java.time obsługują dane reprezentujące wartości w nanosekundach, klasy nie generują jeszcze wartości w nanosekundach. Te
now()
metody użyć tego samego starego zegara jako realizację dawnych klas data-czasowychSystem.currentTimeMillis()
. Mamy nowyClock
interfejs w java.time, ale implementacja tego interfejsu to ten sam stary zegar milisekundowy.Więc możesz sformatować tekstową reprezentację wyniku,
ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )
aby zobaczyć dziewięć cyfr ułamka sekundy, ale tylko pierwsze trzy cyfry będą miały liczby takie jak ta:Nowy zegar w Javie 9
Implementacje OpenJDK i Oracle Java 9 mają nową domyślną
Clock
implementację z większą szczegółowością, aż do pełnej nanosekundowej możliwości klas java.time.Zobacz kwestię OpenJDK, Zwiększ precyzję implementacji java.time.Clock.systemUTC () . Ten problem został pomyślnie wdrożony.
Na MacBooku Pro (Retina, 15-calowym, koniec 2013 r.) Z macOS Sierra otrzymuję aktualny moment w mikrosekundach (do sześciu cyfr ułamka dziesiętnego).
Zegar sprzętowy
Pamiętaj, że nawet przy nowej, lepszej
Clock
implementacji, wyniki mogą się różnić w zależności od komputera. Java jest zależna od zegara sprzętu komputerowego, aby poznać aktualny moment.źródło
Clock
. Mimo to w Javie 8 klasy java.time są przydatne do przechowywania wartości przechwyconych przez inne źródła, takie jak mikrosekundy, w bazie danych Postgres. Uważaj jednak na niedokładność wartości w zakresie mikrosekund i nanosekund; Zwykły sprzęt komputerowy może nie mieć dokładnego czasu śledzenia zegara sprzętowego. Wartość zawierająca sześć lub dziewięć cyfr ułamka sekundy może nie być prawdą.Możesz użyć
System.nanoTime()
:aby uzyskać czas w nanosekundach, ale jest to miara ściśle względna. Nie ma absolutnego znaczenia. Przydaje się tylko do porównania z innymi nanoczasami, aby zmierzyć, jak długo coś trwało.
źródło
Jak już wskazywały inne plakaty; Twój zegar systemowy prawdopodobnie nie jest zsynchronizowany do mikrosekund z rzeczywistym czasem światowym. Niemniej jednak znaczniki czasu z dokładnością do mikrosekund są przydatne jako hybryda zarówno do wskazywania aktualnego czasu ściany, jak i do pomiaru / profilowania czasu trwania rzeczy.
Oznaczam wszystkie zdarzenia / wiadomości zapisane w plikach dziennika za pomocą sygnatur czasowych, takich jak „2012-10-21 19: 13: 45.267128”. Wskazują one zarówno kiedy to się wydarzyło (czas „ściany”), jak i mogą być również użyte do pomiaru czasu trwania między tym a następnym zdarzeniem w pliku dziennika (względna różnica w mikrosekundach).
Aby to osiągnąć, musisz połączyć System.currentTimeMillis () z System.nanoTime () i od tego momentu pracować wyłącznie z System.nanoTime (). Przykładowy kod:
źródło
MicroTimestamp.INSTANCE.get()
mogą być problematyczne.get()
metodzie nie ma nic , co aktualizowałoby zmienne składowe; używa tylko tymczasowych zmiennych lokalnych.Możesz utworzyć komponent, który określa przesunięcie między System.nanoTime () i System.currentTimeMillis () i efektywnie uzyskać nanosekundy od epoki.
Poniższy test daje dość dobre wyniki na moim komputerze.
Różnica wydaje się oscylować w przedziale + -3 ms. Wydaje mi się, że można by nieco bardziej podkręcić obliczenia przesunięcia.
źródło
Jeśli interesuje Cię Linux: Jeśli wyłowisz kod źródłowy do „currentTimeMillis ()”, zobaczysz, że wywołanie tej metody w Linuksie powoduje cofnięcie się o mikrosekundę. Jednak Java skraca następnie mikrosekundy i zwraca milisekundy. Dzieje się tak częściowo dlatego, że Java musi być wieloplatformowa, więc dostarczanie metod specjalnie dla Linuksa było wielkim nie-nie w tamtych czasach (pamiętajcie, że obsługa linków miękkich od wersji 1.6 wstecz ?!) Dzieje się tak również dlatego, że chociaż zegar w Linuksie może zwracać mikrosekundy, niekoniecznie oznacza to, że będzie dobry do sprawdzania czasu. Na poziomach mikrosekund musisz wiedzieć, że NTP nie wyrównuje twojego czasu i że twój zegar nie dryfował zbytnio podczas wywołań metod.
Oznacza to, że teoretycznie w systemie Linux można napisać opakowanie JNI, które jest takie samo jak w pakiecie System, ale nie skracać mikrosekund.
źródło
„szybkie i brudne” rozwiązanie, które ostatecznie wybrałem:
AKTUALIZACJA:
Początkowo korzystałem z System.nanoTime, ale potem odkryłem, że powinien być używany tylko przez upływający czas, ostatecznie zmieniłem kod, aby działał z milisekundami lub w niektórych miejscach używam:
ale to po prostu doda zera na końcu wartości (micros = millis * 1000)
Zostawiłem tę odpowiedź tutaj jako „znak ostrzegawczy” na wypadek, gdyby ktoś pomyślał o nanoTime :)
źródło
System.nanoTime
na upływ czasu: „Metoda ta może być stosowana tylko do mierzenia upływu czasu i nie jest związana z żadnym innym pojęciem systemu lub upływ czasu.”Obsługa języka Java w mikrosekundach przez
TimeUnit
wyliczenie.Oto dokument java: Enum TimeUnit
Możesz uzyskać mikrosekundy w Javie w ten sposób:
Możesz także przekonwertować mikrosekundy z powrotem na inne jednostki czasu, na przykład:
źródło
Jeśli zamierzasz używać go w systemie czasu rzeczywistego, być może java nie jest najlepszym wyborem, aby uzyskać znacznik czasu. Ale jeśli zamierzasz użyć klucza if dla unikalnego klucza, odpowiedź Jasona Smitha wystarczy. Ale na wszelki wypadek, aby przewidzieć, że 2 elementy otrzymają ten sam znacznik czasu (jest to możliwe, jeśli te 2 zostały przetworzone prawie jednocześnie), możesz zapętlić, aż ostatni znacznik czasu nie będzie równy bieżącemu znacznikowi czasu.
źródło
Użyj funkcji Instant, aby obliczyć mikrosekundy od Epoki:
źródło
źródło
Oto przykład sposobu tworzenia UnsignedLong current Timestamp:
źródło