2016-03-23 23 views
17

Attualmente ho un analizzatore di date Joda che utilizza DateTimeFormatterBuilder con una mezza dozzina di diversi formati di data che posso ricevere.Java 8 Data equivalente a DateTimeFormatterBuilder di Joda con più formati di parser?

Sto migrando alle routine Date di Java 8 e non vedo un equivalente.

Come posso fare qualcosa di simile usando Java 8 Date?

DateTimeParser[] parsers = { 
    DateTimeFormat.forPattern("yyyy/MM/dd HH:mm:ss.SSSSSS").getParser() , 
    DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").getParser() , 
    DateTimeFormat.forPattern("ddMMMyyyy:HH:mm:ss.SSS Z").getParser() , 
    DateTimeFormat.forPattern("ddMMMyyyy:HH:mm:ss.SSS").getParser() , 
    DateTimeFormat.forPattern("ddMMMyyyy:HH:mm:ss.SSSSSS").getParser() , 
    DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").getParser() 
}; 

DateTimeFormatter dateTimeFormatterInput = new DateTimeFormatterBuilder() 
    .append(null, parsers).toFormatter(); 
+0

si avrà probabilmente osservare un grave declino delle prestazioni-saggio - soprattutto se si pensa implementare una sostituzione mediante gestione delle eccezioni. Secondo i miei test, Joda-Time è più veloce. Vedi anche questo [problema JDK] (https://bugs.openjdk.java.net/browse/JDK-8152273). –

risposta

16

Non esiste una funzione diretta per eseguire questa operazione, ma è possibile utilizzare sezioni facoltative. Le sezioni opzionali sono racchiuse tra parentesi quadre []. Ciò consente di escludere l'intera sezione della stringa da analizzare.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("" 
    + "[yyyy/MM/dd HH:mm:ss.SSSSSS]" 
    + "[yyyy-MM-dd HH:mm:ss[.SSS]]" 
    + "[ddMMMyyyy:HH:mm:ss.SSS[ Z]]" 
); 

Questo formattatore definisce 3 sezioni opzionali grandi per i tre modelli principali che hai. Ognuno di loro è all'interno della sua sezione opzionale.

lavoro Codice demo:

public static void main(String[] args) { 
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("" 
     + "[yyyy/MM/dd HH:mm:ss.SSSSSS]" 
     + "[yyyy-MM-dd HH:mm:ss[.SSS]]" 
     + "[ddMMMyyyy:HH:mm:ss.SSS[ Z]]" 
    , Locale.ENGLISH); 
    System.out.println(LocalDateTime.parse("2016/03/23 22:00:00.256145", formatter)); 
    System.out.println(LocalDateTime.parse("2016-03-23 22:00:00", formatter)); 
    System.out.println(LocalDateTime.parse("2016-03-23 22:00:00.123", formatter)); 
    System.out.println(LocalDateTime.parse("23Mar2016:22:00:00.123", formatter)); 
    System.out.println(LocalDateTime.parse("23Mar2016:22:00:00.123 -0800", formatter)); 
} 
+0

Se anche le impostazioni locali variano, questo codice non funzionerà. –

+0

Si noti che non è possibile utilizzare questo per la formattazione, solo l'analisi. Durante la formattazione usando un formattatore di questo tipo avrai tutti i formati. Suppongo che se vuoi alcuni formati opzionali e uno "predefinito" per la visualizzazione devi utilizzare due diverse istanze di 'DateTimeFormatter' - una con i formati opzionali usati per l'analisi e una con solo il formato predefinito per la visualizzazione. – Itai

8

Come risposta alternativa al Tunaki, è anche possibile utilizzare DateTimeFormatterBuilder:

DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder() 
    .appendPattern("[yyyy]") 
    .appendPattern("[M/d/yyyy]") 
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1) 
    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) 
    .toFormatter() 
+1

Non ho potuto farlo funzionare con più di un'appendice. Ho creato un elenco di DateTimeFormaters e un loop con try/catch. – Avec

2

iterazione di @ soluzione Tunaki, utilizzando i flussi, quando il codice ha bisogno di accettare diversi modelli in modo configurabile:

DateTimeFormatter dateTimeFormatter = dateFormats.stream() 
     .map(DateTimeFormatter::ofPattern) 
     .reduce(new DateTimeFormatterBuilder(), 
       DateTimeFormatterBuilder::appendOptional, 
       (f1, f2) -> f1.append(f2.toFormatter())) 
     .toFormatter(); 

In questo caso non mi interessa la parte del riduttore del combinatore, ma ne ho bisogno nella firma, quindi ho corretto il combinatore.

Questo codice sarebbe praticamente equivalente a se i modelli di cui sopra (yyyy/MM/dd HH:mm:ss.SSSSSS, yyyy-MM-dd HH:mm:ss[.SSS], ddMMMyyyy:HH:mm:ss.SSS[ Z]) sarebbero stati alimentati al flusso:

DateTimeFormatter formatter = new DateTimeFormatterBuilder() 
    .appendOptional(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSSSSS") 
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]" 
    .appendOptional(DateTimeFormatter.ofPattern("ddMMMyyyy:HH:mm:ss.SSS[ Z]") 
    .toFormatter();