日またぎな処理で恥ずかしい間違いを犯す

別システムから取得するデータを元にこちら側のデータを探索したりする処理でのお話。
よくある話なんだろうけど...AM0:00を過ぎると日付が変わり『翌日』になるんだがこのシステムではAM0:00を過ぎてある一定時までを『今日』と処理することになってた。
ってかそう設計書にはかかれてた。たとえばこうだ。

  • 2009年3月8日で処理
    • 2009年3月8日AM06:00
    • 2009年3月9日AM02:30
  • 2009年3月9日で処理
    • 2009年3月9日AM06:00
    • 2009年3月9日PM11:00


実装ではなぜか別システムから受け取るデータ中から日付のデータを取っていた。
今になって思えばシステム日付でいいんじゃないかと思うんだがまぁそこはそこで。
いろいろあるんですよ...。


一応、日付を変換するためのロジックが用意されていた。こいつに日付をぶち込めばこのシステムで認識する日付をとれる。


さて、なぜか知らんが夜中のある一定時間帯にシステムがうまく動かないなんて障害報告が出てきた。こいつとは別にまた違う障害があったんでついでになおしちまいなってオーダーされとりあえずおいらが見ることに。まぁ仕方ない。めんどいのはおいらがやるって方針なんで。
ほどなく日付処理がおかしいことに気づく。問題となっている時間帯は『今日』になっていなきゃならないのに『翌日』として処理され、データ抽出条件の日付も『翌日』で探索されていた...んでみつかるはずないんで障害になっていた。
おもしろいことにシステム日付を取得してる部分はきちんと変換ロジックかましていたのに一箇所だけ忘れてたらしい。どこかと思い調べてみると、別システムからデータとってそこにかかれてる日付をつかって処理する部分。漏れっすな。まぁ仕方ない。
開発中は夜中テストとかシステム時刻を変えてテストなんてことが出来ない感じだったんで。


であーあと変換ロジックかましてコミット。
さっそくどーん
...あれ、なんかおかしい。
よくわからん。でもうひとりいる人とログ見たりして悩む...。
日付が『前日』になっていた。なして???
ってことでよーくみてみる。
日付変換ロジックに渡してる値をみると、YYYY-MM-DDだった。
そして時刻部分がなかった...どうも時刻がないと0:00:00にしてくれるらしい。
うわーっと絶叫しつつもういちどコミット。
再びどーん
...また駄目?
きちんと時間部分も渡してるはずなのに日付が『前日』のまま。
ソースコードもきちんと対応したものをつかってるはずっていうか調べたが修整した奴だった。
なんで? どうして? 神様お願いもう悪いことしませんからえ〜ん。
で、ふと時計を見る。12:00過ぎだった。
ここにきてようやっと日付変換ロジックの中身を見る。
内部的にはほぼSimpleDateFormat読んでるだけ。
ちょっと調べてみた。

日付/時刻フォーマットは日付/時刻パターン文字列で指定されます。日付/時刻パターン文字列内では、引用符で囲まれていない 'A' 〜 'Z' および 'a' 〜 'z' は、日付または時刻文字列のコンポーネントを表すパターン文字として解釈されます。テキストは単一引用符 (') で囲むことで解釈を回避できます。"''" は単一引用符を表します。他のすべての文字は解釈されず、フォーマット中に出力文字列へ単純にコピーされるか、解析中に入力文字列に対して一致させられます。
次のパターン文字が定義されます。(他の 'A' 〜 'Z' および 'a' 〜 'z' のすべての文字は予約済み)

文字 日付または時刻のコンポーネント 表示
G 紀元 テキスト AD
y 1996; 96
M July; Jul; 07
w 年における週 数値 27
W 月における週 数値 2
D 年における日 数値 189
d 月における日 数値 10
F 月における曜日 数値 2
E 曜日 テキスト Tuesday; Tue
a 午前/午後 テキスト PM
H 一日における時 (0 〜 23) 数値 0
k 一日における時 (1 〜 24) 数値 24
K 午前/午後の時 (0 〜 11) 数値 0
h 午前/午後の時 (1 〜 12) 数値 12
m 数値 30
s 数値 55
S ミリ秒 数値 978
z タイムゾーン 一般的なタイムゾーン Pacific Standard Time; PST; GMT-08:00
Z タイムゾーン RFC 822 タイムゾーン -0800


嫌な予感がしてソースを見る。

yyyy-mm-dd hh:m:ss


はい。hhをHHに直しました。
痛すぎ...orz