Java Date vs Calendar


364

Qualcuno potrebbe consigliare l'attuale "best practice" in giro Datee Calendartipi.

Quando si scrive nuovo codice, è meglio favorire sempre Calendarsopra Date, o ci sono circostanze in cui Dateè il tipo di dati più appropriato?



2
Cordiali saluti, le classi data-ora vecchi problematici, come java.util.Date, java.util.Calendare java.text.SimpleDateFormatora sono l'eredità, soppiantato dai java.time classi. Gran parte della funzionalità java.time è trasferita su Java 6 e Java 7 nel progetto ThreeTen-Backport . Adattato ulteriormente per Android precedente nel progetto ThreeTenABP . Vedi Come usare ThreeTenABP… .
Basil Bourque,

2
Cordiali saluti, il progetto Joda-Time (menzionato in un altro commento) è ora in modalità di manutenzione , con il team che consiglia la migrazione alle classi java.time . Vedi Tutorial di Oracle .
Basil Bourque,

Risposte:


377

La data è una classe più semplice ed è principalmente presente per motivi di compatibilità con le versioni precedenti. Se è necessario impostare date particolari o eseguire l'aritmetica della data, utilizzare un calendario. I calendari gestiscono anche la localizzazione. Le precedenti funzioni di manipolazione della data di Date sono state successivamente deprecate.

Personalmente tendo a usare il tempo in millisecondi come lungo (o lungo, a seconda dei casi) o il calendario quando c'è una scelta.

Sia la data che il calendario sono mutabili, il che tende a presentare problemi quando si utilizza una delle API.


5
Cordiali saluti, le vecchie classi data-ora terribilmente fastidiose come java.util.Date, java.util.Calendare java.text.SimpleDateFormatora sono legacy , soppiantate dalle classi java.time integrate in Java 8 e versioni successive. Vedi Tutorial di Oracle .
Basil Bourque,

67

Il modo migliore per il nuovo codice (se la tua politica consente il codice di terze parti) è utilizzare la libreria Joda Time .

Sia la data che il calendario presentano così tanti problemi di progettazione che non sono nemmeno buone soluzioni per il nuovo codice.


7
Secondo il suggerimento di usare il tempo joda. È più facile da usare e da capire e offre molte più funzionalità che puoi usare.
Jeroen van Bergen,

30
Per la discussione sull'opportunità di utilizzare Joda Time o bastone con le classi JDK standard, vedere stackoverflow.com/questions/589870/...
Jonik

3
Non so se merita i voti negativi, ma non risponde alla domanda. Potrebbe essere meglio come commento.
IcedDante,

7
Perché la domanda riguardava l'uso di Data e Calendario e non l'uso di una libreria di terze parti che aggiunge un rischio di dipendenza di un singolo fornitore a un progetto.
Archimede Trajano,

3
Questo era il "modo migliore" fino a quando il pacchetto java.time non è stato reso disponibile con Java 8.
DaBlick

58
  • Datee Calendarsono davvero lo stesso concetto fondamentale (entrambi rappresentano un istante nel tempo e sono avvolgenti attorno a un longvalore sottostante ).

  • Si potrebbe sostenere che in Calendarrealtà è ancora più rotto di quanto non loDate sia, poiché sembra offrire fatti concreti su cose come il giorno della settimana e l'ora del giorno, mentre se si cambia la sua timeZoneproprietà, il calcestruzzo si trasforma in blancmange! Nessuno dei due oggetti è davvero utile come archivio di anno-mese-giorno o ora del giorno per questo motivo.

  • Utilizzare Calendarsolo come una calcolatrice che, quando fornita Datee TimeZoneoggetti, eseguirà calcoli per te. Evitare il suo utilizzo per la digitazione di proprietà in un'applicazione.

  • Utilizzare SimpleDateFormatinsieme TimeZonee Dateper generare stringhe di visualizzazione.

  • Se ti senti avventuroso, usa Joda-Time, sebbene sia IMHO inutilmente complicato e sarà presto sostituito dall'API di data JSR-310 in ogni caso.

  • In precedenza ho risposto che non è difficile pubblicare la tua YearMonthDayclasse, che utilizza Calendarsotto il cofano per i calcoli della data. Sono stato sottoposto a downgrade per il suggerimento, ma credo ancora che sia valido perché Joda-Time (e JSR-310 ) sono davvero così complicati per la maggior parte dei casi d'uso.


1
C'è un lasso di tempo per JSR310? Sarebbe stato in Java 7, ma credo che ora non sia il caso.
Brian Agnew,

@Brian - Di certo è andato molto tranquillo in quella mailing list!
oxbow_lakes,

