2012年6月17日

SimpleDateFormatで日付チェック

文字列をDate型に変換してくれるステキなクラス SimpleDateFormat。
こんな感じで定義していみます。
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
    SimpleDateFormat displayFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");

検証メソッドはこちら。いったんDate型に変換して、また文字列に戻します。
    private static void parse(String dateString) {
        try {
            System.out.println(displayFormat.format(sdf.parse(dateString)));
        } catch (ParseException e) {
            System.out.println("パース失敗:" + dateString);
        }
    }

SimpleDateFormat(Calendarクラスも?)気が利きすぎているので、あり得ない日付を指定すると、勝手にいい感じで変換してくれます。(コメントは処理結果)
        parse("2000/13/1");      // 2001/01/01 00:00:00.000
        parse("2000/2/30");      // 2000/03/01 00:00:00.000

でも、SimpleDateFormat#setLenient(false)を指定すると、厳密にチェックしてくれます。
        sdf.setLenient(false);

        parse("2000/13/1");      // パース失敗:2000/13/1
        parse("2000/2/30");      // パース失敗:2000/2/30

厳密チェックといっても、0埋めとかはチェックしてくれません。イマイチ気が利かない。
        parse("2000/1/1");      // 2000/01/01 00:00:00.000
        parse("1/1/1");         // 0001/01/01 00:00:00.000

さらに実験。
        parse("0/1/1");         // パース失敗
        parse("-1/1/1");        // パース失敗
これは失敗するんですね。

厳密チェックをやめてみます。
        sdf.setLenient(true);

        parse("1/1/1");         // 0001/01/01 00:00:00.000
        parse("0/1/1");         // 0001/01/01 00:00:00.000
        parse("-1/1/1");        // 0002/01/01 00:00:00.000
0年ってのは無いのですね。

結果が一緒だったので、フォーマットを変更して、再実行。
    displayFormat = new SimpleDateFormat("G yyyy/MM/dd HH:mm:ss.SSS")

0年が紀元前1年になるんですね。
西暦 2000/01/01 00:00:00.000
西暦 0001/01/01 00:00:00.000
紀元前 0001/01/01 00:00:00.000
紀元前 0002/01/01 00:00:00.000

ちなみにフォーマットに指定されなかったものは「0」が設定されるようです。
年を指定しなかったら1970年になります。
        SimpleDateFormat sdf2 = new SimpleDateFormat("MM/dd");
        sdf2.setLenient(false);
        System.out.println(displayFormat.format(sdf2.parse("01/01")));  // 西暦 1970/01/01 00:00:00.000

未設定の値を気にせずに使っちゃうかもしれないので注意が必要ですね。

0 コメント:

コメントを投稿