2015-05-07 9 views
12

Meine MCVE (als TestNG Unit-Test):Java 8 DateTimeFormatter für optionale Sekundenbruchteile von Parsen Bedeutung unterschiedlicher

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) }; 
    } 
} 

Ich versuche, das Parsing einer Datum-Zeit String mit optional Sekundenbruchteilen zu testen, von unterschiedliche Bedeutung mit DateTimeFormatter. Der relevante Teil des Javadoc- lautet:

Fraction: Ausgabe des nano-of-Feld als eine zweite Fraktion-of-Sekunde. Der Nano-Sekunden-Wert hat neun Ziffern, daher beträgt die Anzahl der Musterbuchstaben 1 bis 9. Wenn es kleiner als 9 ist, wird der Wert für den Nano-Sekunden-Wert abgeschnitten, wobei nur die höchstwertigen Ziffern ausgegeben werden.

Aufgrund meiner begrenzten Verständnis, benutzte ich [...] die Sekundenbruchteile als optional zu markieren, und da ich in unterschiedlicher Bedeutung interessiert bin, dachte ich, ich SSSSSSSSS bleiben sollte.

Der Komponententest schlägt jedoch bei der Analyse bis zu Millisekunden und Mikrosekunden fehl, d. H. Der zweite und der dritte Fall. Das Ändern der ResolverStyle zu LENIENT hilft hier nicht, da es bei der Parsing-Phase fehlschlägt, nicht die Auflösung.

Darf ich wissen, welche Ansätze ich zur Lösung meines Problems in Betracht ziehen sollte? Sollte ich DateTimeFormatterBuilder verwenden, um optional jede Nachkommastelle (9 Mal) anzugeben, oder gibt es eine "klügere" Methode mit meinem Muster?

bearbeiten Ich fand meine eigene Antwort am Ende ... wird immer noch als unbeantwortet für einen Tag verlassen und sehen, ob es andere Ansätze gibt oder nicht.

+1

Haben Sie auch diese Frage gesehen: http://stackoverflow.com/questions/30103167/jsr-310-parsing-seconds-fraction-with-variable-length? Sieht so aus, als ob deine Antwort im Wesentlichen die gleiche ist – araqnid

+0

@araqnid danke, dass du darauf hingewiesen hast ... Ich habe meine eigene Antwort unten aktualisiert, um 'parseLenient()' auch für zukünftige Referenzen zu löschen ... –

Antwort

18

Oh cool, weitere 15 Minuten zur Fehlerbehebung ergab dies:

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

bearbeitenparseLenient()optional ist.

Verwandte Themen