Perché alle classi java.time di Java 8 manca un metodo getMillis ()?


64

Java 8 ha una libreria completamente nuova per le date e gli orari nel pacchetto java.time, il che è molto gradito a chiunque abbia dovuto usare JodaTime prima o seccarsi nel creare i propri metodi di supporto per l'elaborazione delle date. Molte classi in questo pacchetto rappresentano timestamp e hanno metodi di supporto come getHour()ottenere ore da timestamp, getMinute()ottenere minuti da timestamp, getNano()ottenere nanos da timestamp ecc ...

Ho notato che non hanno un metodo chiamato getMillis()per ottenere i millesimi di time stamp. Invece si dovrebbe chiamare il metodo get(ChronoField.MILLI_OF_SECOND). A me sembra un'incoerenza nella biblioteca. Qualcuno sa perché manca un tale metodo, o poiché Java 8 è ancora in fase di sviluppo c'è la possibilità che verrà aggiunto in seguito?

https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

Le classi qui definite rappresentano i principali concetti data-ora, inclusi istanti, durate, date, orari, fusi orari e periodi. Si basano sul sistema del calendario ISO, che è di fatto il calendario mondiale che segue le proletiche regole gregoriane. Tutte le classi sono immutabili e thread-safe.

Ogni istanza di data e ora è composta da campi resi disponibili dalle API. Per un accesso di livello inferiore ai campi fare riferimento al java.time.temporalpacchetto. Ogni classe include il supporto per la stampa e l'analisi di tutti i tipi di date e orari. Fare riferimento al java.time.formatpacchetto per le opzioni di personalizzazione ...

Esempio di questo tipo di classe:
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html

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 vista 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 memorizzato in un LocalDateTime...


Sembra che volessero usare il polimorfismo per risolvere un mucchio di metodi tutti chiamati get(), piuttosto che dare loro nomi individuali e univoci. Se ti dà fastidio, scrivi una classe che eredita la classe originale e inserisci il tuo getMillis()metodo nella nuova classe.
Robert Harvey,

@RobertHarvey La maggior parte delle classi nel pacchetto java.time sono immutabili e non possono essere estese.
Assylias,

2
@RobertHarvey La domanda per me non è come posso risolverlo. Ha appena creato una strana incoerenza e mi chiedevo se ci fosse una spiegazione interessante per questo.
Tarmo,

Ho l'idea che alcune architetture / sistemi operativi non supportano in modo affidabile millisecondi. In altre parole, il tempo di sistema non può essere recuperato al millisecondo, solo al centesimo o al decisecondo.
Marco,

Vedi stackoverflow.com/a/23945792/40064 su come farlo tramite la Instantclasse
Wim Deblauwe

Risposte:


63

JSR-310 si basa su nanosecondi, non millisecondi. Pertanto, l'insieme minimo di metodi sensibili si basa su ora, minuti, secondi e nanosecondi. La decisione di avere una base di nanosecondi è stata una delle decisioni originali del progetto e una che credo fermamente sia corretta.

L'aggiunta di un metodo per il millis sovrapposizione a quello del nanosecondo è un modo non ovvio. Gli utenti dovrebbero pensare se il campo nano fosse nano-di-secondo o nano-di-milli per esempio. L'aggiunta di un metodo aggiuntivo confuso non è auspicabile, quindi il metodo è stato omesso. Come sottolineato, l'alternativa get(MILLI_OF_SECOND)è disponibile.

FWIW, mi oppongo all'aggiunta del getMillis()metodo in futuro.


1
Ho ottenuto delle risposte molto valide a questa domanda, ma la tua risposta è la mia preferita in quanto è breve e tuttavia fa ancora un ottimo punto e mi convince davvero sulla necessità di questo approccio. Grazie.
Tarmo,

12
@ s3ib se controlli il profilo del risponditore , noterai anche che è un responsabile delle specifiche proprio per l'API di cui stai chiedendo. Questo rende una risposta tanto autorevole quanto non lo fa :)
moscerino

Quindi dover fare instant.getEpochSecond * 1000 + instant.getNano / 1000000è ragionevole boilerplate per poter comunicare con legacy (a questo punto, tutte) API Java, Javascript, ecc.?
nilskp,

10
no, in quel caso puoi semplicemente usare instant.toEpochMilli () download.java.net/jdk8/docs/api/java/time/…
JodaStephen

20

Prima di far parte di openJDK, Threeten era su Github e prima ancora su Sourceforge. All'epoca Stephen Colebourne, che è un responsabile delle specifiche su jsr-310, ha realizzato un sondaggio che è ancora possibile trovare sul sito di sourceforge .

The fourth question on the survey covered the method names for LocalTime:
1) getHourOfDay(), getMinuteOfHour(), getSecondOfMinute(), getNanoOfSecond()
2) getHour(), getMinute(), getSecond(), getNanoOfSecond()
3) getHour(), getMinute(), getSecond(), getNano()
4) another idea

solo il 6,23% ha scelto la risposta n. 4 e tra questi circa il 15% ha chiesto a getMillis(), ovvero meno dell'1% dei voti totali.

