web-dev-qa-db-ja.com

SimpleDateFormatをDateTimeFormatterに変換する

したがって、SimpleDateFormatとDateを使用してレガシーコードを置き換えようとしたときに、Java.time.DateTimeFormatterとLocalDateを使用すると問題が発生しました。 2つの日付形式は同等ではありません。この時点で、2つの日付タイプが同じではないことを知っていなければなりませんが、私がいるシナリオでは、時間の側面を気にしないので無視できます。

public Date getDate(String value) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
    try {
        return dateFormat.parse(value);
    } catch (ParseException e) {
        return null;
    }
}

public LocalDate getLocalDate(String value) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    try {
        return LocalDate.parse(value, formatter);
    } catch (DateTimeParseException e) {
        return null;
    }
}

public void testDates() {
    getDate("03/07/2016");               // Sun Jul 03 00:00:00 BST 2016
    getDate("3/7/2016");                 // Sun Jul 03 00:00:00 BST 2016
    getDate("3/7/2016 00:00:00");        // Sun Jul 03 00:00:00 BST 2016
    getDate("3/7/2016 00:00:00.0+0100"); // Sun Jul 03 00:00:00 BST 2016
    getDate("3/7/2016T00:00:00.0+0100"); // Sun Jul 03 00:00:00 BST 2016

    getLocalDate("03/07/2016");               // 2016-07-03
    getLocalDate("3/7/2016");                 // null
    getLocalDate("3/7/2016 00:00:00");        // null
    getLocalDate("3/7/2016 00:00:00.0+0100"); // null
    getLocalDate("3/7/2016T00:00:00.0+0100"); // null
}

両方のフォーマッターで同じパターンがいつ使用されるかを確認できるように、DateTimeFormatterは、SDFの日付と同等の日付が表示されると予想される場所でnullを生成します。このシナリオでは、不要なデータが削除されることを期待していますが、そうではありません。

では、どのようにして堅牢な日付/時刻パーサーを作成するのですか?

13
Remlap21

したがって、これに対する他の答えがあるかもしれませんが、私が思いついたものは、私が持っている最も極端なケースに対応しています。まず、dd/MMをd/Mに減らしました。これは、予期される文字の最小数を示すため、2桁の数字を完全に解析します。新しいDateTimeFormatterBuilder()。parseLenient()を使用することもできますが、これは不要に見えました。

次に、フォーマットパターン自体にオプションの句を使用することにしました。これにより、提供されない可能性があるパーツを指定できます。これは、私が解決しようとしていたケースとまったく同じです。

私たちを残して:

DateTimeFormatter.ofPattern("d/M/yyyy[' ']['T'][H:mm[:ss[.S]]][X]");

これは、Tセパレーター、秒、ミリ秒、ゾーンオフセットを含む、日付ありまたはなしの日付の提供を処理します。

運が良ければ、これは他の誰かを助けます!

private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yyyy[' ']['T'][H:mm[:ss[.S]]][X]");

public LocalDate getRobustLocalDate(String value) {
    try {
        return LocalDate.parse(value, formatter);
    } catch (DateTimeParseException e) {
        return null;
    }
}

@Test
public void testDates() {
    getRobustLocalDate("03/07/2016");               // 2016-07-03
    getRobustLocalDate("3/7/2016");                 // 2016-07-03
    getRobustLocalDate("3/7/2016 00:00:00");        // 2016-07-03
    getRobustLocalDate("3/7/2016 00:00:00.0+0100"); // 2016-07-03
    getRobustLocalDate("3/7/2016T00:00:00.0+0100"); // 2016-07-03
}
12
Remlap21