Cosa c'è di sbagliato in Java Date & Time API? [chiuso]


105

Molto spesso mi imbatto in feedback negativi su Java Datee altre classi relative alla data e all'ora. Essendo uno sviluppatore .NET, non posso capire completamente (senza averli usati) cosa c'è di sbagliato in loro.

Qualcuno può fare luce su questo?


Risposte:


142

Ah, la Dateclasse Java . Forse uno dei migliori esempi di come non fare qualcosa in nessuna lingua, ovunque. Da dove comincio?

La lettura del JavaDoc potrebbe far pensare che gli sviluppatori abbiano effettivamente delle buone idee. Continua a lungo sulla differenza tra UTC e GMT , nonostante il fatto che la differenza tra i due sia fondamentalmente intercalare i secondi (cosa che accade piuttosto raramente ).

Tuttavia, le decisioni di progettazione gettano davvero sprecare ogni pensiero di essere un'API ben progettata. Ecco alcuni degli errori preferiti:

  • Nonostante sia stato progettato nell'ultimo decennio del millennio, valuta gli anni come due cifre dal 1900. Ci sono letteralmente milioni di soluzioni alternative che fanno 1900+ (o 1900) nel mondo Java come risultato di questa banale decisione.
  • I mesi sono indicizzati a zero, per soddisfare il caso straordinariamente insolito di avere un array di mesi e non vivere con un array di tredici elementi, il primo dei quali contenente a null. Di conseguenza, abbiamo 0..11 (e oggi è il mese 11 dell'anno 109). Ci sono un numero simile di ++ e - nei mesi per convertire in una stringa.
  • Sono mutevoli . Di conseguenza, ogni volta che vuoi restituire una data (ad esempio, come struttura di istanza) devi restituire un clone di quella data invece dell'oggetto data stesso (poiché altrimenti, le persone possono modificare la tua struttura).
  • Il Calendar, progettato per 'riparare' questo, in realtà fa gli stessi errori. Sono ancora mutevoli.
  • Daterappresenta a DateTime, ma per rimandare a quelli in SQL land, c'è un'altra sottoclasse java.sql.Date, che rappresenta un singolo giorno (sebbene senza un fuso orario ad esso associato).
  • Non ci sono messaggi di posta TimeZoneelettronica associati a Date, quindi gli intervalli (come un "giorno intero") sono spesso rappresentati come mezzanotte-mezzanotte (spesso in un fuso orario arbitrario)

Infine, vale la pena notare che i secondi intercalari generalmente si correggono da soli contro un buon orologio di sistema che viene aggiornato con ntp entro un'ora (vedere i collegamenti di seguito). La possibilità che un sistema sia ancora attivo e funzionante nell'introduzione di due secondi intercalari (ogni sei mesi minimo, praticamente ogni pochi anni) è piuttosto improbabile, soprattutto considerando il fatto che devi ridistribuire nuove versioni del tuo codice di tanto in tanto . Anche l'uso di un linguaggio dinamico che rigenera le classi o qualcosa come un motore WAR inquinerà lo spazio della classe e alla fine si esaurirà il permgen.


43

JSR 310 , che ha soppiantato le vecchie classi data-ora con java.time in Java 8, si giustifica nel JSR originale come segue:

2.5 Quale esigenza della comunità Java sarà affrontata dalla specifica proposta?

Attualmente Java SE ha due API separate per data e ora: java.util.Date e java.util.Calendar. Entrambe le API sono costantemente descritte come difficili da usare dagli sviluppatori Java su weblog e forum. In particolare, entrambi utilizzano un indice zero per mesi, che è causa di molti bug. Calendar ha anche sofferto di molti bug e problemi di prestazioni nel corso degli anni, principalmente a causa della memorizzazione interna del suo stato in due modi diversi.

Un bug classico (4639407) impediva la creazione di determinate date in un oggetto Calendar. Si potrebbe scrivere una sequenza di codice che crei una data in alcuni anni ma non in altri, avendo l'effetto di impedire ad alcuni utenti di inserire le loro date di nascita corrette. Ciò è stato causato dalla classe Calendar che consente solo un guadagno dell'ora legale di un'ora in estate, quando storicamente era più 2 ore nel periodo della seconda guerra mondiale. Anche se questo bug è stato ora risolto, se in futuro un paese scegliesse di introdurre un aumento dell'ora legale di più tre ore in estate, la classe Calendar verrebbe nuovamente interrotta.

L'attuale API Java SE soffre anche in ambienti multi-thread. Le classi immutabili sono note per essere intrinsecamente thread-safe poiché il loro stato non può cambiare. Tuttavia, sia la data che il calendario sono modificabili, il che richiede ai programmatori di considerare esplicitamente la clonazione e il threading. Inoltre, la mancanza di thread-safety in DateTimeFormat non è ampiamente nota ed è stata la causa di molti problemi di threading difficili da rintracciare.

Oltre ai problemi con le classi che Java SE ha per datetime, non ha classi per modellare altri concetti. Le date o le ore senza fuso orario, le durate, i periodi e gli intervalli non hanno alcuna rappresentazione di classe in Java SE. Di conseguenza, gli sviluppatori usano spesso un int per rappresentare una durata di tempo, con javadoc che specifica l'unità.

La mancanza di un modello completo di data e ora fa sì che molte operazioni comuni siano più complicate di quanto dovrebbero essere. Ad esempio, il calcolo del numero di giorni tra due date è attualmente un problema particolarmente difficile.

Questo JSR affronterà il problema di un modello completo di data e ora, comprese date e ore (con e senza fusi orari), durate e periodi di tempo, intervalli, formattazione e analisi.


28
  • Data casi sono mutabili , che è quasi sempre scomodo.
  • Hanno una doppia natura. Rappresentano sia un timestamp che una data di calendario. Si scopre che questo è problematico quando si eseguono calcoli sulle date.
  • Le rappresentazioni numeriche dei dati del calendario sono in molti casi controintuitive. Ad esempio: getMonth()è a base zero, getYear()è a base 1900 (ovvero, l'anno 2009 è rappresentato come 109).
  • Mancano molte funzionalità che ti aspetti da una Dateclasse.

13

Mi sento per te ... come ex programmatore .NET, ho fatto le stesse domande, l'API time in .NET (timespans, sovraccarico di operatori) è molto conveniente.

Innanzitutto, per creare una data specifica, utilizzi un'API obsoleta oppure:

Calendar c = Calendar.getInstance();
c.set(2000, 31, 12)

Per sottrarre un giorno fai cose cattive come

Date firstDate = ...
Calendar c = Calendar.getInstance();
c.setTime(fistDate);
c.add(Calendar.DATE,-1);
Date dayAgo = c.getTime();

o peggio

Date d = new Date();
Date d2 = new Date(d.getTime() - 1000*60*60*24);

Per scoprire quanto tempo è passato tra due date (in giorni / settimane / mesi) ... diventa ancora peggio

Tuttavia DateUtils di apache ( org.apache.commons.lang.time.DateUtils) offre alcuni metodi convenienti e ultimamente mi sono ritrovato a usarli solo

Come ha scritto Brabster, Joda Time è anche una buona libreria esterna, ma apache sembra più "comune" di ogni altra cosa ...


Per favore, per favore, mostraci come fare ("scopri quanto tempo è passato tra due date")!
Anton Gogolev

Vorrei conoscere un modo semplice ... inclusi anni bisestili, mesi nervosi e giorni volatili ...
Eran Medan

1
Vedi anche org.apache.commons.lang.time: commons.apache.org/lang//api/org/apache/commons/lang/time/…
trashgod

@AntonGogolev In java.time , utilizzare Periode Durationclasses per calcolare e rappresentare il tempo trascorso su una scala rispettivamente di anni-mesi-giorni e ore-minuti-secondi.
Basil Bourque

4

Trovo utilizzabile l'API Date di Java, ad essere onesti. La maggior parte dei problemi che ho visto e sentito parlare riguardano il livello di dettaglio, la necessità di coinvolgere più classi di fare qualcosa di utile ( Calendar, Date, DateFormat/ SimpleDateFormat) e la mancanza di funzioni di accesso semplici come getDayOfWeek().

Joda Time è un'API alternativa molto rispettata in Java e nella sezione Perché Joda Time fornisce alcuni ulteriori argomenti sul motivo per cui è un'alternativa praticabile che potrebbe essere di interesse.

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.