Como obter a data UTC + 0 no Java 8?

108

Tenho problemas com a classe Date em Java. A classe de data retorna a data da máquina local, mas eu preciso de UTC-0.

Eu pesquisei e encontrei uma ótima solução para JavaScript, mas para Java nada útil.

Como obter a data UTC + 0 no Java 8?

Marca
fonte
12
java.util.Datenunca é uma data de máquina local. É sempre definido como milissegundos decorridos desde 01/01/1970 em relação ao UTC + 00: 00. Talvez o comportamento de seu método o toString()confunda, que de fato usa uma representação em fuso horário local.
Meno Hochschild,
Uma resposta provável pode ser encontrada na pergunta: stackoverflow.com/questions/45350095/…
Priya Jain

Respostas:

146

Com o Java 8 você pode escrever:

OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);

Para responder ao seu comentário, você pode convertê-lo em uma data (a menos que dependa de um código legado, não vejo nenhuma razão para isso) ou em milis desde as épocas:

Date date = Date.from(utc.toInstant());
long epochMillis = utc.toEpochSecond() * 1000;
assilias
fonte
1
obrigado. é possível converter ZonedDateTime em Date ou em long (ms)?
Marque
7
Embora o código deste respondente funcione tecnicamente, não seria mais apropriado usar em OffsetDateTimevez de ZonedDateTimeconsiderar que estamos trabalhando com um mero deslocamento do UTC em vez de um fuso horário completo?
Basil Bourque de
179

tl; dr

Instant.now()

java.time

As antigas classes problemáticas de data e hora empacotadas com as primeiras versões do Java foram suplantadas pelas classes java.time construídas no Java 8 e posterior. Veja o tutorial Oracle . Muitas das funcionalidades foram adaptadas para Java 6 e 7 no ThreeTen-Backport e posteriormente adaptadas para Android no ThreeTenABP .

Instant

Um Instantrepresenta um momento na linha do tempo em UTC com uma resolução de até nanossegundos .

Instant instant = Instant.now();

O toStringmétodo gera um objeto String com texto que representa o valor de data e hora usando um dos formatos padrão ISO 8601 .

String output = instant.toString();  

2016-06-27T19: 15: 25.864Z

A Instantclasse é uma classe de bloco de construção básico em java.time. Esta deve ser sua aula preferida ao lidar com data e hora, pois geralmente a prática recomendada é rastrear, armazenar e trocar valores de data e hora em UTC.

OffsetDateTime

Mas Instanttem limitações, como nenhuma opção de formatação para gerar strings em formatos alternativos. Para obter mais flexibilidade, converta de Instantpara OffsetDateTime. Especifique um deslocamento do UTC . Em java.time, isso significa um ZoneOffsetobjeto. Aqui, queremos manter o UTC (+00) para que possamos usar a constante conveniente ZoneOffset.UTC.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC );

2016-06-27T19: 15: 25.864Z

Ou pule a Instantaula.

OffsetDateTime.now( ZoneOffset.UTC )

Agora com um OffsetDateTimeobjeto em mãos, você pode usar DateTimeFormatterpara criar objetos String com texto em formatos alternativos. Procure no Stack Overflow muitos exemplos de uso DateTimeFormatter.

ZonedDateTime

Quando você deseja exibir a hora do relógio para algum fuso horário específico, aplique um ZoneIdpara obter umZonedDateTime .

Neste exemplo, aplicamos o fuso horário de Montreal. No verão, sob o absurdo do horário de verão (DST) , a zona tem um deslocamento de -04:00. Portanto, observe como a hora do dia é quatro horas mais cedo na saída, em 15vez de 19horas. Instante ZonedDateTimeambos representam o mesmo momento simultâneo, visto apenas por duas lentes diferentes.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

2016-06-27T15: 15: 25.864-04: 00 [America / Montreal]

Convertendo

