2014-09-09 11 views
12

In questo esempio non riesco ad ottenere i millisecondi dall'epoca fuori dalla stringa. Ho provato questo tre diversi modi finora, e l'esempio mostra l'ultimo tentativo. Sembra sempre che il numero TemporalAccessor non supporti ChronoField. Se potessi costruire con successo un'istanza di Instant, potrei usare toEpochMilli().Indicatore di data e ora di analisi ISO utilizzando Java 8 java.time api (solo versione standard)

String dateStr = "2014-08-16T05:03:45-05:00" 
TemporalAccessor creationAccessor = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(dateStr); 
Instant creationDate = Instant.from(creationAccessor); 

Si prega di dare risposte concise (non costruire un formattatore da zero) e utilizzare solo la distribuzione standard di Java 8 (posso farlo con Joda, ma vuole evitare le dipendenze).

Edit: Instant.from nel codice qui sopra getta: java.time.DateTimeException: Unable to obtain Instant from TemporalAccessor: {OffsetSeconds=-18000},ISO resolved to 2014-08-16T05:03:45 of type java.time.format.Parsed

+1

Il codice che hai pubblicato compila e gira bene. Quale versione di Java 8 stai usando? – assylias

risposta

10

Questo sembra essere un bug che ho trovato in tutte le versioni testate prima e incluso jdk1.8.0_20b19 ma non nel finale jdk1.8.0_20. Quindi downloading an up-to-date jdk version risolverebbe il problema. È stato risolto anche nel jdk1.9 più recente.

Nota che il buon vecchio metodo Java 7 funziona in tutte le versioni:

long epochMillis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX") 
        .parse(dateStr).getTime(); 

Supporta inoltre ottenere un Instant:

Instant i=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse(dateStr).toInstant(); 
long epochMillis = i.toEpochMilli(); 

Ma, come detto, un semplice aggiornamento rende il vostro Java 8 codice funzionante.

0

Dal momento non si può correttamente essere rappresentato con un lungo (che hanno progettato l'API per non avere problemi di Y 2040, quando un lungo non è più sufficiente è), è necessario utilizzare una combinazione di due metodi

getEpochSecond()

e

getNano()

Il primo ti dà il numero di secondi di epoca, e quest'ultimo ti dà il numero di nanosecondi che sono passati dallo stesso secondo.

+0

Questi sono entrambi i metodi su Instant, di cui non riesco a ottenere un'istanza. Se potessi, allora Instant # toEpochMilli() sarebbe la risposta. –

+3

Un valore millisecondo durerà molto al di là del 2040. Stai confondendolo con un secondo valore int che scade nel 2038. – JodaStephen

0

Instant.from (creationAccessor) .toEpochMili() dovrebbe ordinare l'utente, almeno in base allo ThreeTen javadoc for TemporalInstant. ThreeTen è l'implementazione di riferimento di javax.time. Fatemi sapere se questo funziona per voi o no, lasciando un commento.

+0

dipende da quanto preciso vuoi essere. toEpochMillis funzionerà, ma come documentato, ad un certo punto nel futuro (2040 ish), questo genererà un'eccezione. Speriamo che java sia ancora in circolazione. – Matt

+1

Entro il 2040, si spera che sarà sostituito con javax.datetimetwentythirtyeight. – hd1

+0

Più guardo al momento e [nell'esempio di wikipedia] (http://en.wikipedia.org/wiki/ISO_8601), più sospetto che si tratti di un bug JDK ... * sigh * – hd1

6

Il tuo codice funziona, a partire dal Java 8 Update 51

il codice sta lavorando ora, come di Java 8 Update 51 su Mac OS X Mountain Lion. Answer di Holger che potrebbe essersi verificato un errore nelle versioni precedenti di Java. Comprensibile come il framework java.time è nuovo di zecca in Java 8.

Ecco una copia modificata del codice.

String dateStr = "2014-08-16T05:03:45-05:00"; 
TemporalAccessor creationAccessor = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(dateStr); 
Instant instant = Instant.from(creationAccessor); 
long millisSinceEpoch = instant.toEpochMilli(); 
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneOffset.of("-05:00")); 

Discarica per consolle.

System.out.println("dateStr: " + dateStr); 
System.out.println("instant: " + instant); 
System.out.println(" millis: " + millisSinceEpoch); 
System.out.println(" zdt: " + zdt); 

Quando eseguito.

dateStr: 2014-08-16T05:03:45-05:00 
instant: 2014-08-16T10:03:45Z 
millis: 1408183425000 
    zdt: 2014-08-16T05:03:45-05:00 

Canonical Metodo:
parse(CharSequence text, TemporalQuery<T> query)

Si consiglia di realizzare il vostro analisi utilizzando un metodo alternativo.

Il documento di classe per DateTimeFormatter indica che il modo normale di analisi deve essere una chiamata a DateTimeFormatter::parse(CharSequence text, TemporalQuery<T> query) anziché DateTimeFormatter::parse(CharSequence text).

Così, invece di questo:

String input = "2007-12-03T10:15:30+01:00[Europe/Paris]" ; 
TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse(input) ; 

... fare questo, in cui si aggiunge un secondo argomento, l'argomento di essere un method reference in Java 8 syntax, per chiamare il metodo di conversione from (in questo esempio, ZonedDateTime :: from):

String input = "2007-12-03T10:15:30+01:00[Europe/Paris]" ; 
ZonedDateTime zdt = DateTimeFormatter.ISO_DATE_TIME.parse(input , ZonedDateTime :: from) ; 

Scarico alla console.

System.out.println("input: " + input); 
System.out.println(" zdt: " + zdt); 

Quando eseguito.

input: 2007-12-03T10:15:30+01:00[Europe/Paris] 
    zdt: 2007-12-03T10:15:30+01:00[Europe/Paris]