Solo controllando, è diventato inattivo, il che significa che non hanno pubblicato una bozza del traguardo in 18 mesi :-(
Brian Agnew,

Il commento più recente sulla mailing list è di luglio e di Stephen, quindi il progetto probabilmente sta ancora andando
avanti

Concordato. Se sai come utilizzare Date in modo sicuro come oggetto immutabile e Calendar per manipolare le Date, la maggior parte delle persone dovrebbe essere al sicuro. Prestare attenzione quando si utilizza SimpleDateFormat nel codice multithread.
cwash

25

La data è la migliore per la memorizzazione di un oggetto data. È quello persistente, quello serializzato ...

Calendar è il migliore per manipolare le date.

Nota: a volte preferiamo anche java.lang.Long over Date, perché Date è mutevole e quindi non sicuro per i thread. Su un oggetto Date, utilizzare setTime () e getTime () per alternare tra i due. Ad esempio, una data costante nell'applicazione (esempi: zero 1970/01/01 o un END_OF_TIME applicativo impostato su 2099/12/31; quelli sono molto utili per sostituire i valori null come ora di inizio e ora di fine, in particolare quando li persistete nel database, dato che SQL è così peculiare con i null).


java.lang.Long
Suppongo

17

In genere utilizzo Date, se possibile. Sebbene sia mutabile, i mutatori sono in realtà deprecati. Alla fine si avvolge sostanzialmente un lungo che rappresenterebbe la data / ora. Al contrario, utilizzerei i calendari se dovessi manipolare i valori.

Puoi pensarlo in questo modo: usi StringBuffer solo quando hai bisogno di stringhe che puoi facilmente manipolare e poi convertirle in stringhe usando il metodo toString (). Allo stesso modo, uso Calendar solo se devo manipolare i dati temporali.

Per la migliore pratica, tendo a utilizzare oggetti immutabili il più possibile al di fuori del modello di dominio . Riduce significativamente le possibilità di effetti collaterali ed è fatto per te dal compilatore, piuttosto che un test JUnit. Usi questa tecnica creando campi finali privati nella tua classe.

E tornando all'analogia StringBuffer. Ecco un codice che mostra come convertire tra Calendario e Data

String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String

// immutable date with hard coded format.  If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date =     new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");

// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);

// mutate the value
cal.add(Calendar.YEAR, 1);

// convert back to Date
Date newDate = cal.getTime();

// 
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);

Sì, gli oggetti immutabili hanno senso per il lavoro data-ora. Le classi java.time che hanno soppiantato Date/ Calendarutilizzato il modello di oggetti immutabili.
Basil Bourque,

Questo potrebbe essere vero ma non nel 2010.
Archimede Trajano,

Sì. Ma ci sono migliaia di persone che leggono questa pagina ora , oltre 150.000 finora. Il mio commento è una nota per loro, non una critica per te.
Basil Bourque,

Lo so, ecco perché ho votato a fondo l'altra risposta. Tuttavia, ci sono ancora alcune persone che hanno bisogno di soffrire con i JDK più vecchi che hanno bisogno della risposta sopra.
Archimede Trajano,

1
In realtà, per Java 6 e 7, abbiamo il progetto ThreeTen-Backport . Questo porta la maggior parte delle funzionalità java.time praticamente con la stessa API. Quindi non c'è mai bisogno di usare quelle terribili lezioni di data e ora.
Basil Bourque,

15

Dates dovrebbero essere usati come punti immutabili nel tempo; Calendarsono mutabili e possono essere passati in giro e modificati se è necessario collaborare con altre classi per trovare una data finale. Considerali analoghi a Stringe StringBuildercapirai come ritengo che dovrebbero essere usati.

