¿Cómo obtener la fecha UTC + 0 en Java 8?

108

Tengo problemas con la clase Date en Java. La clase de fecha devuelve la fecha de la máquina local pero necesito UTC-0.

Busqué en Google y encontré una gran solución para JavaScript, pero para Java nada útil.

¿Cómo obtener la fecha UTC + 0 en Java 8?

marca
fuente
12
java.util.Datenunca es una fecha de máquina local. Siempre se define como milisegundos transcurridos desde 1970-01-01 en relación con UTC + 00: 00. Tal vez el comportamiento de su método lo toString()confunda, ya que de hecho usa una representación en la zona horaria local.
Meno Hochschild
Se puede encontrar una respuesta probable en la pregunta: stackoverflow.com/questions/45350095/…
Priya Jain

Respuestas:

146

Con Java 8 puedes escribir:

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

Para responder a su comentario, puede convertirlo en una Fecha (a menos que dependa del código heredado, no veo ninguna razón por la cual) o en milisegundos desde las épocas:

Date date = Date.from(utc.toInstant());
long epochMillis = utc.toEpochSecond() * 1000;
Assylias
fuente
1
Gracias. ¿Es posible convertir ZonedDateTime en Date o en long (ms)?
Marcos
7
Si bien el código de esta respuesta funciona técnicamente, ¿no sería más apropiado usarlo en OffsetDateTimelugar de ZonedDateTimedado que estamos trabajando con un simple desplazamiento de UTC en lugar de una zona horaria completa?
Basil Bourque
179

tl; dr

Instant.now()

java.time

Las problemáticas clases antiguas de fecha y hora incluidas con las primeras versiones de Java han sido suplantadas por las clases java.time integradas en Java 8 y posteriores. Consulte el tutorial de Oracle . Gran parte de la funcionalidad se ha actualizado a Java 6 y 7 en ThreeTen-Backport y se ha adaptado aún más a Android en ThreeTenABP .

Instant

An Instantrepresenta un momento en la línea de tiempo en UTC con una resolución de hasta nanosegundos .

Instant instant = Instant.now();

El toStringmétodo genera un objeto String con texto que representa el valor de fecha y hora utilizando uno de los formatos estándar ISO 8601 .

String output = instant.toString();  

2016-06-27T19: 15: 25.864Z

La Instantclase es una clase básica de bloques de construcción en java.time. Esta debería ser su clase de referencia cuando maneje la fecha y hora, ya que generalmente la mejor práctica es rastrear, almacenar e intercambiar valores de fecha y hora en UTC.

OffsetDateTime

Pero Instanttiene limitaciones como no tener opciones de formato para generar cadenas en formatos alternativos. Para mayor flexibilidad, convierta de Instanta OffsetDateTime. Especifique un desplazamiento de UTC . En java.time eso significa un ZoneOffsetobjeto. Aquí queremos seguir con UTC (+00) para poder usar la constante conveniente ZoneOffset.UTC.

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

2016-06-27T19: 15: 25.864Z

O salte la Instantclase.

OffsetDateTime.now( ZoneOffset.UTC )

Ahora, con un OffsetDateTimeobjeto en la mano, puede usarlo DateTimeFormatterpara crear objetos String con texto en formatos alternativos. Busque Stack Overflow para ver muchos ejemplos de uso DateTimeFormatter.

ZonedDateTime

Cuando desee mostrar la hora del reloj de pared para una zona horaria en particular, aplique un ZoneIdpara obtener un ZonedDateTime.

En este ejemplo, aplicamos la zona horaria de Montreal. En el verano, según la tontería del horario de verano (DST) , la zona tiene una compensación de -04:00. Observe que la hora del día es cuatro horas antes en la salida, en 15lugar de 19horas. Instanty ZonedDateTimeambos representan el mismo momento simultáneo, visto a través de dos lentes diferentes.

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

2016-06-27T15: 15: 25.864-04: 00 [América / Montreal]

Mudado

Si bien debe evitar las antiguas clases de fecha y hora, si es necesario, puede convertir utilizando nuevos métodos agregados a las antiguas clases. Aquí usamos java.util.Date.from( Instant )y java.util.Date::toInstant.

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

Y yendo en la otra dirección.

Instant instant= utilDate.toInstant();

De manera similar, busque nuevos métodos agregados a GregorianCalendar(subclase de Calendar) para convertir ay desde java.time.ZonedDateTime.

Tabla de tipos de clases de fecha y hora en java.time moderno versus heredado.

Acerca de java.time

El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora como java.util.Date, Calendar, y SimpleDateFormat.

Para obtener más información, consulte el tutorial de Oracle . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

Puede intercambiar objetos java.time directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No se necesitan cuerdas, no se necesitan java.sql.*clases. Hibernate 5 y JPA 2.2 admiten java.time .

¿Dónde obtener las clases java.time?

Albahaca Bourque
fuente
3
Aprecio por decir que el horario de verano es una
tontería
entonces, si DST no existiera, ZonedDateTime¿no sería necesario ya que todos ZoneIdse asignarían a uno ZoneOffsetque podríamos usar OffsetDateTime?
wilmol
1
@wilmol No. El horario de verano (DST) es solo una de las muchas razones por las que los políticos eligen redefinir los límites de las zonas horarias y las compensaciones dentro de esas zonas. Recientemente, Corea del Norte cambió su reloj media hora para sincronizarse con Corea del Sur por razones diplomáticas. En la guerra, los invasores / ocupantes pueden cambiar la compensación para que coincida con la del país de origen. Actualmente hay una nueva moda en la que los gobiernos eligen detener los cambios de horario de verano, pero permanecen permanentemente en el horario de verano en lugar de volver a su horario estándar anterior. Siempre planifique la compensación de cada cambio de zona o su aplicación eventualmente se romperá.
Basil Bourque
1
¡Respuesta fantástica! Realmente aprecio el tiempo que dedicas a esto. :)
drognisep
ZoneId. De ("América / Montreal"); ¿Por qué alguien inventaría tal cosa en jdk? es feo, repugnante, no decir si hay algo mal hasta el momento de la ejecución, ¿quién puede recordar todo ese código duro? ¿Por qué no lo implica en la clase ENUM?
workplaylifecycle
4

En java8, usaría la Instantclase que ya está en UTC y es conveniente trabajar con ella.

import java.time.Instant;

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

Instant ins2 = Instant.ofEpochMilli(ts)

Alternativamente, puede utilizar lo siguiente:

import java.time.*;

Instant ins = Instant.now(); 

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

De regreso Instant

Instant ins4 = Instant.from(odt);
Abel Terefe
fuente
3
No, noInstant es a la hora local. Una , por definición, es en UTC. Por lo tanto, no es necesario que las maquinaciones que se ven en esta Respuesta intenten ingresar a UTC; el ya está en UTC. Vea mi respuesta para obtener más información y un código mucho más simple. InstantInstant
Basil Bourque
Gracias por el comentario.
Abel Terefe
0

Solución de 1 línea en Java 8:

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