2015-05-07 8 views
12

mio MCVE (come test TestNG unità):Java 8 DateTimeFormatter parsing per frazioni di secondo opzionali di varia rilevanza

public class MyDateTimeFormatterTest { 

    private static final String BASE_PATTERN = "yyyy/MM/dd HH:mm:ss"; 
    private static final DateTimeFormatter FORMATTER = 
      DateTimeFormatter.ofPattern(BASE_PATTERN + "[.SSSSSSSSS]"); 
    private static final LocalDateTime TEST_INPUT = 
      LocalDateTime.of(2015, 5, 4, 12, 34, 56, 123456789); 

    @DataProvider(name = "test-cases") 
    public Iterator<Object[]> getTestCases() { 
     return Arrays.asList(testFor("", ChronoUnit.SECONDS), 
       testFor(".SSS", ChronoUnit.MILLIS), 
       testFor(".SSSSSS", ChronoUnit.MICROS), 
       testFor(".SSSSSSSSS", ChronoUnit.NANOS)).iterator(); 
    } 

    @Test(dataProvider = "test-cases") 
    public void testWithDefaultResolution(String input, LocalDateTime output) { 
     assertThat(FORMATTER.parse(input, LocalDateTime::from), equalTo(output)); 
    } 

    private Object[] testFor(String patternSuffix, TemporalUnit truncatedTo) { 
     return new Object[] { DateTimeFormatter.ofPattern(BASE_PATTERN + patternSuffix) 
       .format(TEST_INPUT), TEST_INPUT.truncatedTo(truncatedTo) }; 
    } 
} 

sto cercando di testare il parsing di un data-ora String con opzionali frazioni di secondo su variazione significativa utilizzando DateTimeFormatter. La parte rilevante del Javadoc legge:

Frazione: Emette il campo nano-di-secondo come una frazione-di-secondo. Il valore nano-secondo ha nove cifre, quindi il numero di lettere del modello è compreso tra 1 e 9. Se è inferiore a 9, il valore nano-secondo viene troncato, con l'output delle sole cifre più significative.

Sulla base della mia comprensione limitata, ho usato [...] per marcare le frazioni di secondo, come optional, e dato che io sono interessato a diversa entità, ho pensato che avrei dovuto attenersi a SSSSSSSSS.

Tuttavia, il test dell'unità non riesce durante l'analisi di fino a millisecondi e microsecondi, vale a dire il secondo e il terzo caso. La modifica di ResolverStyle in LENIENT non è utile in quanto non riesce nella fase di analisi, non nella risoluzione.

Posso sapere quali approcci dovrei considerare per risolvere il mio problema? Dovrei usare DateTimeFormatterBuilder per specificare facoltativamente ogni cifra frazionaria (9 volte), oppure c'è un modo "più intelligente" con il mio pattern?

modifica Ho trovato la mia risposta alla fine ... lascerò questo come senza risposta per un giorno e vedere se ci sono altri approcci o meno.

+1

Hai anche visualizzato questa domanda: http://stackoverflow.com/questions/30103167/jsr-310-parsing-seconds-fraction-with-variable-length? Sembra che la tua risposta sia essenzialmente la stessa – araqnid

+0

@araqnid grazie per averlo indicato ... Ho aggiornato la mia risposta qui sotto per eliminare 'parseLenient()', per riferimenti futuri ... –

risposta

18

Oh fresco, altri 15 minuti di risoluzione dei problemi ha dato questo:

private static final DateTimeFormatter FORMATTER = 
    new DateTimeFormatterBuilder().appendPattern(BASE_PATTERN) // .parseLenient() 
     .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true).toFormatter(); 

modificaparseLenient() è optional.