Converti java.util.Date a che tipo “java.time”?

Ho un object java.util.Date o un object java.util.Calendar . Come posso convertirlo nel tipo giusto nel framework java.time ?

Ho sentito che ora dovremmo fare la maggior parte della nostra logica di business con i tipi java.time. Quando si lavora con il vecchio codice non ancora aggiornato per java.time, devo essere in grado di convertire avanti e indietro. Quali tipi di mappe sono java.util.Date a java.util.Date o java.util.Calendar ?

Sì, dovresti sicuramente usare il framework java.time ogni volta che è ansible.

Evita le vecchie lezioni di data-ora

Le vecchie classi di data e ora compresi java.util.Date , java.util.Calendar e java.text.SimpleTextFormat e simili hanno dimostrato di essere mal progettate, confuse e problematiche . Evitalo dove puoi. Ma quando devi interagire con questi vecchi tipi, puoi convertire tra vecchio e nuovo.

Continua a leggere per un’introduzione di base, un po ‘troppo semplificata, per orientarti nello spostamento avanti e indietro tra le vecchie e le nuove lezioni di data-ora.

java.time

Il framework java.time è definito da JSR 310 , ispirato alla libreria Joda-Time di grande successo ed esteso dal progetto ThreeTen-Extra . La maggior parte delle funzionalità è stata ritrasportata su Java 6 e 7 nel progetto ThreeTen-Backport , con un ulteriore adattamento per Android nel progetto ThreeTenABP .

Quale tipo di java.time corrisponde a java.util.Date ? Bene, un object java.util.Date rappresenta fondamentalmente un momento sulla timeline in UTC, una combinazione di data e ora del giorno. Possiamo tradurlo in uno qualsiasi dei diversi tipi in java.time. Ciascuno è discusso di seguito. Si noti che alcuni nuovi metodi sono stati aggiunti alle vecchie classi di data e ora per facilitare le conversioni.

