Come ottenere la data UTC + 0 in Java 8?


108

Ho problemi con la classe Date in Java. La classe Date restituisce la data della macchina locale ma ho bisogno di UTC-0.

Ho cercato su Google e ho trovato un'ottima soluzione per JavaScript ma per Java niente di utile.

Come ottenere la data UTC + 0 in Java 8?


12
java.util.Datenon è mai una data della macchina locale. È sempre definito come millisecondi trascorsi dal 1970-01-01 rispetto a UTC + 00: 00. Forse il comportamento del suo metodo toString()ti confonde che in effetti usa una rappresentazione nel fuso orario locale.
Meno Hochschild

Una probabile risposta può essere trovata nella domanda: stackoverflow.com/questions/45350095/…
Priya Jain

Risposte:


146

Con Java 8 puoi scrivere:

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

Per rispondere al tuo commento, puoi quindi convertirlo in una data (a meno che tu non dipenda dal codice legacy, non vedo alcun motivo) o in millisecondi dalle epoche:

Date date = Date.from(utc.toInstant());
long epochMillis = utc.toEpochSecond() * 1000;

1
Grazie. è possibile convertire ZonedDateTime in Date o in long (ms)?
Marco

7
Anche se il codice di questa risposta funziona tecnicamente, non sarebbe più appropriato usare OffsetDateTimepiuttosto che ZonedDateTimedato che stiamo lavorando con un semplice offset da UTC piuttosto che con un fuso orario completo?
Basil Bourque

179

tl; dr

Instant.now()

java.time

Le fastidiose vecchie classi data-ora in bundle con le prime versioni di Java sono state soppiantate dalle classi java.time integrate in Java 8 e versioni successive. Vedi Oracle Tutorial . Molte delle funzionalità sono state portate indietro a Java 6 e 7 in ThreeTen-Backport e ulteriormente adattate ad Android in ThreeTenABP .

Instant

Un Instantrappresenta un momento sulla timeline in UTC con una risoluzione fino a nanosecondi .

Instant instant = Instant.now();

Il toStringmetodo genera un oggetto String con testo che rappresenta il valore di data e ora utilizzando uno dei formati ISO 8601 standard .

String output = instant.toString();  

2016-06-27T19: 15: 25.864Z

La Instantclasse è una classe elementare di base in java.time. Questa dovrebbe essere la tua lezione quando gestisci la data e l'ora, poiché generalmente la best practice è quella di monitorare, archiviare e scambiare i valori di data e ora in UTC.

OffsetDateTime

Ma Instantha limitazioni come nessuna opzione di formattazione per la generazione di stringhe in formati alternativi. Per una maggiore flessibilità, converti da Instanta OffsetDateTime. Specificare un offset da UTC . In java.time ciò significa un ZoneOffsetoggetto. Qui vogliamo restare con UTC (+00) in modo da poter usare la comoda costante ZoneOffset.UTC.

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

2016-06-27T19: 15: 25.864Z

Oppure salta la Instantlezione.

OffsetDateTime.now( ZoneOffset.UTC )

Ora con un OffsetDateTimeoggetto in mano, puoi usarlo DateTimeFormatterper creare oggetti String con testo in formati alternativi. Cerca in Stack Overflow molti esempi di utilizzo DateTimeFormatter.

ZonedDateTime

Quando si desidera visualizzare l' ora dell'orologio da parete per un determinato fuso orario, applicare a ZoneIdper ottenere a ZonedDateTime.

In questo esempio applichiamo il fuso orario di Montréal. In estate, sotto l' assurdità dell'ora legale (DST) , la zona ha un offset di -04:00. Quindi nota come l'ora del giorno è quattro ore prima nell'output, 15invece delle 19ore. Instanted ZonedDateTimeentrambi rappresentano lo stesso momento simultaneo, appena visto attraverso due lenti differenti.

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

2016-06-27T15: 15: 25,864-04: 00 [America / Montreal]

Conversione

Anche se dovresti evitare le vecchie classi data-ora, se devi puoi convertire usando nuovi metodi aggiunti alle vecchie classi. Qui usiamo java.util.Date.from( Instant )e java.util.Date::toInstant.

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

E andando nella direzione opposta.

Instant instant= utilDate.toInstant();

Allo stesso modo, cerca nuovi metodi aggiunti a GregorianCalendar(sottoclasse di Calendar) da convertire in e da java.time.ZonedDateTime.

Tabella dei tipi di classi data-ora nel moderno java.time rispetto a legacy.

Informazioni su java.time

Il framework java.time è integrato in Java 8 e versioni successive. Queste classi soppiantare la vecchia fastidiosi legacy classi data-time come java.util.Date, Calendar, e SimpleDateFormat.

Per saperne di più, vedere il tutorial Oracle . E cerca Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310 .

Il progetto Joda-Time , ora in modalità di manutenzione , consiglia la migrazione alle classi java.time .

Puoi scambiare oggetti java.time direttamente con il tuo database. Utilizza un driver JDBC conforme a JDBC 4.2 o successivo. Non c'è bisogno di stringhe, non c'è bisogno di java.sql.*classi. Hibernate 5 e JPA 2.2 supportano java.time .

Dove ottenere le classi java.time?


3
Apprezzo per aver detto che l'ora legale non ha senso :-)
prash

quindi se l'ora legale non esistesse ZonedDateTimenon sarebbe necessaria perché tutto ZoneIdverrebbe mappato su uno ZoneOffsetche potremmo semplicemente usare OffsetDateTime?
Wilmol

1
@wilmol No. L'ora legale (DST) è solo uno dei tanti motivi per cui i politici scelgono di ridefinire i confini e gli offset del fuso orario all'interno di tali zone. Recentemente la Corea del Nord ha cambiato il proprio orologio di mezz'ora per sincronizzarsi con la Corea del Sud per motivi diplomatici. In guerra, gli invasori / occupanti possono modificare l'offset in modo che corrisponda a quello del paese di origine. Attualmente v'è una nuova moda in cui i governi hanno scelto di fermarsi modifiche dell'ora legale, ma di restare in modo permanente sul DST piuttosto che ritornano alle loro precedente tempo standard. Pianifica sempre l'offset di ogni cambio di zona o la tua app finirà per non funzionare.
Basil Bourque

1
Risposta fantastica! Apprezzo molto il tempo che ci dedichi. :)
drognisep

ZoneId.of ("America / Montreal"); perché qualcuno dovrebbe inventare una cosa del genere in jdk? è brutto, disgustoso, non dire se c'è qualcosa di sbagliato fino al momento dell'esecuzione, chi può ricordare tutti quei codici hard? perché non impiantarlo in classe ENUM?
ciclo di lavoro del

4

In java8, userei la Instantclasse che è già in UTC ed è conveniente lavorare con.

import java.time.Instant;

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

Instant ins2 = Instant.ofEpochMilli(ts)

In alternativa, puoi utilizzare quanto segue:

import java.time.*;

Instant ins = Instant.now(); 

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

Torna a Instant

Instant ins4 = Instant.from(odt);

3
No, nonInstant è nell'ora locale. An per definizione è in UTC. Quindi non c'è bisogno delle macchinazioni viste in questa risposta che cercano di entrare in UTC; il già è in UTC. Vedi la mia risposta per maggiori informazioni e codice molto più semplice. InstantInstant
Basil Bourque

Grazie per il commento.
Abel Terefe


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.