The HIRO Says

If you smell what The HIRO is cooking!!!

【slim3】日付型のvalidation【Struts】

今更なんですが、日付型データの validation で躓いたのでメモしておきます。
Struts 由来のものなのですが、slim3 でも同様なので、一応 GAE/J の slim3 カテゴリにしています。


1.具体的な事象

日付型の validation では、"yyyy/MM/dd" などのフォーマットを指定できる dateType を使用するかと思います。
この dateType ですが、

  • "2010/01/03" : OK
  • "2010/1/3"  : OK(前のゼロがなくてもOK)
  • "2010/01/32" : NG(存在しない日付)
  • "2010/01/a@" : NG(数値ではない)

になるのはわかります。


ですが、"2010/01/3a" と指定するのはOKだったりします。


2.原因

dateType で使用している SimpleDateFormat#parse() が、ParsePosition を指定していないためです。
"2010/01/3a" の "a" 以前までが日付として解釈され、"a" が切り捨てられます。
そのため、今回の場合では、値が "2010/01/3" と「誤認識」されます。


3.考えられる影響

ユーザによっては、この箇所だけではなく、全体的な品質に問題のあるシステムなのではと誤解されるケースもあり得ます。(私の場合、実際そうでした。)
また、validation はOKでも、後続の処理でのデータ変換で想定外の例外が起こる可能性もあります。


4.対処方法

dateType と一緒に、正規表現のチェックも追加すると良いです。
Struts なら mask、slim3 なら regexp を追加します。
正規表現チェックだけですと、数値部分が日付として妥当かをチェックすることが面倒なので、dateType とセットにした方が無難かと思います。


5.具体例(slim3

    Validators v = new Validators(RequestLocator.get());
    v.add("date", v.dateType("yyyy/MM/dd"));
    v.add("time", v.dateType("HH:mm"));

     ↓

    Validators v = new Validators(RequestLocator.get());
    v.add("date", v.dateType("yyyy/MM/dd"), v.regexp("^\\d{4}/\\d{2}/\\d{2}$"));
    v.add("time", v.dateType("HH:mm"),      v.regexp("^\\d{2}:\\d{2}$"));