もう、7年前にリリースしたシステムのなんですが、2年に一度実行されるCSVデータのインポート処理なんですよ。リリースの際ももちろんデータ確認しましたサ。過去2~3回の実施でも問題はなかったんですよ。それが今回はインポートした日付時刻データが12時間(半日分)ズレるんです。
このデータでは開始日と終了日をエントリするのです。java.util.Calendarで受けてデータベースに永続化してます。
時刻まで管理しますので、開始日では00:00:00.000に、終了日では23:59:59.999をセットして書き込んでます。
CSVファイルによるバッチ処理とは別に、オンライン画面での個別処理もあるのですが、こちらでは何故か問題ありません。
うーん。デバッグ作業では、成功するオンラインと失敗するバッチ処理の比較を行いました。
面倒くさいので、System.out.println(そのcalendarインスタンス)と、ダラダラと表示してみたところ、失敗ではtime=?となっちょるのがわかりました。調べるとその次のareFieldsSet=falseでは失敗で、成功してるのはareFieldsSet=trueとなっちょります。
ググってみると「なるほどザ・ワールド」。
setterで色々なパラをもらうたびに日時を再算出していたのでは大変なので、日時自体の値の呼び出しがあるまで算出しないヨ・・・と。
ははぁ、なのでtime=?なのネ。で、パラと算出値に矛盾がありませんよ・・・ってのがareFieldsSet=trueとのことなんですね。
あ、失敗のパターンではさらにAM_PM=1になっているじゃア~りませんか!!!!!
これだ!!!!!!失敗のパターンでは時刻が午後基準になっちょる。
そうか!calendarのインスタンスに年月日時分秒をセットする前に、clear()してあげるのが正しいお作法なのだろうけど、それをしていないのでnewインスタンスでの現在時刻が午後(AM_PM=1)だと、2時が14時に半日ズレちゃうのね。(終了日なんぞは翌日になっちゃいます)
対処として、時刻のsetterが発生する個所では必ずAM_PM=0もセットするようにして、バグつぶしできました。
今回のバグは、処理を行った時刻が午後である際にしか発生しません。故にテストでも数回の運用でも発覚しなかったのですね。また、オンライン画面ではjavaScriptの日付をDWRでjavaクラスに読み換える実装なので、改めてnewしないのでスナオに時刻をconvertしてくれるので問題は起こらない・・・と。
理屈がわかればガッテンです。ずいぶんとjavaやってますが、こんなコトでこんなバグが発見されるなんて、本当に勉強になりますネ。