Qual è la differenza tra Instant e LocalDateTime?


256

Lo so:

  • Instant è piuttosto una rappresentazione "tecnica" di data e ora (nanosecondi) per l'informatica.
  • LocalDateTime è piuttosto una rappresentazione di data / orologio compresi i fusi orari per l'uomo.

Ancora alla fine, IMO può essere considerato come tipo per la maggior parte dei casi d'uso dell'applicazione. Ad esempio: attualmente sto eseguendo un processo batch in cui ho bisogno di calcolare una prossima esecuzione in base alle date e sto lottando per trovare vantaggi / svantaggi tra questi due tipi (a parte il vantaggio della precisione dei nanosecondi di Instant e la parte del fuso orario di LocalDateTime).

Puoi citare alcuni esempi di applicazioni in cui utilizzare solo Instant o LocalDateTime?

Modifica: attenzione alle documentazioni errate per LocalDateTime relative a precisione e fuso orario


Instant è più elementare, avvolgendo lo standard long per l'UTC. Per un batch come cron non è una scelta così logica.
Joop Eggen,

37
Definizione errata . LocalDateTimenon non ha un fuso orario!
Basil Bourque,

Risposte:


832

Tabella di tutti i tipi di data e ora in Java, sia moderni che legacy

tl; dr

Instante LocalDateTimesono due animali completamente diversi: uno rappresenta un momento, l'altro no.

  • Instant rappresenta un momento, un punto specifico nella sequenza temporale.
  • LocalDateTimerappresenta una data e un'ora del giorno. Ma mancando di un fuso orario o offset da UTC, questa classe non può rappresentare un momento . Rappresenta potenziali momenti lungo un intervallo di circa 26-27 ore, l'intervallo di tutti i fusi orari in tutto il mondo.

Presunzione errata

LocalDateTime è piuttosto una rappresentazione di data / orologio compresi i fusi orari per l'uomo.

La tua affermazione non è corretta: A nonLocalDateTime ha fuso orario . Non avere il fuso orario è l'intero punto di quella classe.

Per citare il documento di quella classe:

Questa classe non memorizza o rappresenta un fuso orario. Invece, è una descrizione della data, utilizzata per i compleanni, combinata con l'ora locale come si vede su un orologio da parete. Non può rappresentare un istante sulla linea temporale senza informazioni aggiuntive come un offset o un fuso orario.

Quindi Local…significa "non suddiviso in zone, nessun offset".

Instant

inserisci qui la descrizione dell'immagine

An Instantè un momento sulla linea temporale in UTC , un conteggio di nanosecondi dall'epoca del primo momento del 1970 UTC (in pratica, vedi documento di classe per dettagli nitidi). Poiché la maggior parte della logica aziendale, dell'archiviazione e dello scambio di dati dovrebbe essere in UTC, questa è una classe utile da usare spesso.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

OffsetDateTime

inserisci qui la descrizione dell'immagine

La classe OffsetDateTimeclass rappresenta un momento come data e ora con un contesto di un numero di ore-minuti-secondi prima o dietro UTC. La quantità di offset, il numero di ore-minuti-secondi, è rappresentata dalla ZoneOffsetclasse.

Se il numero di ore-minuti-secondi è zero, un OffsetDateTimerappresenta un momento in UTC uguale a un Instant.

ZoneOffset

inserisci qui la descrizione dell'immagine

La ZoneOffsetclasse rappresenta un offset da UTC , un numero di ore-minuti-secondi avanti rispetto a UTC o dietro UTC.

A ZoneOffsetè semplicemente un numero di ore-minuti-secondi, niente di più. Una zona è molto di più, con un nome e una cronologia delle modifiche da compensare. Pertanto, è sempre preferibile utilizzare una zona rispetto a un semplice offset.

ZoneId

inserisci qui la descrizione dell'immagine

Un fuso orario è rappresentato dalla ZoneIdclasse.

Un nuovo giorno nasce prima a Parigi che a Montreal , per esempio. Quindi abbiamo bisogno di muovere le lancette dell'orologio per riflettere meglio il mezzogiorno (quando il Sole è direttamente sopra la testa) per una data regione. Quanto più a est / ovest della linea UTC in Europa occidentale / Africa tanto maggiore è l'offset.

Un fuso orario è un insieme di regole per la gestione degli aggiustamenti e delle anomalie praticate da una comunità o regione locale. L'anomalia più comune è la pazzia fin troppo popolare nota come ora legale (DST) .

Un fuso orario ha la storia delle regole passate, delle regole presenti e delle regole confermate per il prossimo futuro.

