❌ La risposta accettata non è né corretta né utile.
✅ Al contrario, la risposta di Ole V.V. riassume correttamente le differenze tecniche – per i dettagli seguire i link alle pagine dettagliate in Wikipedia.
Per i programmatori che costruiscono applicazioni orientate al business, il risultato è che UTC è il nuovo GMT. È possibile utilizzare i termini in modo intercambiabile, con la differenza che è letteralmente meno di un secondo. Quindi, per tutti gli scopi pratici nella maggior parte delle applicazioni, non c’è alcuna differenza.
Qui ci sono alcuni consigli più pratici, con esempi di codice.
Stringhe
Ad esempio, ho l’ora UTC come “02-01-2018 00:03” significa che la mia ora locale statunitense è “01-01-2018 18:00”?
Quella prima parte è un cattivo esempio, con la stringa data-ora priva di un indicatore del suo offset o zona.
Se una stringa indica un momento specifico, deve indicare o un fuso orario (Continent/Region
nome formattato) e/o un offset-from-UTC come numero di ore-minuti-secondi. Se la stringa è destinata a rappresentare un momento all’UTC stesso, ciò significa un offset-from-UTC di zero.
Per scrivere quella stringa con un offset, si possono applicare varie convenzioni. La migliore in pratica è con entrambe le ore e i minuti insieme a due punti, come +00:00
+05:30
, o -08:00
. Lo zero iniziale e i due punti sono entrambi opzionali, ma ho visto le librerie rompersi quando incontrano un valore come -0800
o -8
.
Zulu
Come scorciatoia per un offset di zero, la lettera Z
è comunemente usata per indicare UTC stesso. Pronunciato Zulu
.
ISO 8601
Inoltre, la migliore pratica nella formattazione testuale della data-ora per l’informatica è quella di utilizzare i formati standard ISO 8601. Per una data-ora si usa il formato YYYY-MM-DDTHH:MM:SS±HH:MM:SS. Il T
separa la parte della data dalla parte dell’ora del giorno. Questo formato ha dei vantaggi come l’essere in gran parte non ambiguo, facile da analizzare per la macchina, facile da leggere per gli esseri umani attraverso le culture. Un altro vantaggio è che l’ordinamento alfabetico è anche cronologico. Lo standard accetta anche l’abbreviazione Z
.
Quindi il tuo esempio UTC time as "02-01-2018 00:03"
è meglio indicato come 2018-01-02T00:03Z
.
java.time
Siate consapevoli che la maggior parte dei linguaggi di programmazione, delle librerie e dei database hanno un supporto molto scarso per la gestione della data-ora, di solito basato su una scarsa comprensione dei problemi relativi alla data-ora. Gestire la data-ora è sorprendentemente complicato e difficile da padroneggiare.
L’unica libreria decente che ho incontrato è la classe java.time (vedi Tutorial) fornita con Java 8 e successivi, e il suo predecessore il progetto Joda-Time (anche vagamente portato da Java a .Net nel progetto Noda Time).
In java.time, un momento è rappresentato in tre modi. Tutti hanno una risoluzione di nanosecondi.
-
Instant
Sempre in UTC. Tecnicamente, un conteggio di nanosecondi dal riferimento epocale del primo momento del 1970 (1970-01-01T00:00:00Z). -
OffsetDateTime
Una data con l’ora del giorno nel contesto di un certo numero di ore-minuti-secondi avanti, o dietro, UTC. -
ZonedDateTime
Una data con l’ora del giorno nel contesto di un certo fuso orario.
Quindi qual è la differenza tra un fuso orario e un offset-from-UTC? Perché abbiamo bisogno di classi separate? Un offset dall’UTC è semplicemente un numero di ore-minuti-secondi, tre numeri, né più né meno. Un fuso orario è molto di più. Un fuso orario è una storia dei cambiamenti passati, presenti e futuri dell’offset usato dalla gente di una particolare regione.
Che cosa cambia? Cambiamenti dettati dai capricci o dalla saggezza dei loro politici. I politici di tutto il mondo hanno mostrato una predilezione per cambiare l’offset usato dal fuso orario nella loro giurisdizione. L’ora legale (DST) è un modello comune di cambiamenti, con il suo programma spesso cambiato e la decisione di promulgare o ritornare dalla DST a volte cambiata. Altri cambiamenti accadono anche, come negli ultimi anni la Corea del Nord che ha cambiato il suo orologio di mezz’ora per sincronizzarsi con la Corea del Sud, il Venezuela che ha riportato indietro il suo orologio di mezz’ora solo per tornare indietro meno di un decennio dopo, la Turchia che quest’anno ha cancellato il cambiamento programmato dall’ora legale all’ora solare con poco preavviso, e la Russia contemporanea che ha fatto molteplici cambiamenti del genere negli ultimi anni.
Tornando al tuo esempio nel tuo punto # 3, guardiamo un po’ di codice.
Sai, ho l’ora UTC come “02-01-2018 00:03” significa che la mia ora locale statunitense è “01-01-2018 18:00”?
Le tue stringhe di esempio hanno un altro problema. Quel 03
minuto nella prima parte è ignorato la tua seconda parte, un apparente refuso. Lo so perché non c’è nessun aggiustamento di fuso orario in vigore nelle Americhe in quella data che comporta una frazione di ora di 57 minuti.
Non è un momento
Primo, analizziamo la tua stringa di input. Mancando qualsiasi indicatore di zona o di offset, dobbiamo analizzare usando il LocalDateTime
. Il nome LocalDateTime
può essere fuorviante, in quanto indica una località specifica. Significa qualsiasi o tutte le località. Per maggiori spiegazioni, vedere Qual è la differenza tra Instant e LocalDateTime?
String input = "2018-01-02T00:03" ; // Text of a date with time-of-day but without any context of time zore or offset-from-UTC. *Not* a moment, *not* a point on the timeline.LocalDateTime ldt = LocalDateTime.parse( input ) ; // Parsing the input as a `LocalDateTime`, a class representing a date with time but no zone/offset. Again, this does *not* represent a moment, is *not* a point on the timeline.
UTC
Con i fatti riportati nella Domanda, sappiamo che questa data e ora è stata intesa per rappresentare un momento in UTC. Quindi possiamo assegnare il contesto di un offset-from-UTC di zero ore-minuti-secondi per UTC stesso. Applichiamo una ZoneOffset
costante UTC
per ottenere un oggetto OffsetDateTime
.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ); // We are certain this text was intended to represent a moment in UTC. So correct the faulty text input by assigning the context of an offset of zero, for UTC itself.
Fuso orario
La domanda chiede di vedere questo momento attraverso un orologio a muro di sei ore dietro l’UTC usato negli Stati Uniti. Un fuso orario con tale offset è America/Chicago
.
Specificare un nome di fuso orario corretto nel formato continent/region
, come America/Montreal
Africa/Casablanca
, o Pacific/Auckland
. Non utilizzare mai l’abbreviazione di 2-4 lettere come CST
EST
, o IST
poiché non sono veri fusi orari, non sono standardizzati e non sono nemmeno unici(!).
ZoneId z = ZoneId.of( "America/Chicago" ) ; // Adjust from UTC to a time zone where the wall-clock time is six hours behind UTC.ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
Vedi questo codice eseguito dal vivo su IdeOne.com.
odt.toString(): 2018-01-02T00:03Z
zdt.toString(): 2018-01-01T18:03-06:00
Stesso momento, diverso orario dell’orologio a muro
Questo odt
e zdt
rappresentano entrambi lo stesso momento simultaneo, lo stesso punto sulla linea temporale. L’unica differenza è il tempo dell’orologio a muro.
Facciamo un esempio, usando l’Islanda dove il loro fuso orario usa un offset-from-UTC di zero ore-minuti-secondi. Quindi la zona Atlantic/Reykjavik
ha un orario wall-clock identico a UTC. Almeno oggi il loro orario wall-clock corrisponde a UTC; in passato o in futuro potrebbe essere diverso, motivo per cui non è corretto dire “UTC è il fuso orario dell’Islanda”. Comunque, il nostro esempio… diciamo che qualcuno a Reykjavík, Islanda, con 3 minuti dopo la mezzanotte sull’orologio appeso al muro fa una telefonata a qualcuno negli Stati Uniti. Quella persona americana vive in un posto che usa il fuso orario della regione di Chicago. Quando la persona chiamata prende il telefono, alza lo sguardo verso l’orologio appeso al muro e vede che l’ora è appena dopo le 6 PM (18:03). Stesso momento, diverso orario dell’orologio a muro.
Anche i calendari appesi alle loro pareti sono diversi, perché è “domani” in Islanda ma “ieri” negli Stati Uniti continentali. Stesso momento, date diverse!
A proposito di java.time
Il framework java.time è integrato in Java 8 e successivi. Queste classi sostituiscono le vecchie e fastidiose classi legacy per la data-ora come java.util.Date
Calendar
&SimpleDateFormat
.
Il progetto Joda-Time, ora in modalità manutenzione, consiglia la migrazione alle classi java.time.
Per saperne di più, vedere il Tutorial Oracle. E cercate su Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310.
Puoi scambiare oggetti java.time direttamente con il tuo database. Usate un driver JDBC conforme a JDBC 4.2 o successivo. Non c’è bisogno di stringhe, non c’è bisogno di classi java.sql.*
.
Dove ottenere le classi java.time?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11, e successivi – Parte dell’API Java standard con un’implementazione in bundle.
- Java 9 aggiunge alcune caratteristiche minori e correzioni.
- Java SE 6 e Java SE 7
- La maggior parte delle funzionalità di java.time è riportata a Java 6 & 7 in ThreeTen-Backport.
- Android
- Le versioni successive di Android implementano le classi java.time classes.
- Per i precedenti Android (<26), il progetto ThreeTenABP adatta ThreeTen-Backport (menzionato sopra). Vedere Come usare ThreeTenABP….
Il progetto ThreeTen-Extra estende java.time con classi aggiuntive. Questo progetto è un terreno di prova per possibili aggiunte future a java.time. Si possono trovare alcune classi utili qui come Interval
YearWeek
YearQuarter
, e altro ancora.