diagramma di conversione da java.util.Date/.Calendar a ZonedDateTime (o OffsetDateTime) ai tre tipi <code/> Local … </ code>“> </p>
<h2> <code>Instant</code> </h2>
<p>  Il blocco predefinito in java.time è un <code>Instant</code> , un momento sulla timeline in UTC con una risoluzione di nanosecondi . </p>
<p>  In generale, dovresti eseguire gran parte della tua logica aziendale in UTC.  In tale lavoro, <code>Instant</code> sarà usato frequentemente.  Passa attorno agli oggetti <code>Instant</code> , applicando un fuso orario solo per la presentazione a un utente.  Quando è necessario applicare un offset o un fuso orario, utilizzare i tipi trattati di seguito. </p>
<h3>  Da <code>java.util.Date</code> a <code>Instant</code> </h3>
<p>  Dato che sia <code>Instant</code> che <code>java.util.Date</code> sono un momento nella timeline in UTC, possiamo facilmente passare da un <code>java.util.Date</code> a un <code>Instant</code> .  La vecchia class ha acquisito un nuovo metodo, <code>java.util.Date::toInstant</code> . </p>
<pre> <code>Instant instant = myUtilDate.toInstant();</code> </pre>
<p>  Puoi andare nell’altra direzione, da <code>Instant</code> a <code>java.util.Date</code> .  Ma potresti perdere informazioni sul secondo frazionario.  Un <code>Instant</code> traccia i nanosecondi , per un massimo di nove cifre dopo la virgola decimale, ad esempio <code>2016-01-23T12:34:56.123456789Z</code> .  Sia java.util.Date che .Calendar sono limitati a millisecondi , per un massimo di tre cifre dopo il decimale, ad esempio <code>2016-01-23T12:34:56.123Z</code> .  In questo esempio, passando da <code>Instant</code> a <code>Date</code> intende il troncamento del <code>456789</code> . </p>
<pre> <code>java.util.Date myUtilDate = java.util.Date.from( instant );</code> </pre>
<h3>  Da <code>java.util.Calendar</code> a <code>Instant</code> </h3>
<p>  Che dire di un <code>java.util.Calendar</code> invece di un <code>java.util.Date</code> ?  All’interno dell’object del <code>Calendar</code> , la data / ora viene tracciata come un conteggio di millisecondi dall’epoca di riferimento dell’epoca del primo momento del 1970 in UTC ( <code>1970-01-01T00:00:00.0Z</code> ).  Quindi questo valore può essere convertito facilmente in un <code>Instant</code> . </p>
<pre> <code>Instant instant = myUtilCalendar.toInstant() ;</code> </pre>
<h3>  Da <code>java.util.GregorianCalendar</code> a <code>ZonedDateTime</code> </h3>
<p>  Ancora meglio, se il tuo object <code>java.util.Calendar</code> è in realtà un <code>java.util.GregorianCalendar</code> puoi facilmente andare direttamente a <code>ZonedDateTime</code> .  Questo approccio ha il vantaggio di conservare le informazioni sul fuso orario incorporato. </p>
<p>  Downcast dall’interfaccia di <code>Calendar</code> alla class concreta di <code>GregorianCalendar</code> .  Quindi chiama il <code>toZonedDateTime</code> e <code>from</code> metodi per andare avanti e indietro. </p>
<pre> <code>if( myUtilCalendar instanceof GregorianCalendar ) { GregorianCalendar gregCal = (GregorianCalendar) myUtilCalendar; // Downcasting from the interface to the concrete class. ZonedDateTime zdt = gregCal.toZonedDateTime(); // Create `ZonedDateTime` with same time zone info found in the `GregorianCalendar` end if</code> </pre>
<p>  Andando nella direzione opposta … </p>
<pre> <code> java.util.Calendar myUtilCalendar = java.util.GregorianCalendar.from( zdt ); // Produces an instant of `GregorianCalendar` which implements `Calendar` interface.</code> </pre>
<p>  Come discusso sopra, fai attenzione che potresti <strong>perdere informazioni sulla frazione di secondo</strong> .  I nanosecondi nel tipo java.time ( <code>ZonedDateTime</code> ) vengono troncati in millisecondi nel <code>.Calendar</code> / <code>.GregorianCalendar</code> . </p>
<h1> <code>OffsetDateTime</code> </h1>
<p>  Da un <code>Instant</code> possiamo applicare un offset da UTC per spostarci in un tempo di wall-clock per alcune località.  Un offset è un numero di ore, e possibilmente minuti e secondi, prima di UTC (verso est) o dietro UTC (verso ovest).  La class <code>ZoneOffset</code> rappresenta questa idea.  Il risultato è un object <code>OffsetDateTime</code> . </p>
<pre> <code>ZoneOffset offset = ZoneOffset.of(

Puoi andare nell’altra direzione, da OffsetDateTime a java.util.Date . Estrai un Instant e poi procedi come abbiamo visto nel codice sopra. Come discusso sopra, qualsiasi nanosecondo viene troncato in millisecondi ( perdita di dati ).

 java.util.Date myUtilDate = java.util.Date.from( odt.toInstant() ); 

ZonedDateTime

Meglio ancora, applica un fuso orario completo. Un fuso orario è un offset più regole per la gestione di anomalie come l’ ora legale (DST) .

L’applicazione di ZoneId ti ZoneId ottenere un object ZonedDateTime . Utilizzare un nome di fuso orario appropriato (continente / regione). Non usare mai le abbreviazioni di 3-4 lettere comunemente viste come EST o IST quanto non sono né standardizzate né uniche.

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId ); 

Puoi andare nell’altra direzione, da ZonedDateTime a java.util.Date . Estrai un Instant e poi procedi come abbiamo visto nel codice sopra. Come discusso sopra, qualsiasi nanosecondo viene troncato in millisecondi ( perdita di dati ).

 java.util.Date myUtilDate = java.util.Date.from( zdt.toInstant() ); 

E abbiamo visto più in alto che un ZonedDateTime può essere convertito in un GregorianCalendar .

LocalDate

A volte potresti desiderare un valore solo per la data, senza orario e senza fuso orario. Per questo, usa un object java.time.LocalDate .

Vedere questa domanda per ulteriori discussioni, convertire java.util.Date in java.time.LocalDate , in particolare questa risposta scritta dall’uomo principale dietro l’invenzione di Joda-Time e java.time.

La chiave è passare attraverso ZonedDateTime (come generato nel codice sopra). Abbiamo bisogno di un fuso orario per determinare una data. La data varia in tutto il mondo, con un nuovo giorno che sorge prima nell’est. Ad esempio, dopo la mezzanotte a Parigi è un nuovo giorno mentre ancora “ieri” a Montréal. Pertanto, mentre un LocalDate non contiene un fuso orario, è necessario un fuso orario per determinare un LocalDate .

 LocalDate localDate = zdt.toLocalDate(); 

Convertire nella direzione LocalDate da LocalDate a una data-ora significa inventare un momento della giornata. Puoi scegliere qualsiasi momento del giorno che abbia senso nel tuo scenario aziendale. Per molte persone, il primo momento della giornata ha un senso. Potresti essere tentato di codificare il primo momento come l’ora 00:00:00.0 . In alcuni fusi orari, tale orario potrebbe non essere valido come primo momento a causa dell’ora legale (DST) o di altre anomalie. Quindi lascia che java.time determini l’ora corretta con una chiamata a atStartOfDay .

 ZonedDateTime zdt = localDate.atStartOfDay( zoneId ); 

LocalTime

In rare occasioni potresti volere solo un momento della giornata senza una data e senza un fuso orario. Questo concetto è rappresentato dalla class LocalTime . Come discusso sopra con LocalDate , abbiamo bisogno di un fuso orario per determinare un LocalTime anche se l’object LocalTime non contiene (non “ricorda”) quel fuso orario. Quindi, di nuovo, passiamo attraverso un object ZonedDateTime ottenuto da un Instant come visto sopra.

 LocalTime localTime = zdt.toLocalTime(); 

LocalDateTime

Come per gli altri due tipi di Local… , a LocalDateTime non sono assegnati fuso orario né offset. Come tale potresti raramente usarlo . Ti dà un’idea approssimativa di una data, ma non è un punto sulla timeline. Utilizzare questo se si intende una data generale e un po ‘di tempo che potrebbe essere applicato a un fuso orario.

Ad esempio, “Natale inizia quest’anno” sarà il 2016-12-25T00:00:00.0 . Notare la mancanza di qualsiasi offset o fuso orario in quella rappresentazione testuale di un LocalDateTime . Il Natale inizia prima a Delhi, in India, piuttosto che a Parigi, in Francia, e più tardi ancora a Montréal Québec, in Canada. Applicare il fuso orario di ognuna di queste aree produrrebbe un momento diverso sulla timeline.

 LocalDateTime ldt = zdt.toLocalDateTime();