Questo è probabilmente il motivo per cui non ce getMillisn'era in primo luogo e non sono riuscito a trovare nulla di simile nella mailing list di openjdk, quindi apparentemente la questione non è stata discussa in seguito.


3
Penso che dare alle persone diverse scelte sia più probabile che scelgano una di quelle scelte, anche se la loro scelta ideale è sotto "altra". Potrei sbagliarmi però.
Allon Guralnek,

2
@AllonGuralnek Sì, sicuramente - tuttavia il componente in millisecondi era importante nell'API Date perché tutto era basato su un numero di millis dall'epoca. Nella nuova API è meno rilevante l'IMO. Nella maggior parte dei casi d'uso, è necessaria una seconda precisione o la migliore precisione disponibile (nanos). Potrei sbagliarmi.
Assylias,

1
Questo sembra chiedere informazioni sulla denominazione dei metodi, non sui metodi che dovrebbero esistere.
svick,

1
Giusto, scusa, non ero chiaro: intendevo la domanda del sondaggio, che non cercava direttamente correlata a questa domanda.
svick

15

Le classi che rappresentano i tempi UTC non ambigui (quelli sono Instant, OffsetDateTime, ZonedDateTime) hanno due metodi di supporto per accedere all'offset assoluto dall'epoca Java, vale a dire ciò che si chiama 'millisecond time' in java.util.Date, che è possibile utilizzare per arrivare a millisecondi

long getEpochSecond()
int getNano()

1000L*getEpochSecond() + getNano() / 1000000L;

Alcuni motivi per cui questo è stato scelto invece di long getEpochMillis()sono stati discussi nella mailing list jsr 310 , alcuni dei quali ho estratto per comodità:

sembra ragionevole supporre che la precisione in millisecondi non sia sufficiente. Tuttavia, qualsiasi cosa superiore alla precisione dei nanosecondi sembra eccessiva

...

Per implementare questo, la mia opzione preferita sarebbe 64 secondi lunghi (con segno) + 32 bit int nanosecondi (senza segno).

...

Preferisco che la divisione sia al secondo livello in quanto questa è l'unità di tempo ufficiale della scienza nella scienza, e lo standard più universalmente concordato.

La divisione a livello di giorni è problematica per gli istanti in quanto non gestisce i secondi bisestili. Dividere a livello di millisecondi, pur integrandosi leggermente meglio con il resto di Java, sembra davvero piuttosto strano. Inoltre perde nell'intervallo supportato.

La divisione al secondo, come proposto, offre una gamma di istanti di nanosecondi oltre 290 miliardi di anni. Mentre nessuno dovrebbe mai usare quella precisione su quell'intervallo di tempo, suggerirei che è più facile supportarlo che bloccarlo. La suddivisione a livello di giorni è problematica per gli istanti in quanto non gestisce i secondi bisestili

Ho la sensazione che un altro motivo sia stato quello di rendere intenzionalmente difficile la conversione da java.util.Date alle classi JSR310, sperando che gli sviluppatori avrebbero cercato di capire le differenze tra le varie opzioni e non solo di usare ciecamente (mis) le nuove classi.

Per quanto riguarda il motivo per cui la LocalDateTimeclasse non ha questi metodi - non possono probabilmente esistere lì perché LocalDateTimenon è legata alla linea temporale UTC fino a quando non decidi in quale zona ti trovi o quale sia il tuo offset UTC, a quel punto hai un OffsetDateTimeo ZonedDateTime(entrambi i quali hanno i metodi necessari).

In alternativa, puoi definire la tua LOCAL_EPOCHcostante 1970-01-01T00:00:00e quindi fare una MILLIS.between(LOCAL_EPOCH, localTime)per ottenere una sorta di durata in millisecondi. Questo valore, tuttavia, non sarà compatibile con alcun valore restituito da System.currentTimeMilliseconds()o java.util.Date.getTime(), a meno che ovviamente non si definisca l'ora locale come ora UTC; ma in questo caso potresti anche usare Instant direttamente o OffsetDateTime con ZoneOffset.UTC.


4
" probabilmente non possono esistere lì perché LocalDateTime non è legato alla linea temporale UTC " => un LocalDateTime potrebbe sicuramente avere un getMillismetodo che sostanzialmente ritornerebbe getNanos()/1e6- il fatto che non sia un istante nel tempo non gli impedisce di avere un millisecondo componente.
Assylias,

2
" Ho la sensazione che un altro motivo sia stato quello di rendere intenzionalmente difficile la conversione da java.util.Date alle classi JSR310 " Probabilmente vero, ma sfortunatamente "millis dall'epoca" è diventata una rappresentazione quasi universale del tempo, quindi per tutto ciò che ha bisogno per comunicare con le vecchie API Java, Javascript, nient'altro, questa omissione è una vera seccatura.
nilskp,

Lo snippet di codice nella parte superiore non è corretto - devi moltiplicare getEpochSecond per 1000.
Tin Man

@nilskp Sono due cose diverse. La domanda è: getMillis()come in getMillis-of-second; stai parlando di "millis dall'epoca". Il primo è assente come spiegato nella risposta accettata. Quest'ultimo è già disponibile come Instant.toEpochMillis(). Quindi, per un LocalDateTime, ldt.toInstant(offset).toEpochMillis()
andresti
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.