System.currentTimeMillis () retorna a hora UTC?

93

Desejo obter a hora UTC atual em milissegundos. Eu pesquisei no google e encontrei algumas respostas que System.currentTimeMillis () retorna a hora UTC. mas isso não acontece. Se eu fizer o seguinte:

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

todas as três vezes são quase iguais (a diferença é em milissegundos devido às chamadas).

t1 = 1372060916
t2 = 1372060917
t3 = 1372060918

e esta hora não é a hora UTC, em vez disso, é o meu fuso horário. Como posso obter a hora UTC atual no android?

g.revolution
fonte
4
Retorna a hora atual do sistema em milissegundos desde 1 de janeiro de 1970 00:00:00 UTC
Blackbelt
3
longo t3 = Calendar.getInstance (TimeZone.getTimeZone ("UTC")). getTimeInMillis ();
Blackbelt
3
O link acima diz: "Veja a descrição da classe Date para uma discussão das pequenas discrepâncias que podem surgir entre o" horário do computador "e o horário universal coordenado (UTC)." e na documentação java.util.Date você encontra: "Embora a classe Date se destine a refletir a hora universal coordenada (UTC), pode não fazê-lo exatamente, dependendo do ambiente de host da Java Virtual Machine" -> então pode é possível que sua máquina retorne horário não UTC
Marco Forberg
4
@ g.revolution: É "o número de milissegundos desde 1º de janeiro de 1970 00:00:00 UTC" - como você esperaria que isso se ajustasse a um fuso horário? Seu fuso horário local não afeta quantos milissegundos ocorreram desde aquela época.
Jon Skeet

Respostas:

132

Todas as três linhas que você mostrou darão o número de milissegundos desde a época do unix, que é um ponto fixo no tempo, não afetado pelo seu fuso horário local.

Você diz "esta hora não é a hora UTC" - eu suspeito que você realmente diagnosticou isso incorretamente. Eu sugeriria usar epochconverter.com para isso. Por exemplo, em seu exemplo:

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

Não sabemos quando você gerou esse valor, mas a menos que seja realmente às 8:01 UTC, é um problema com o relógio do sistema.

Nem, System.currentTimeMillisnem o valor dentro de Datesi são afetados pelo fuso horário. No entanto, você deve estar ciente de que Date.toString() não usar o fuso horário local, que engana muitos desenvolvedores em pensar que uma Dateestá intrinsecamente associada uma zona de tempo - não é, é apenas um instante no tempo, sem um fuso horário associado ou sistema de calendário mesmo.

Jon Skeet
fonte
6
Então, basicamente, quer dizer que esta função retorna o mesmo valor se chamada ao mesmo tempo de fusos horários diferentes, independente do relógio do host, correto?
Phillip em
14
Cara, isso me faz desejar que o mundo adotasse (pudesse) um único fuso horário. Quem se importa se o número do relógio é 00:00 ou 08:00, quando a grande coisa brilhante aparece no céu? As incontáveis ​​horas de tempo produtivo desperdiçadas nesta relíquia histórica fazem meu sangue ferver ...
corsiKa
Relacionado a isso, observe que a chamada subjacente à função de relógio do sistema operacional tem um 'desvio' documentado de vários milissegundos. Java tem um 'cronômetro de alto desempenho' se a intenção é obter uma duração altamente precisa de uma operação (cronometragem quando uma tarefa começa e termina, o delta sendo a quantidade de tempo decorrido). Veja: docs.oracle.com/javase/7/docs/api/java/lang/…
Darrell Teague
@JonSkeet se toString () usar fuso horário internamente, como poderia construir string a partir dele sem fuso horário. Na verdade, estou gerando um arquivo no servidor REST que tem um nome de arquivo exatamente com o valor da meia-noite ex "1551139200.json" (26 de fevereiro de 2019 às 12h00) e que precisa ser acessado do aplicativo Android assim que o System.currentTimeMillis do dispositivo () retorna a hora exata.
kiranking
@kiranking: Use Date.getTime()para encontrar o tempo em milissegundos desde a época do Unix, divida por 1000 (já que o nome do arquivo está em segundos desde a época do Unix) e apenas formate esse inteiro como uma string.
Jon Skeet
3

Posso confirmar que todas as três chamadas podem depender da hora local, considerando a época, e não o Date.toString()ou qualquer método semelhante. Já vi que dependem da hora local em dispositivos específicos que executam o Android 2.3. Não os testei com outros dispositivos e versões do Android. Neste caso, a hora local foi acertada manualmente.

A única maneira confiável de obter uma hora UTC independente é solicitando uma atualização de local usando o GPS_PROVIDER. O getTime()valor de um local recuperado NETWORK_PROVIDERtambém depende da hora local. Outra opção é fazer ping em um servidor que retorna um carimbo de data / hora UTC, por exemplo.

Então, o que eu faço é o seguinte:

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
fonte
1
System.currentTimeMillis () retorna um valor baseado em UTC. Quanto à 'precisão' ou exatidão do relógio do sistema operacional, embora isso certamente afete o resultado, não está de forma alguma relacionado ao valor do fuso horário do sistema ou do ambiente Java.
Darrell Teague de
@DarrellTeague, eu insisto, vi valores diferentes em um dispositivo específico da Huawei. Portanto, não, ele nem sempre retorna a hora UTC correta (descartando as diferenças de precisão)
jlhonora
A pergunta do OP era sobre o uso do fuso horário da classe Java. Não se tratava de hardware ou da precisão do valor de tempo retornado. Simplificando, a JVM obtém seu tempo do "relógio do sistema" operacional (abstrato) (que varia de acordo com o sistema operacional em termos de funcionamento). Consulte também: drdobbs.com/embedded-systems/… e implementações "C" em sistemas operacionais chemie.fu-berlin.de/chemnet/use/info/libc/libc_17.html
Darrell Teague