会社で commons ftpclient を使っているシステムがありまして、 こいつが今日動かなくなってたんです。
で、調べたら、commons ftpclient のバグらしく、 こんなパッチを見つけました。
<URL:http://svn.apache.org/viewvc?view=rev&revision=631284>
FTP でファイルのリストを取得したときに、
Feb 29
みたいなタイムスタンプ文字列が返ってくる訳ですが、 こいつをうまくパースできずにエラーしていたらしい。
Feb 28
はパースできるのに
Feb 29
がパースできないってどういうことだ?と不思議になり、 ちょっと追試してみましたが、結局のところこれは SimpleDateFormat のバグ(仕様?)ってことに なるのかなぁ?
SimpleDateFormat sdf = new SimpleDateFormat("M d");
sdf.setLenient(false);
Date date = sdf.parse("2 28");
System.out.println(date.toString());
このコードだと、
// => Sat Feb 28 00:00:00 JST 1970
という文字列が返って来て(1970年ってのはどうなんだ?という のはさておき)問題ありません。
しかし、うるう日である 2/29 をパースしようと 以下のようなコードに変えた途端に、
SimpleDateFormat sdf = new SimpleDateFormat("M d");
sdf.setLenient(false);
Date date = sdf.parse("2 29");
System.out.println(date.toString());
ParseException ですよ。
ちなみに、Format を "y M d" などにして、
parse("2008 2 29")
だと、例外は上がってこないみたいです。
1970年2月29日って日付を作ろうとして、1970年は 閏年じゃないから、この日付は間違いだねー、ってことで 例外をあげてるんじゃないかと思いますが、、、
これを使って、日付を作ろうとすると、いちいち自分で 「今日の日付を求めてー、年の部分だけ取り出してー、 パースしたい文字列に年をくっつけてー」というお膳立てを してあげないと、意図通りの日付を作ってくれないわけです。
非常に使いにくすぎですね。
Java をお使いの方は気をつけてください。
ちなみに、Ruby だと、「今年の」2/29 としてオブジェクトを 作ってくれるので、こんな問題は起きません。 しかも、フォーマットの指定とかしなくても空気を読んで、 なんとなくパースしてくれますし。
Rubyのtime.rbは、ものすごく空気の読める子。
$ irb
>> require 'time'
=> true
>> Time.parse("Feb 29")
=> Fri Feb 29 00:00:00 +0900 2008
と、いうわけで(?)。