Embora você deva evitar as classes de data e hora antigas, se necessário, você pode converter usando novos métodos adicionados às classes antigas. Aqui usamos java.util.Date.from( Instant )e java.util.Date::toInstant.

java.util.Date utilDate = java.util.Date.from( instant );

E indo na outra direção.

Instant instant= utilDate.toInstant();

Da mesma forma, procure novos métodos adicionados a GregorianCalendar(subclasse de Calendar) para conversão de e para java.time.ZonedDateTime.

Tabela de tipos de classes de data e hora em java.time moderno versus legado.

Sobre java.time

A estrutura java.time é integrada ao Java 8 e posterior. Essas classes suplantar os velhos problemáticos legados aulas de data e hora, como java.util.Date, Calendar, e SimpleDateFormat.

Para saber mais, consulte o tutorial Oracle . E pesquise no Stack Overflow para muitos exemplos e explicações. A especificação é JSR 310 .

O projeto Joda-Time , agora em modo de manutenção , aconselha a migração para as classes java.time .

Você pode trocar objetos java.time diretamente com seu banco de dados. Use um driver JDBC compatível com JDBC 4.2 ou posterior. Não há necessidade de cordas, não há necessidade de java.sql.*classes. Hibernate 5 e JPA 2.2 suportam java.time .

Onde obter as classes java.time?

Basil Bourque
fonte
3
Agradeço por dizer que o horário de verão não faz sentido :-)
prash
então, se o DST não existisse ZonedDateTime, não seria necessário, já que todos ZoneIdseriam mapeados para um ZoneOffsetque poderíamos apenas usar OffsetDateTime?
Wilmol
1
@wilmol Não. O horário de verão (DST) é apenas um dos muitos motivos pelos quais os políticos optam por redefinir os limites e compensações dos fusos horários dentro desses fusos horários. Recentemente, a Coreia do Norte mudou seu relógio em meia hora para sincronizar com a Coreia do Sul por razões diplomáticas. Na guerra, os invasores / ocupantes podem alterar o deslocamento para coincidir com o do país de origem. Atualmente, existe uma nova moda em que os governos estão optando por interromper as alterações do horário de verão, mas permanecem permanentemente no horário de verão, em vez de reverter ao horário padrão anterior. Sempre planeje o deslocamento de cada mudança de zona ou seu aplicativo irá eventualmente quebrar.
Basil Bourque
1
Resposta fantástica! Eu realmente aprecio o tempo que você dedicou a isso. :)
drognisep
ZoneId.of ("América / Montreal"); por que alguém inventaria tal coisa no jdk? é feio, nojento, não dizer se há algo errado até o tempo de execução, quem pode se lembrar de todo aquele código rígido? por que não implementá-lo na classe ENUM?
workplaylifecycle
4

Em java8, eu usaria a Instantclasse que já está em UTC e é conveniente para trabalhar.

import java.time.Instant;

Instant ins = Instant.now();
long ts = ins.toEpochMilli();

Instant ins2 = Instant.ofEpochMilli(ts)

Como alternativa, você pode usar o seguinte:

import java.time.*;

Instant ins = Instant.now(); 

OffsetDateTime odt = ins.atOffset(ZoneOffset.UTC);
ZonedDateTime zdt = ins.atZone(ZoneId.of("UTC"));

De volta a Instant

Instant ins4 = Instant.from(odt);
Abel Terefe
fonte
3
Não, nãoInstant está no horário local. Um , por definição, está em UTC. Portanto, não há necessidade das maquinações vistas nesta Resposta tentando entrar no UTC; o já está em UTC. Veja minha resposta para mais informações e um código muito mais simples. InstantInstant
Basil Bourque de
Obrigado pelo comentário.
Abel Terefe
0

Solução de 1 linha em Java 8:

public Date getCurrentUtcTime() {
    return Date.from(Instant.now());
}
Abhijeet Ashok Muneshwar
fonte