czy System.currentTimeMillis () zwraca czas UTC?

93

Chcę uzyskać aktualny czas UTC w milisach. Przeszukałem google i otrzymałem odpowiedzi, że System.currentTimeMillis () zwraca czas UTC. ale tak nie jest. Jeśli wykonam następujące czynności:

long t1 = System.currentTimeMillis();
long t2 = new Date().getTime();
long t3 = Calendar.getInstance().getTimeInMillis();

wszystkie trzy czasy są prawie takie same (różnica jest w milisekundach z powodu połączeń).

t1 = 1372060916
t2 = 1372060917
t3 = 1372060918

i tym razem nie jest czasem UTC, a jest to moja strefa czasowa. Jak mogę sprawdzić aktualny czas UTC w systemie Android?

g. rewolucja
źródło
5
Zwraca bieżący czas systemowy w milisekundach od 1 stycznia 1970 00:00:00 UTC
Blackbelt
3
long t3 = Calendar.getInstance (TimeZone.getTimeZone ("UTC")). getTimeInMillis ();
Blackbelt
3
Powyższy link mówi: „Zobacz opis klasy Data, aby zapoznać się z drobnymi rozbieżnościami, które mogą wystąpić między„ czasem komputerowym ”a uniwersalnym czasem koordynowanym (UTC)”. oraz w dokumentacji java.util.Date można znaleźć: „Chociaż klasa Date ma odzwierciedlać skoordynowany czas uniwersalny (UTC), może to nie odzwierciedlać dokładnie, w zależności od środowiska hosta wirtualnej maszyny języka Java” -> więc może być możliwe, że twoja maszyna zwraca czas inny niż UTC
Marco Forberg
4
@ g.revolution: To „liczba milisekund od 1 stycznia 1970 00:00:00 czasu UTC” - jak można się tego spodziewać, aby dostosować się do strefy czasowej? Twoja lokalna strefa czasowa nie wpływa na to, ile milisekund minęło od tej epoki.
Jon Skeet

Odpowiedzi:

134

Wszystkie trzy linie, które pokazałeś, podają liczbę milisekund od epoki unixowej, która jest stałym punktem w czasie, na który nie ma wpływu lokalna strefa czasowa.

Mówisz „ten czas nie jest czasem UTC” - podejrzewam, że faktycznie źle to zdiagnozowałeś. Sugerowałbym użycie do tego epochconverter.com . Na przykład w Twoim przykładzie:

1372060916 = Mon, 24 Jun 2013 08:01:56 GMT

Nie wiemy, kiedy generowany tę wartość, ale chyba to było w rzeczywistości o 8:01 czasu UTC, jest to problem z zegarem systemowym.

Ani System.currentTimeMillisani wartość w Datesobie wpływa strefy czasowej. Należy jednak mieć świadomość, że Date.toString() nie korzystać z lokalnej strefy czasowej, która wprowadza w błąd wielu twórców do myślenia, że Datejest nieodłącznie związane ze strefy czasowej - to nie jest, to tylko chwila w czasie, bez podania strefy czasowej, a nawet systemu kalendarzowego.

Jon Skeet
źródło
6
Zasadniczo oznacza to, że ta funkcja zwraca tę samą wartość, jeśli zostanie wywołana w tym samym czasie z różnych stref czasowych, niezależnie od zegara hosta, prawda?
Phillip,
14
Człowieku, to sprawia, że ​​żałuję, że świat (nie mógłby) przyjąć jednej strefy czasowej. Kogo obchodzi, czy liczba na zegarze to 00:00 czy 08:00, kiedy na niebie pojawia się wielka, jasna rzecz? Niezliczone godziny produktywnego czasu spędzonego na tej historycznej relikwii sprawiają, że moja krew gotuje się ...
corsiKa
W związku z tym należy zauważyć, że podstawowe wywołanie funkcji zegara systemu operacyjnego ma udokumentowany „dryft” wynoszący kilka milisekund. Java ma „zegar o wysokiej wydajności”, jeśli celem jest uzyskanie bardzo precyzyjnego czasu trwania operacji (czas rozpoczęcia i zakończenia zadania, przy czym delta to czas, który upłynął). Zobacz: docs.oracle.com/javase/7/docs/api/java/lang/…
Darrell Teague
@JonSkeet jeśli toString () wewnętrznie używa strefy czasowej, jak mogę zbudować z niej ciąg znaków bez strefy czasowej. W rzeczywistości generuję plik na serwerze REST, który ma nazwę pliku dokładnie o północy, np. „1551139200.json” (26 lutego 2019 r., 12:00:00) i do którego należy uzyskać dostęp z aplikacji na Androida po System.currentTimeMillis () urządzenia zwraca dokładny czas.
kiranking
@kiranking: Użyj, Date.getTime()aby znaleźć czas w milisekundach od epoki uniksowej, podziel przez 1000 (ponieważ nazwa pliku jest w sekundach od epoki systemu Unix) i sformatuj tę liczbę całkowitą jako ciąg.
Jon Skeet
2

Mogę potwierdzić, że wszystkie trzy wezwania mogą zależeć od czasu lokalnego, biorąc pod uwagę epokę, a nie czasDate.toString() metody lub podobnej. Widziałem, że zależą one od czasu lokalnego na określonych urządzeniach z Androidem 2.3. Nie testowałem ich z innymi urządzeniami i wersjami Androida. W tym przypadku czas lokalny został ustawiony ręcznie.

Jedynym niezawodnym sposobem uzyskania niezależnego czasu UTC jest żądanie aktualizacji lokalizacji przy użyciu GPS_PROVIDER. getTime()Wartość pobierana z lokalizacjiNETWORK_PROVIDER zależy również od czasu lokalnego. Inną opcją jest na przykład pingowanie serwera, który zwraca znacznik czasu UTC.

Więc to, co robię, jest następujące:

public static String getUTCstring(Location location) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    String date = sdf.format(new Date(location.getTime()));
    // Append the string "UTC" to the date
    if(!date.contains("UTC")) {
        date += " UTC";
    }
    return date;
}
jlhonora
źródło
1
System.currentTimeMillis () zwraca wartość opartą na czasie UTC. Jeśli chodzi o „precyzję” lub dokładność zegara systemu operacyjnego, choć z pewnością wpływa to na wynik, nie jest w żaden sposób powiązana z wartością strefy czasowej systemu lub środowiska Java.
Darrell Teague
@DarrellTeague Nalegam, widziałem różne wartości w konkretnym urządzeniu Huawei. Więc nie, nie zawsze zwraca prawidłowy czas UTC (
pomijając
Pytanie OP dotyczyło użycia strefy czasowej w klasie Java. Nie chodziło o sprzęt ani dokładność zwracanej wartości czasu. Mówiąc najprościej, JVM pobiera swój czas z (abstrakcyjnego) „zegara systemowego” (który różni się w zależności od systemu operacyjnego pod względem sposobu działania). Zobacz też: drdobbs.com/embedded-systems/… i implementacje "C" w systemach operacyjnych chemie.fu-berlin.de/chemnet/use/info/libc/libc_17.html
Darrell Teague