No Programming, No Life

プログラミング関連の話題や雑記

日付フォーマットエラー

今私が仕事で作っているとあるシステムで、
エラーが発生しました。

ブラウザ上のINPUTフィールドに入力された
日付フォーマット文字列を
そのままSQLに投げる部分でこのエラーが発生した模様です。

ORA-01847: 月単位の日付は1から月末日の間で指定する必要があります

さて、このOracleのエラーが発生したわけですが、
これはたとえば "2006/5/32" とかみたいな
ありえない日付を入力されたときに起こるエラーです。

ところで今作っている日付フォーマットチェックは完璧にされているはずなんですが
どうしてこんなことが起こったんだろう?
データ受け渡しのBeanの詰め替えが失敗しているのかな?
ということでソースコードをひたすら追いかけていってみたら
以下のような部分を発見しました。

/* 作成日(To) */
str = bean.getSishkshnToDt();
if (str != null && false == str.equals("")) {
	list.add(str + "23:59:59.999999999"); //作成日(To)
}

SQLのWHERE部分

str = bean.getSishkshnToDt();
if (str != null && false == str.equals("")) {
	conditionBuff.append(" AND b.sishkshn_dt <= TO_TIMESTAMP(?,'YYYY/MM/DDHH24:MI:SSxFF')"); //作成日(To)
}

beanの項目sishkshnToDtに "23:59:59.999999999" を結合した文字列を
SQLのパラメータとして作成している部分なんですが、
これではまずいことに気が付きます。
もし、strの中身が"2006/5/3"のような日付だった場合、
結合した文字列は
"2006/5/323:59:59.999999999"となってしまい
これで晴れて"2006/5/32"という
無茶な日付が完成します。

回避作として以下のようにするといいみたいです。

list.add(str + " 23:59:59.999999999"); //作成日(To)

のように23の前に半角スペースを入れてあげると
Oracleさんはちゃんと動いてくれるみたいです。

このエラーの原因は日付フォーマットチェックを行った後に
文字列を結合してしまっている点にあります。
エラーチェックの際の順番は大事ですね。