возвращает ли System.currentTimeMillis () время UTC?

93

Я хочу получить текущее время UTC в миллисекундах. Я поискал в Google и получил несколько ответов, что System.currentTimeMillis () действительно возвращает время в формате UTC. но это не так. Если я сделаю следующее:

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

все три раза практически одинаковы (разница в миллисекундах из-за звонков).

t1 = 1372060916
t2 = 1372060917
t3 = 1372060918

и это время не в формате UTC, а в моем часовом поясе. Как я могу узнать текущее время в формате UTC в android?

g.революция
источник
5
Возвращает текущее системное время в миллисекундах с 1 января 1970 г., 00:00:00 UTC
Blackbelt,
3
long t3 = Calendar.getInstance (TimeZone.getTimeZone ("UTC")). getTimeInMillis ();
Blackbelt
3
В приведенной выше ссылке говорится: «См. Описание класса Date для обсуждения небольших расхождений, которые могут возникнуть между« компьютерным временем »и всемирным координированным временем (UTC)». и в документации java.util.Date вы найдете: «Хотя класс Date предназначен для отображения скоординированного всемирного времени (UTC), он может не делать этого точно, в зависимости от среды хоста виртуальной машины Java» -> поэтому он может возможно, что ваша машина возвращает время,
отличное от
4
@ g.revolution: Это «количество миллисекунд с 00:00:00 UTC 1 января 1970 г.» - как вы ожидаете, что это изменится с учетом часового пояса? Ваш местный часовой пояс не влияет на количество миллисекунд, прошедших с той эпохи.
Джон Скит,

Ответы:

134

Все три строки, которые вы показали, дадут количество миллисекунд с эпохи unix, которая является фиксированной точкой во времени, не зависящей от вашего местного часового пояса.

Вы говорите: «Это время не по Гринвичу» - я подозреваю, что вы на самом деле неправильно это диагностировали. Я бы посоветовал использовать для этого epochconverter.com . Например, в вашем примере:

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

Мы не знаем, когда вы сгенерировали это значение, но если это не произошло на самом деле в 8:01 по всемирному координированному времени, это проблема с вашими системными часами.

Ни , System.currentTimeMillisни стоимость в Dateсебе страдают от временной зоны. Однако вы должны знать, что Date.toString() он использует местный часовой пояс, что вводит в заблуждение многих разработчиков, заставляя думать, что a Dateпо своей сути связано с часовым поясом - это не так, это просто момент времени, без соответствующего часового пояса или даже календарной системы.

Джон Скит
источник
6
По сути, это означает, что эта функция возвращает одно и то же значение, если вызывается в одно и то же время из разных часовых поясов, независимо от часов хоста, правильно?
Филлип
15
Чувак, это заставляет меня желать, чтобы мир (мог) принять единый часовой пояс. Кого волнует, будет ли число на часах 00:00 или 08:00, когда в небе появляется большая яркая вещь? Бесчисленные часы продуктивного времени, потраченного на эту историческую реликвию, заставляют мою кровь
закипать
В связи с этим обратите внимание, что основной вызов функции часов ОС имеет задокументированный «дрейф» на несколько миллисекунд. В Java есть «высокопроизводительный таймер», если намерение состоит в том, чтобы получить очень точную продолжительность операции (время, когда задача начинается и заканчивается, а дельта - это прошедшее время). См .: docs.oracle.com/javase/7/docs/api/java/lang/…
Даррелл Тиг,
@JonSkeet, если toString () внутренне использует часовой пояс, как я могу построить из него строку без часового пояса. На самом деле я создаю файл на сервере REST, имя файла которого соответствует значению времени в полночь, например, «1551139200.json» (26 февраля 2019 г., 12:00:00), и к нему необходимо получить доступ из приложения Android после того, как устройство System.currentTimeMillis () возвращает точное время.
Киранкинг
@kiranking: используйте, Date.getTime()чтобы найти время в миллисекундах с эпохи Unix, разделите на 1000 (поскольку имя файла находится в секундах с эпохи Unix) и просто отформатируйте это целое число как строку.
Джон Скит,
2

Я могу подтвердить, что все три звонка могли зависеть от местного времени, учитывая эпоху, а не от Date.toString()какого-либо подобного метода. Я видел, что они зависят от местного времени на определенных устройствах под управлением Android 2.3. Я не тестировал их с другими устройствами и версиями Android. В этом случае местное время выставлялось вручную.

Единственный надежный способ получить независимое время в формате UTC - это запросить обновление местоположения с помощью GPS_PROVIDER. ВgetTime()Значение местоположения , извлеченное из NETWORK_PROVIDERтакже зависит от местного времени. Другой вариант - это проверить связь с сервером, который, например, возвращает метку времени в формате UTC.

Итак, я делаю следующее:

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
источник
1
System.currentTimeMillis () возвращает значение на основе UTC. Что касается «точности» или точности часов операционной системы, это, безусловно, влияет на результат, но никоим образом не связано со значением часового пояса системы или среды Java.
Даррелл Тиг,
@DarrellTeague Я настаиваю, я видел разные значения в конкретном устройстве Huawei. Так что нет, он не всегда возвращает правильное время в формате UTC (без
учета
Вопрос OP касался использования часового пояса класса Java. Дело не в оборудовании или точности возвращаемого значения времени. Проще говоря, JVM получает свое время от (абстрактных) операционных «системных часов» (которые зависят от операционной системы с точки зрения ее функций). См. Также: drdobbs.com/embedded-systems/… и реализации "C" в операционных системах chemie.fu-berlin.de/chemnet/use/info/libc/libc_17.html
Даррелл Тиг