Version 13.28
日付の比較
「今回からはまた日付についてです」
『日付作ったりしたところまでしたよね』
「これでもう好きな日付が作れるから、今度はそれで比較してみます」
『これも簡単そうだけど、結構大変?』
「うーん、大変でもないし、複雑でもないけど、ややこしいかな」
『なんか全部同じ意味に聞こえる……』
「まず、日付の比較は、基本的に秒に変換してからします」
『 Version 13.24 ( No.260 ) でやった、最後に秒にするってゆーのをすれ
ばいいわけね』
「そういうこと。 tm 構造体で日時を作って mktime() で秒に変換、それを
使って比較します。そうしないと」
『まず年で比較して、月で比較して、ってなってややこしい!』
「そういうこと。秒に変換すれば各桁を見る必要はないからね。ただ、この
日時を作るときに注意する点があります」
・見ない桁を 0 にする。
『見ない桁?』
「たとえば、今日が 2004/06/01 - 2004/06/15 の範囲に入っているか、
っていうチェックをしたい場合」
『 tm 構造体で作ればいいでしょ』
「そのときの時分秒は?」
『 0 ……だよね』
「じゃあ、今日の日付は?」
『それは time() で取ってきて……これは秒だからそのまま使えるよね』
「そのときの時分秒は?」
『取ってきた時の……あ、 0 じゃない……』
「さて、今日が 2004/06/15 の場合、 time() で取得した日時は
2004/06/15 ??:??:?? になります。それに対して、範囲末日の
2004/06/15 の日時は、時分秒は 0 だから 2004/06/15 00:00:00 だから」
『げ、今日って 2004/06/15 に入らない!?』
「そういうこと。つまり、このチェックは日付のチェックだから、現在時刻
の時分秒は 0 にしなきゃいけないんです」
『そうしないと、同じ日付で含まれない……』
「こういうところは見落としがちだから注して」
『あ、質問! 2004/06/15 の時分秒を 23:59:59 にするっていうのは?』
「それもひとつの方法だけど、この 2004/06/15 23:59:59 って特殊な日時
だから、他の比較に使いづらいかな」
『そか、一度作った日付を使い回すこともあるんだもんね……』
「それをするんなら、 2004/06/16 で作って〈同一の日付は含まない〉で比
較する手もあるかな」
『その方が楽そう!』
「ただこの場合には、1ヶ月間の範囲指定だと〈次の月〉を取得しなきゃい
けないから面倒かな」
『月末よりは簡単じゃない?』
「 2004/12/01 の1ヶ月後は?」
『繰り上がりの話? だったら秒に変換して 31 足す……の 31 が月末の日
付ね……』
「ま、この辺は関数作っちゃえば面倒なことはないからどちらでもいいか
も。ただ〈日付だけ見る〉っていうのはこういうことも気を付けなきゃいけ
ないんだってことは憶えておいて」
『はーい』
「さて次に、範囲指定の種類について説明します。基本的なパターンは
3つ」
・1対1の比較
例: 2004/06/01 <= 今日の日付
・1対2の比較
例: 2004/06/01 <= 今日の日付 <= 2004/06/15
・2対2の比較
例: 2004/06/01 <= 今日の日付、今日の1週間後 <= 2004/06/15
『……ってゆーか当然だね』
「そこが重要、というかいつも言ってるけど、日時は〈簡単そう〉に見える
ことが危険だから」
『そか、楽勝って思うところに落とし穴があるわけね』
「そういうこと。重要なのはつぎの3つ」
・変数を取り違えないようにする。
・表現方法。
・「ない場合」に対応する。
「まず〈変数を取り違えないようにする〉から」
『ようするに、範囲だったら〈○○から〉と〈××まで〉を取り違えないよ
うに、とか?』
「そっちはたいがい間違えないかな、変数名を begin と end とか、 from
と to とかにすれば」
『それなら間違えないね』
「むしろ、A対Bの比較だったら、AとBを取り違える方が多いから」
『う”、確かに……』
「これはできる限りわかりやすい変数名を使うようにするのがいいんだけ
ど、それでも取り違えやすいから気を付けてね」
『それでも間違えそう』
「それならテストプログラムでこまめにチェックするのがいいかな」
『あ、それなら絶対大丈夫だもんね』
「そういうこと。次の〈表現方法〉は、今紹介した例だと」
2004/06/01 <= 今日の日付
「ってしたけど、仕様とかでこういうふうに具体的に書かれてることはあま
りなくて、たとえば」
・今日の日付以前
・今日より前の日付
・今日よりも過去
・今日より未来以外
『……なんかこんがらがってくる……』
「日本語で書くと色々な表現があるから、こういう場合には十分注意して。
これを記号化すると」
・今日の日付以前 : A <= 今日
・今日より前の日付 : A < 今日
・今日よりも過去 : A < 今日
・今日の日付以降以外 : A <= 今日 ( ← !( 今日 < A ) だから)
「となります」
『そうよねー、記号で書いた方がわかりやすいよねー』
「このあたりをはっきりと決めるのと、本当に〈以前/以降〉じゃないの
か、っていうことも確認が必要」
『以前、ってことはその日を含むか含まないか、ってことね』
「そう。時々、以前/以降のつもりで〈より〉って書いてあることがあるか
ら」
『うわ……』
「こういう所は本当にバグができやすいし、しかも結構重要な箇所だから注
意しないといけないんです」
『難しいね……』
「まぁ、注意すればできるっていうレベルだから注意するしかないんだけど
ね。最後に〈「ない場合」に対応する〉について」
『ない場合?』
「たとえば日付の範囲を入力する場合に〈左側だけ入力〉〈右側だけ入力〉
っていう場合」
『そっか、その日だけ検索ってしたいこともあるもんね』
「それだけじゃないよ?」
『へ?』
□左側だけ入力した場合の対処方法
・完全一致確認(左側とまったく同じ日付のみとする)
・デフォルト範囲検索(右側に1ヶ月後等のデフォルトを使用する)
・片側範囲検索(左側 <= 対象、という検索を行う)
・エラー
『こんなにバリエーションが……』
「さらに【右側だけ入力した場合】とか、【両側とも入力しなかった場合】
とか」
『入力しなかったらエラーなんじゃないの?』
「これも、次のようなバリエーションがあります」
□両側とも入力しなかった場合の対処方法
・今日の日付との完全一致確認
・デフォルト範囲検索(例:現在の月の月始から月末まで)
・全検索
・エラー
『これもこんだけあるんだ……』
「ここで重要なのは、これらはプログラムの問題じゃない、ってこと」
『どゆこと?』
「こういった場合に、プログラムの基準で〈こうすればいい〉っていうのは
ないでしょ」
『ってゆーか使い勝手とかで決めるよね』
「そう、使い勝手や、あとパフォーマンス、つまり検索するのにもどれだけ
時間が掛かるか、それに関連して検索対象のデータ量」
『そういうのが関係してくるわけね』
「それらを総合して、使う人にとってどれが一番いいかを決める、もしくは
実際に使う人に聴いて決めるわけです」
『それが、プログラムの問題じゃない、ってことね』
「日時の難しい点のひとつは、こういったプログラムとはちょっと違う面で
の問題が出てくる点。日時はいろんなところで使われるから」
『いろんなところで注意しなきゃいけないわけね』
「そういうこと」
『……ところで、プログラムの例は?』
「プログラムについては、特に説明することってないかな…… mktime() で
秒に変換して比較するだけだからね」
『そうよねー』
「ただ、注意する点はあるかな。たとえば」
// 今日の日付が含まれていた true 、そうでなければ false 。
bool IsIncludeToday( tm &p_rstBegin, tm &p_rstEnd )
{
time_t lTime_t;
time( &lTime_t );
if (
( mktime( &p_rstBegin ) <= lTime_t ) &&
( lTime_t <= mktime( &p_rstEnd ) )
)
{
// 含まれていたので true 。
return true;
}
return false;
}
「これは現在の日付が含まれているかどうかの関数」
『 mktime() でのべ秒に変換して普通に比較、ね』
「注意点はみっつ。まず、 p_rstBegin と p_rstEnd 、この日付と一致する
日付はどうするのか、ってことが明記されてないかな」
『それって……コメントが、って話?』
「そういうことでもあるし、たとえコメントで詳しく説明していたとして
も、そのコメントを見なきゃいけないでしょ」
『あー、コントラクトってことね』
「そういうこと。プログラムで約束できるわけじゃないから、コメントに頼
るしかないんだけど、そこが危険だから」
『コメント間違えたらどうしようもないしね……』
「ふたつめは、日付のチェックだから」
『あ、時分秒を 0 にしなきゃ!』
「この関数そのものは、そうされてるデータを渡してもらってる、っていう
前提で作ってあります。元々そういうデータしか渡されないんだったら」
『何度もやったら2度手間だもんね』
「みっつめはエラーチェック。 p_rstBegin と p_rstEnd 、逆だったら?」
『あ……』
「これは渡す前にチェックできるから assert するのが一番、かな」
『なんか色々注意点あるね』
「実際に実装するときには、手元で注意点をまとめておいて、それを守って
いるかどうか調べながらプログラムを作った方がいいかもね」
/*
Preview Next Story!
*/
『実際にプログラム作ると面倒そう……』
「そのためにもテストプログラムは作った方がいいかな」
『でもさ、毎回日時変えなきゃいけないじゃん』
「プログラムで変えればいいでしょ」
『へ?』
「というわけで次回」
< Version 13.29 日時の変更 >
『につづく!』
「プログラムのことはプログラムでする、それだけのこと」
『日時もちゃんとプログラムで変えられるんだ……』
「OSでできることはプログラムでもほとんどできる、これ重要」