12

例外によるフロー制御は (多くの人が) アンチパターンであると考えていることを考えると、例外をキャッチすることなくjava.time.*、一時ライブラリ ( )を使用して、文字列が有効な日付を表していることを検証することは可能ですか?

内部爆発に依存する次のコードを検討してください。

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

これは、解析の爆発をキャッチせずに達成できますか? に似たものはありますかformatter.isValid(date)(たとえそれが内部的に爆発したとしても、それは「カーテンの後ろ」にあるJDK impl次第です)。

4

1 に答える 1

3

のフォーマット エンジンはjava.time.format常に内部例外を処理してフローを制御します。これは、を使用しようとする場合にも当てはまりますParsePosition。例外が発生し、ParsePosition-object はエラーを報告しません:

   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]
   }

javadocは次のように説明しています。

このメソッドの操作は、java.text.Format で ParsePosition を使用する同様のメソッドとは少し異なります。そのクラスは、ParsePosition のエラー インデックスを使用してエラーを返します。対照的に、このメソッドは、エラーが発生した場合に DateTimeParseException をスローし、例外にはエラー インデックスが含まれます。この動作の変更は、この API での日付/時刻の解析と解決の複雑さが増すために必要です。

次の例では、メソッドを使用して例外を回避しようとしていますparseUnresolved

   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
   }

これは例外なく機能しますが、検証コードを自分で作成する必要があり、トラブルが発生します。

私は常に、プログラム フローを制御するために例外をスローするこのアプローチを悪いコーディング プラクティスと考えてきました。そのため、内部例外を可能な限り回避するように独自のライブラリ Time4J を設計しました (すべての場合ではなく、ほとんどの場合、例外)。

   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}]

このコードは、別の設計の可能性を明確に示しています。java.time多くの間違ったデータを含む大量のバルク データのバッチ処理に関しては、選択された設計が潜在的なボトルネックであると考えています。

于 2015-08-31T16:38:16.273 に答える