民芸的プログラミング 〜ソフトウェア開発日記〜

アクセスカウンタ

zoom RSS 8月と9月にしか見られないバグ

<<   作成日時 : 2009/04/10 07:18   >>

ブログ気持玉 0 / トラックバック 0 / コメント 0

2008年9月30日を、"20080930"と表記しているデータがあった。いわゆるYYYYMMDD形式というやつだ。
これを年度表記に変換するために、月を意味する5文字目から2文字分(ここでは"09")を切り出して、それが3以下だったら、年を一つマイナスするというプログラムを組んだ。
すると、得られた結果が、なぜか2007年度の9月30日となってしまった。
もちろん私のプログラムミス。

使用した言語は JScript。
var mydate="20080930";
myyear = parseInt(mydate.substr(0, 4)) +((parseInt(mydate.substr(5, 2)) <= 3) ? -1 : 0);
こんな感じのプログラムだった。
見る人が見れば、間違いにはすぐ気付くのだろうが、知らない人にとっては、なぜこれがいけないのかさっぱり分からないだろう。

問題は parseInt(mydate.substr(5,2)) の部分。
結論からいくと parseInt("09") は 0 と評価されてしまうのだ。

なぜなら、parseInt では、一文字目に 0 がつくのは8進数の印だからだ。8進数に9以上の数字はありえない。ここで、エラーを返してくれればいいものを、なぜか parseInt は 0 を返す仕様になっている。
プログラムは動き続けてしまうわけだ。

しかも厄介なことに、このバグは8月と9月のデータでしか発生しない。
01 〜 07 は8進数として正常だし、10月以降は正常な10進数として扱われるからだ。
プログラムのテストの際に、8月や9月のデータを投入していないと、気付かないままリリースされてしまうことになる。

正しい使い方は
var mydate="20080930";
myyear = parseInt(mydate.substr(0, 4), 10) +((parseInt(mydate.substr(5, 2), 10) <= 3) ? -1 : 0);
となる。ポイントは、基数を指定して、10進数であることを parseInt に知らせている部分。

バグが見つかった後からこの記事を書いているので、記事自体はあっさりしたものだが、問題部分の特定にはかなりの時間がかかった。
ちなみに、Perl では、"09" は十進数の9に変換される。言語仕様を予めしっかりと学習しておくしか対策はないようだ。

テーマ

関連テーマ 一覧


月別リンク

ブログ気持玉

クリックして気持ちを伝えよう!
ログインしてクリックすれば、自分のブログへのリンクが付きます。
→ログインへ

トラックバック(0件)

タイトル (本文) ブログ名/日時

トラックバック用URL help


自分のブログにトラックバック記事作成(会員用) help

タイトル
本 文

コメント(0件)

内 容 ニックネーム/日時

コメントする help

ニックネーム
本 文
8月と9月にしか見られないバグ 民芸的プログラミング 〜ソフトウェア開発日記〜/BIGLOBEウェブリブログ
文字サイズ:       閉じる