Queste regole cambiano più spesso di quanto ti aspetti. Assicurati di mantenere aggiornate le regole della tua libreria data-ora, di solito una copia del database 'tz' . Aggiornarsi è più semplice che mai in Java 8 con Oracle che rilascia uno strumento di aggiornamento del fuso orario .

Specificare un nome proprio fuso orario nel formato Continent/Region, come ad esempio America/Montreal, Africa/Casablancao Pacific/Auckland. Non usare mai il 2-4 lettera sigla come ad esempio ESTo ISTcome sono non fusi orari veri e propri, non standardizzati, e nemmeno unico (!).

Fuso orario = Offset + Regole di regolazione

ZoneId z = ZoneId.of( Africa/Tunis ) ; 

ZonedDateTime

inserisci qui la descrizione dell'immagine

Pensa ZonedDateTimeconcettualmente come Instantcon un assegnato ZoneId.

ZonedDateTime = (Instant + ZoneId)

Per catturare il momento attuale visto nell'orologio dell'orologio da parete usato dalle persone di una particolare regione (un fuso orario):

ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`. 

Quasi tutti i tuoi back-end, database, business logic, persistenza dei dati, scambio di dati dovrebbero essere tutti in UTC. Ma per la presentazione agli utenti è necessario adeguarsi al fuso orario previsto dall'utente. Questo è lo scopo della ZonedDateTimeclasse e delle classi di formattazione utilizzate per generare rappresentazioni String di quei valori data-ora.

ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ;                 // Standard ISO 8601 format.

È possibile generare testo in formato localizzato utilizzando DateTimeFormatter.

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ; 
String outputFormatted = zdt.format( f ) ;

martedì 30 aprile 2019 a 23 h 22 min 55 s heure de l'Inde

LocalDate, LocalTime,LocalDateTime

Diagramma che mostra solo un calendario per un <code> LocalDate </code>.

Diagramma che mostra solo un orologio per un <code> LocalTime </code>.

Diagramma che mostra un calendario più un orologio per un <code> LocalDateTime </code>.

Le classi a tempo data "locali", LocalDateTime, LocalDate, LocalTime, sono un diverso tipo di creatura. Non sono legati a nessuna località o fuso orario. Non sono legati alla linea temporale. Non hanno alcun significato reale fino a quando non vengono applicati a una località per trovare un punto nella sequenza temporale.

La parola "Local" in questi nomi di classe può essere controintuitiva per chi non lo sapesse. La parola significa qualsiasi località, o ogni località, ma non una località particolare.

Pertanto, per le app aziendali, i tipi "locali" non vengono spesso utilizzati in quanto rappresentano solo l'idea generale di una possibile data o ora, non di un momento specifico nella sequenza temporale. Le app aziendali tendono a preoccuparsi del momento esatto in cui è arrivata una fattura, un prodotto spedito per il trasporto, un dipendente è stato assunto o il taxi ha lasciato il garage. Quindi gli sviluppatori di app aziendali usano Instante le ZonedDateTimeclassi più comunemente.

Quindi quando dovremmo usare LocalDateTime? In tre situazioni: in cui vogliamo applicare una determinata data e ora del giorno in più località, in cui prenotiamo appuntamenti o in cui abbiamo un fuso orario previsto ma non definito. Si noti che nessuno di questi tre casi è un singolo punto specifico nella sequenza temporale, nessuno di questi è un momento.

Un'ora del giorno, più momenti

A volte vogliamo rappresentare un determinato momento del giorno in una determinata data, ma vogliamo applicarlo in più località attraverso i fusi orari.

Ad esempio, "Natale inizia a mezzanotte del 25 dicembre 2015" è un LocalDateTime. La mezzanotte colpisce in momenti diversi a Parigi rispetto a Montréal, e di nuovo diversi a Seattle e ad Auckland .

LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
LocalTime lt = LocalTime.MIN ;   // 00:00:00
LocalTime ldt = LocalDateTime.of( ld , lt ) ;  // Xmas morning anywhere. 

Un altro esempio, "Acme Company ha una politica secondo cui l'ora di pranzo inizia alle 12:30 PM in ciascuna delle sue fabbriche in tutto il mondo" è un LocalTime. Per avere un significato reale è necessario applicarlo alla cronologia per capire il momento delle 12:30 presso lo stabilimento di Stoccarda o le 12:30 presso lo stabilimento di Rabat o le 12:30 presso lo stabilimento di Sydney .

Prenotazione appuntamenti

Un'altra situazione da utilizzare LocalDateTimeè la prenotazione di eventi futuri (es: appuntamenti dal dentista). Questi appuntamenti potrebbero essere abbastanza lontani in futuro da rischiare che i politici ridefiniscano il fuso orario. I politici spesso prestano poca attenzione o addirittura nessun avvertimento. Se intendi "15:00 il prossimo 23 gennaio", indipendentemente da come i politici possano giocare con l'orologio, allora non puoi registrare un momento - ciò vedrebbe le 15:00 trasformarsi in 14:00 o 16:00 se quella regione adottasse o abbandonasse l'ora legale, per esempio.

Per gli appuntamenti, conservare a LocalDateTimee a ZoneId, conservati separatamente. Successivamente, durante la generazione di una pianificazione, determinare al volo un momento chiamando LocalDateTime::atZone( ZoneId )per generare un ZonedDateTimeoggetto.

ZonedDateTime zdt = ldt.atZone( z ) ;  // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.

Se necessario, è possibile regolare su UTC. Estrai un Instantda ZonedDateTime.

Instant instant = zdt.toInstant() ;  // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.

Zona sconosciuta

Alcune persone potrebbero utilizzare LocalDateTimein una situazione in cui il fuso orario o l'offset non sono noti.

Ritengo questo caso inappropriato e poco saggio. Se una zona o un offset sono previsti ma indeterminati, si hanno dati errati. Sarebbe come conservare un prezzo di un prodotto senza conoscere la valuta prevista. Non è una buona idea.

Tutti i tipi di data e ora

Per completezza, ecco una tabella di tutti i possibili tipi di data e ora, sia moderni che legacy in Java, oltre a quelli definiti dallo standard SQL. Questo potrebbe aiutare a collocare le classi Instant& LocalDateTimein un contesto più ampio.

Tabella di tutti i tipi di data e ora in Java (sia moderni che legacy) e SQL standard.

Notare le strane scelte fatte dal team Java nella progettazione di JDBC 4.2. Hanno scelto di supportare tutti i tempi di java.time ... ad eccezione delle due classi più comunemente usate: Instant& ZonedDateTime.

Ma non preoccuparti. Possiamo facilmente convertire avanti e indietro.

Conversione Instant.

// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject(  , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject(  , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;

Conversione ZonedDateTime.

// Storing
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject(  , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject(  , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZone( z ) ; 

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.

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

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

Puoi scambiare oggetti java.time direttamente con il tuo database. Utilizzare un driver JDBC conforme a JDBC 4.2 o successivo. Nessuna necessità di stringhe, nessuna necessità di java.sql.*classi.

Dove ottenere le classi java.time?

Tabella di quale libreria java.time utilizzare con quale versione di Java o Android

Il progetto ThreeTen-Extra estende java.time con classi aggiuntive. Questo progetto è un banco di prova per possibili aggiunte future a java.time. Si possono trovare alcune classi utili, come per esempio Interval, YearWeek, YearQuartere altro .


40
Bella risposta. Penso che un po 'di confusione (almeno la mia) derivi dalla Localdenominazione. La mia intuizione per i Localmezzi in relazione a dove sono E quando sono (?!), Che mi porta a credere che sarebbe effettivamente ciò che ZonedDateTimeè.
mkobit,

4
Sì, è confuso. Ecco perché java.time ha abilmente aggiunto la parola 'Zoned' al DateTimenome della classe usata dal suo predecessore Joda-Time (produttore ZonedDateTime), per sottolineare la differenza rispetto alle classi "Local". Pensa al nome "Locale" come a una scorciatoia per "dover essere applicato ad una particolare località".
Basil Bourque,

2
Il prefisso con la parola Localpotrebbe anche essere stato un modo per differenziarsi dal pacchetto java.util, anche se in qualche modo sento che avrebbe potuto esserci una scelta di parole migliore.
vphilipnyc,

2
@simonh Al contrario ... Quando quel nuovo dipendente firma i suoi documenti di assunzione che definiscono i loro benefici tra cui l'assicurazione sulla vita e poi che i nuovi assunti escono per un caffè solo per essere colpiti e uccisi da un camion, ci saranno molte persone come come responsabili delle risorse umane, agenti assicurativi e avvocati che vorranno conoscere il momento preciso in cui la nuova assunzione è entrata in vigore.
Basil Bourque,

2
@simonh Sì, ci sono casi in cui l'ora della data "locale" è appropriata. Oltre a quelli menzionati nella mia risposta, un altro caso comune nel mondo degli affari è che gli appuntamenti vengano presi più di un paio di mesi in futuro, abbastanza lontano da consentire ai politici di cambiare le regole del fuso orario, di solito con un piccolo preavviso. I politici apportano frequentemente queste modifiche, ad esempio modificando le date durante l'attivazione / disattivazione dell'ora legale (DST) o durante l'attivazione / disattivazione dell'ora legale in modo permanente.
Basil Bourque,

20

Una differenza principale è la Localparte di LocalDateTime. Se vivi in ​​Germania e crei LocalDateTimeun'istanza e qualcun altro vive negli Stati Uniti e crea un'altra istanza nello stesso momento (purché gli orologi siano impostati correttamente), il valore di quegli oggetti sarebbe effettivamente diverso. Questo non si applica a Instant, che viene calcolato indipendentemente dal fuso orario.

LocalDateTimememorizza la data e l'ora senza fuso orario, ma il suo valore iniziale dipende dal fuso orario. Instantnon lo è.

Inoltre, LocalDateTimefornisce metodi per manipolare componenti della data come giorni, ore, mesi. An Instantno.

a parte il vantaggio di precisione dei nanosecondi di Instant e la parte del fuso orario di LocalDateTime

Entrambe le classi hanno la stessa precisione. LocalDateTimenon memorizza il fuso orario. Leggi attentamente javadocs, perché potresti fare un grosso errore con tali presupposti non validi: Instant e LocalDateTime .


scusate per aver letto male la parte sulla zona + precisione. Ci scusiamo per la ripetizione dal precedente post: Considerando una singola applicazione di fuso orario, in quali casi d'uso preferiresti LocalDateTime o viceversa?
manuel aldana,

1
Prenderei LocalDateTime ogni volta che ho bisogno di date e / o orari. Tra ore, minuti o così. Userei Instant per misurare i tempi di esecuzione, per esempio, o memorizzare un campo interno di sth che accadeva allora e lì. Calcolo delle esecuzioni successive, come nel tuo caso? LocalDateTime sembra appropriato, ma è un'opinione. Come hai affermato, entrambi possono essere utilizzati.
Dariusz,

Puoi approfondire di più LocalDateTime stores date and time without timezone, but it's initial value is timezone dependent? qual è il valore iniziale e in che modo dipende dal fuso orario? Grazie.
Max

12

Ti sbagli LocalDateTime: non memorizza alcuna informazione sul fuso orario e ha una precisione di nanosecondi. Citando il Javadoc (sottolineatura mia):

Una data-ora senza fuso orario nel sistema di calendario ISO-8601 , come 2007-12-03T10: 15: 30.

LocalDateTime è un oggetto data-ora immutabile che rappresenta una data-ora, spesso visualizzata come anno-mese-giorno-ora-minuto-secondo. È inoltre possibile accedere ad altri campi di data e ora, come il giorno dell'anno, il giorno della settimana e la settimana dell'anno. Il tempo è rappresentato dalla precisione dei nanosecondi . Ad esempio, il valore "2 ottobre 2007 alle 13: 45.30.123456789" può essere archiviato in LocalDateTime.

La differenza tra i due è che Instantrappresenta un offset rispetto all'epoca (01-01-1970) e, come tale, rappresenta un particolare istante sulla linea del tempo. Due Instantoggetti creati nello stesso momento in due diversi luoghi della Terra avranno esattamente lo stesso valore.


Considerando una singola applicazione di fuso orario, in quali casi d'uso preferiresti LocalDateTime o viceversa?
manuel aldana,

3
@manuelaldana È più una questione di gusti. Preferirei LocalDateTime per qualsiasi cosa relativa all'utente (compleanno ...) e Instant per qualsiasi cosa relativa alla macchina (tempo di esecuzione ...).
Tunaki,

2
@manuelaldana Un'unica app per fuso orario è rara se non inesistente. Potresti cavartela ignorando i fusi orari per una piccola app che hai preparato per il tuo club musicale barocco locale. Ma non appena devi pubblicare un evento per le persone che viaggiano (e attraversano i fusi orari) vorranno che i dati siano collegati a un fuso orario in modo che la loro app di calendario possa adattarsi, se necessario. Ti suggerisco di imparare a lavorare correttamente con i fusi orari in tutte le tue app.
Basil Bourque,

@Tunaki Il tuo uso della parola 'offset' nell'ultimo paragrafo è fonte di distrazione. Quella parola ha un certo significato nel lavoro data-ora, quindi il suo utilizzo qui in questo contesto potrebbe non essere utile.
Basil Bourque,

0

Instant corrisponde al tempo sul meridiano principale (Greenwich).

Considerando che LocalDateTimerelativamente alle impostazioni del fuso orario del sistema operativo, e

non può rappresentare un istante senza informazioni aggiuntive come un offset o un fuso orario.


2
Instant è basato su UTC e non su GMT.
Torsten Ojaperv,
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.