SimpleDateFormatのパースは前方一致だよ

SimpleDateFormat#parse(String, ParsePosition)のコード読んだら,そうだった。だから,

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
sdf.setLenient(false);
Date date = sdf.parse(source);

なコードの場合,次の文字列は日付としてパスする。

2007/01/12
2007/1/1
07/01/12
2007/1/31(WED)
2007/2/6に買い物に行きました。

SimpleDateFormat#setLenient(false)は,暦通りの日付かどうかのチェックしかしないようだ。:-(
なんで,setLenient(false)の場合,"2007/2/29"は不正な日付だけど,trueだと"2007年3月1日"と解釈される。
...というのは知ってたんだけど,表題のことは知らなかった。まだまだ,修行が足りない。orz


日付の検査にSimpleDateFormatだけを利用してると,こんなところで足下をすくわれるので,併せて文字列検査(「数字と/だけ」とか)を組み合わせとく必要があるのだろう。
#自前でDateFormatを実装するのは,ちょっとイヤだ。


などと今更言ってみるテスト。:-)


(追記)コメントありがとうございます。なるほどと思い試してみました。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
sdf.setLenient(false);
ParsePosition position = new ParsePosition(0);
Date date = sdf.parse(source, position);
if (position.getErrorIndex() != -1) {
  // パース失敗
} else {
  // パース成功
  if (position.getIndex() != source.length()) {
    // 厳密には失敗
  }
}

うむ,評価精度を高めたいならこっちが正解だな。