2015-07-24 6 views
7

In Anbetracht der Tatsache, dass die Flusskontrolle über Ausnahmen als ein Anti-Pattern betrachtet wird, ist es möglich, zu validieren, dass eine Zeichenfolge ein gültiges Datum unter Verwendung der Temporären Bibliothek (java.time.*), ohne darstellt.Kann eine Datumszeichenfolge von DateTimeFormatter validiert werden, ohne Ausnahme zu fangen?

Betrachten Sie den folgenden Code, der auf einer inneren Explosion beruht:

public static boolean isValidDateFormat(String date, DateTimeFormatter formatter) { 
    try { 
     formatter.parse(date); 
     return true; 
    } catch (DateTimeParseException e) { 
     return false; 
    } 
} 

dies ohne Fang einer Parse Explosion erreicht werden kann? Gibt es etwas Ähnliches zu formatter.isValid(date) (selbst wenn das intern explodiert - das wäre bis zu dem JDK-Impl, das "hinter dem Vorhang" ist).

+1

Warum nicht Regex verwenden? –

+1

@Daniel gut, weil es nicht klar ist, und erfordert zusätzlichen Programmieraufwand (und Tests). Meine Frage ist mehr im Sinne von "Gibt es eine versteckte JDK-Bibliothek, die mir nicht bekannt ist, kann ein' DateTimeFormatter' bestimmen, ob eine gegebene Zeichenfolge gültig ist " – Bohemian

+0

Ich sehe. Ich weiß nichts über die Existenz dieser gültigen Methode. In JDK-Quellen können Sie beim Debugger nichts finden? –

Antwort

1

Die Format-Engine java.time.format arbeitet immer mit internen Ausnahmen, um den Fluss zu steuern. Das ist sogar richtig, wenn Sie versuchen, eine ParsePosition zu verwenden. Eine Ausnahme tritt, und die ParsePosition -object berichten nicht einmal einen Fehler:

pp = new ParsePosition(0); 
    try { 
     TemporalAccessor t = 
      DateTimeFormatter.ofPattern("uuuu-MM-dd") 
      .withResolverStyle(ResolverStyle.STRICT) 
      .parse("2015-02-29", pp); 
    } catch (RuntimeException e) { 
     e.printStackTrace(); 
     System.out.println("Error! " + pp); 
     // Error! java.text.ParsePosition[index=10,errorIndex=-1] 
    } 

Die javadoc erklärt:

The operation of this method is slightly different to similar methods using ParsePosition on java.text.Format. That class will return errors using the error index on the ParsePosition. By contrast, this method will throw a DateTimeParseException if an error occurs, with the exception containing the error index. This change in behavior is necessary due to the increased complexity of parsing and resolving dates/times in this API.

Das folgende Beispiel versucht parseUnresolved eine Ausnahme unter Verwendung des Verfahrens zu vermeiden:

ParsePosition pp = new ParsePosition(0); 
    try { 
     TemporalAccessor t = 
      DateTimeFormatter.ofPattern("uuuu-MM-dd") 
      .withResolverStyle(ResolverStyle.STRICT) 
      .parseUnresolved("2015-02-29", pp); 
     System.out.println("Info! " + t + "/" + pp); // note, no error in pp here! 
     // Info! {DayOfMonth=29, MonthOfYear=2, Year=2015},null,null/java.text.ParsePosition[index=10,errorIndex=-1] 
     boolean leapyear = Year.from(t).isLeap(); 
     MonthDay md = MonthDay.from(t); 
     if (!leapyear && md.getDayOfMonth() == 29 && md.getMonth().getValue() == 2) { 
      System.out.println("Error!"); // hand-made validation covering a special case 
     } 
    } catch (RuntimeException e) { 
     e.printStackTrace(); // does not happen for given input 
    } 

Dies funktioniert ohne Ausnahme, aber Sie müssen den Validierungscode selbst schreiben whi ch bittet um Ärger.

Ich habe diesen Ansatz des Auslösens von Ausnahmen zur Steuerung des Programmablaufs immer als schlechte Programmierpraxis betrachtet und daher meine eigene Bibliothek Time4J so konzipiert, dass interne Ausnahmen so gut wie möglich vermieden werden (nicht in jedem Fall aber in den meisten Fällen ohne Ausnahme).

ParseLog plog = new ParseLog(); 
    PlainDate date = ChronoFormatter.ofDatePattern("uuuu-MM-dd", PatternType.CLDR, Locale.ROOT).parse("2015-02-29", plog); 
    System.out.println(date); // null 
    System.out.println(plog.isError() + "/" + plog.getErrorMessage()); 
    // true/Validation failed => DAY_OF_MONTH out of range: 29 [parsed={YEAR=2015, MONTH_AS_NUMBER=2, DAY_OF_MONTH=29}] 

Dieser Code zeigt deutlich die Möglichkeit eines anderen Designs. Ich betrachte das gewählte Design von java.time als potentiellen Engpass, wenn es darum geht, Massendaten mit vielen falschen Daten stapelweise zu verarbeiten.

Verwandte Themen