(E sì, so che Date non è in realtà tecnicamente immutabile, ma l'intenzione è che non dovrebbe essere mutabile, e se nulla chiama i metodi deprecati allora è così.)


Sì, gli oggetti immutabili hanno senso per il lavoro data-ora. Le classi java.time che hanno soppiantato Date/ Calendarutilizzato il modello di oggetti immutabili. In particolare, Instantsostituisce java.util.Datee ZonedDateTimesostituisce Calendar/ GregorianCalendar.
Basil Bourque,

15

tl; dr

consigliare l'attuale "best practice" in giro DateeCalendar

E 'meglio per favorire sempre Calendarpiù diDate

Evita del tutto queste classi legacy . Utilizzare invece le classi java.time .

  • Per un momento in UTC , utilizzare (l'equivalente moderno di )Instant
    Date
  • Per un momento in un determinato fuso orario , utilizzare (l'equivalente moderno di )ZonedDateTime
    GregorianCalendar
  • Per un momento in un particolare offset da UTC , utilizzare (nessun equivalente nelle classi legacy)OffsetDateTime
  • Per una data-ora (non un momento) con fuso orario o offset sconosciuti, utilizzare (nessun equivalente nelle classi legacy)LocalDateTime

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

Dettagli

La risposta da Ortomala Lokni è giusto suggerire utilizzando le moderne java.time classi, piuttosto che le classi legacy data-ora vecchi fastidiosi ( Date, Calendar, ecc). Ma quella risposta suggerisce la classe sbagliata come equivalente (vedi il mio commento su quella risposta).

Utilizzando java.time

Le classi java.time rappresentano un notevole miglioramento rispetto alle classi di data e ora legacy, differenza diurna e giornaliera. Le vecchie classi sono mal progettate, confuse e problematiche. Dovresti evitare le vecchie lezioni quando possibile. Ma quando è necessario convertire in / dal vecchio / nuovo, è possibile farlo chiamando nuovi metodi da aggiungere alle vecchie classi.

Per ulteriori informazioni sulla conversione, vedere la mia risposta e il diagramma elegante in un'altra domanda, Converti java.util.Data in quale tipo di "java.time"? .

La ricerca di Stack Overflow offre molte centinaia di esempi di domande e risposte sull'uso di java.time. Ma ecco una breve sinossi.

Instant

Ottieni il momento attuale con un Instant. La Instantclasse rappresenta un momento sulla linea temporale in UTC con una risoluzione di nanosecondi (fino a nove (9) cifre di una frazione decimale).

Instant instant = Instant.now();

ZonedDateTime

Per vedere lo stesso momento simultaneo attraverso l'obiettivo dell'ora dell'orologio a parete di una particolare regione , applica un fuso orario ( ZoneId) per ottenere un ZonedDateTime.

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 3-4 lettera sigla come ad esempio ESTo ISTcome sono non fusi orari veri e propri, non standardizzati, e nemmeno unico (!).

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

Compensare

Un fuso orario è la cronologia delle modifiche di una regione nel suo offset da UTC . Ma a volte ti viene dato solo un offset senza la zona intera. In tal caso, utilizzare la OffsetDateTimeclasse.

ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );

L'uso di un fuso orario è preferibile all'uso di un semplice offset.

LocalDateTime

Il "Locale" nelle Local…classi indica qualsiasi località, non una località particolare. Quindi il nome può essere contro-intuitivo.

LocalDateTime, LocalDatee LocalTimeintenzionalmente privo di informazioni su offset o fuso orario. Quindi essi non rappresentano momenti attuali, sono senza punti sulla timeline. In caso di dubbi o confusione, utilizzare ZonedDateTimeanziché LocalDateTime. Cerca Stack Overflow per ulteriori discussioni.

stringhe

Non confondere gli oggetti data-ora con stringhe che rappresentano il loro valore. È possibile analizzare una stringa per ottenere un oggetto data-ora e generare una stringa da un oggetto data-ora. Ma la stringa non è mai la data-ora stessa.

Informazioni sui formati ISO 8601 standard , utilizzati per impostazione predefinita nelle classi java.time.


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 .

Utilizzando un driver JDBC conforme a JDBC 4.2 o successivo, è possibile scambiare oggetti java.time direttamente con il database. Non sono necessarie stringhe né classi java.sql. *.

Dove ottenere le classi java.time?

  • Java SE 8 , Java SE 9 e versioni successive
    • Built-in.
    • Parte dell'API Java standard con un'implementazione in bundle.
    • Java 9 aggiunge alcune funzionalità e correzioni minori.
  • Java SE 6 e Java SE 7
    • Gran parte della funzionalità java.time è trasferita su Java 6 e 7 in ThreeTen-Backport .
  • androide
    • Versioni successive di implementazioni di bundle Android delle classi java.time.
    • Per precedenza Android, il ThreeTenABP progetto si adatta ThreeTen-Backport (di cui sopra). Vedi Come usare ThreeTenABP… .

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 .


10

Con Java 8, è necessario utilizzare il nuovo pacchetto java.time .

Gli oggetti sono immutabili, vengono presi in considerazione i fusi orari e l'ora legale.

Puoi creare un ZonedDateTimeoggetto da un vecchio java.util.Dateoggetto come questo:

    Date date = new Date();
    ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());

Buono a suggerire le classi java.time. Ma male da suggerire LocalDateTime. Quella classe perde intenzionalmente qualsiasi informazione su offset-da-UTC e fuso orario. Quindi quella classe non è equivalente come Datein UTC e Calendarha un fuso orario assegnato. Vedi la mia risposta e il diagramma elegante in un'altra domanda, Converti java.util.Date in quale tipo di "java.time"? .
Basil Bourque,

9

Sostengo sempre il tempo di Joda . Ecco perché.

  1. l'API è coerente e intuitiva. A differenza delle API java.util.Date/Calendar
  2. non soffre di problemi di threading, a differenza di java.text.SimpleDateFormat ecc. (ho visto numerosi problemi del client relativi al non rendersi conto che la formattazione di data / ora standard non è thread-safe)
  3. è la base delle nuove API di data / ora di Java ( JSR310 , pianificato per Java 8. Quindi utilizzerai API che diventeranno API Java di base.

EDIT: le classi data / ora Java introdotte con Java 8 sono ora la soluzione preferita, se è possibile migrare a Java 8


3
L'ultima volta che ho guardato, JODA e JSR-310 sembravano molto diversi, anche se entrambi sono stati scritti da Stephen Colebourne. Detto questo, JODA ti introdurrebbe alla complessità dei problemi di data e ora che anche JSR-310 risolve
oxbow_lakes,

2
Perché la domanda riguardava l'uso di Data e Calendario e non l'uso di una libreria di terze parti che aggiunge un rischio di dipendenza di un singolo fornitore a un progetto.
Archimede Trajano,

2
Ritengo che la migliore pratica sia semplicemente quella di non usare quelle lezioni
Brian Agnew,

3
Dati i problemi noti con le classi java.util.Date e Calendar, suggerire Joda-Time (o JSR 310) mi sembra appropriato e responsabile. Non stiamo parlando di una questione di gusti o di stile estetico. Se qualcuno mi chiedesse se dovevano prendere la macchina rossa o la macchina d'argento, e sapevo che la macchina rossa aveva una gomma a terra e la macchina d'argento aveva un radiatore rotto, dovrei scegliere una macchina o dovrei suggerire di chiamare un taxi? La risposta a questa domanda dovrebbe sembrare ovvia al giorno d'oggi poiché anche Sun / Oracle hanno deciso di lasciarsi alle spalle quei tossicodipendenti e acquistare una nuova auto: JSR 310: API Data e ora.
Basil Bourque,

1
Cordiali saluti, il progetto Joda-Time è ora in modalità di manutenzione , che consiglia la migrazione alle classi java.time . Vedi Tutorial di Oracle .
Basil Bourque,

8

Un po 'tardi alla festa, ma Java ha una nuova API Date Time in JDK 8. Potresti voler aggiornare la tua versione JDK e abbracciare lo standard. Niente più data / calendario disordinato, niente più vasetti di terze parti.


1

La data dovrebbe essere ri-sviluppata. Invece di essere un interger lungo, dovrebbe contenere anno, mese, data, ora, minuto, secondo, come campi separati. Potrebbe anche essere utile memorizzare il calendario e il fuso orario a cui è associata questa data.

Nella nostra conversazione naturale, se fissiamo un appuntamento al 1 novembre 2013 alle 13:00 ora di New York, questo è un DateTime. NON è un calendario. Quindi dovremmo essere in grado di conversare in questo modo anche in Java.

Quando la Data viene memorizzata come un intero lungo (di secondi in mili dal 1 ° gennaio 1970 o qualcosa del genere), il calcolo della data corrente dipende dal calendario. Calendari diversi daranno data diversa. Questo è dalla prospettiva di dare un tempo assoluto (es. 1 trilione di secondi dopo il Big Bang). Ma spesso abbiamo anche bisogno di un modo conveniente di conversazione, come un oggetto che incapsula anno, mese ecc.

Mi chiedo se ci siano nuovi progressi in Java per conciliare questi 2 obiettivi. Forse la mia conoscenza di Java è troppo vecchia.


Il fatto che sia possibile memorizzare lo stesso istante nel tempo, ma riportare diverse ore / minuti / giorno / settimana / anno / foo in base a diversi sistemi di calendario, è un punto di forza, non di debolezza. Riflette la realtà (complessa).
Lanciato il

In effetti, Dateè stato ri-sviluppato; sostituito dalla java.time.Instantclasse. E Calendar/ è GregorianCalendarstato sostituito dalla java.time.ZonedDateTimeclasse.
Basil Bourque,


0

Uso Calendar quando ho bisogno di alcune operazioni specifiche durante le date come spostarmi nel tempo, ma Data lo trovo utile quando devi formattare la data per adattare le tue esigenze, recentemente ho scoperto che Locale ha molte operazioni e metodi utili. Sto usando Locale adesso!


Cordiali saluti, il fastidioso Calendare le Dateclassi sono state soppiantate anni fa dalle classi java.time . Non c'è bisogno di usare mai Dateo Calendar. E Localenon ha nulla a che fare con il significato degli oggetti data-ora. A Localeviene utilizzato solo per specificare il linguaggio umano e le norme culturali da utilizzare nella localizzazione durante la generazione di testo per rappresentare il valore di un oggetto data-ora.
Basil Bourque,
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.