1999.9.13

1999年9月9日問題クリア?

 それなりに深刻だった9999問題も、大事にならずにすんだようだ。
 2000年問題の予行演習みたいな形式でチェックしたところもあるようだ。
 というのが、マスコミの記事だ。

 年月日入力時に9999を入力するとページ終了というプログラムもあるというのが、9999問題だ。
 つまり、1999年9月9日のデータ入力が出来ない。また、内部処理で扱おうとすると処理が中止になるという。
 ただ、考えてみて欲しい。
 マスコミはいろいろ騒いでいるが、年月日で9999を入力することがあるだろうか?
 もし、YYMDで入力するプログラムがあった場合、1998年10月10日はどう入力する?
 981010と入力するのではないか?
 ということは、9999という4桁の数字を入力することはないのではないか?
 1999年9月9日は、990909と入力するのではないか?
 もし「年」入力欄だとしたら、9999年の時に問題になるだろう。
 で、「年」入力欄が2桁で、99という数字がキーになっていた場合、今年の最初(去年の終わり)には、既に問題が発覚しているはずである。

 同様に、4桁入力の場合、0000は存在しない。
 問題は、「00」という2桁の西暦入力の場合である。
 最近になってマスコミが騒いだ、9999問題は、全く問題がないか、もしくは既に問題が発生して修正済みということだ。

 2000年問題は1999から2000になる場合の、西暦2桁時の処理であるが、普通に考えると、残りの2000年問題はうるう年をちゃんと計算しているかどうかだけである。
 もちろん、ハードウェア的に、つまりBIOS(リアルタイムクロックのIC)が2000年以降に対応しているかどうかも重要ではあるが、この点については後述する。


 本当の問題は、これからである。
 20??年問題はまだ先だがもっと深刻だと思っている。  unixや MS-DOS等では、いろいろあったが、C言語の場合、1900年からや1970年からや1980年の1月1日0時0分0秒からの秒数だったと記憶している。(もちろん、ライブラリ関数なので、処理系依存で、すべてがそうだとは言えない。)
 unixや MS-DOSでプログラムしていたころは、OSから取得したこの秒数を使用して、現在の日付や時刻を取得していた。この秒数を表す数値が、だいたい long(主に32ビット)であった(ビット数も処理系依存)。doubleのものもあったかもしれないが、だいたい longであったと思う。
 符号付整数値は、2の補数だとし、longは32ビットだとすると、
 ・longでは、-2147483648〜2147483647
 ・unsigned longでは、0〜4294967295
 となる。ここで、1900年を基準として longを使用していた場合は全くだめなので、2通りの計算を考えてみる。
<1900年を基準として、unsigned longを使用していた場合>
 ・1年365日(うるう年の場合は366日)
 ・1日(24*60*60=)86400秒
 とすると、
 4294967295/86400=49710.269618055555555555555555556で、49710日と6時間28分15秒になる。
 うるう年は、
 ・西暦で4で割れる数値
 ・ただし、100で割れる場合は違う
 ・ただし、400で割れる場合はうるう年
 となっているので、1900年はうるう年ではない。
 残りは、2000年を含めて4年ごと。
 1900年からはじめると、136年2月5日なので、2036年2月5日6時28分15秒に最後となり、2036年2月5日6時28分16秒は、1900年1月1日0時0分0秒に戻ってしまう計算になる。

<1970年を基準として、longを使用していた場合(ansi time()関数)>
 同様に、
 2147483647/86400=24855.134803240740740740740740741で、24855日と3時間14分7秒になる。
 1970年からはじめると、68年1月18日なので、2038年1月18日3時14分7秒に最後となり、2038年1月18日3時14分8秒は、1980年1月1日0時0分0秒に戻ってしまう計算になる。

 多分計算は間違っていないはずだが、各自計算しなおしてもらいたい。

 1秒以下の単位も計ることが出来るリアルタイムクロックを持っているコンピューターの場合は、もしかしたら doubleになっていて、計算もぜんぜん変わるかもしれないが、主なコンピューターの現在のアーキティクチャーはある基準時刻からの秒数になっていたはずだ。

 この問題の重要な点は、コンピューターのハードウェアの問題ではなく、OSを含むソフトウェア問題である点だ。
 もちろんハードウェアの問題も大きいが、unixの時代からこういう計算方法を使用してきたC言語では、もし、標準関数(localtime()関数等)を使わずに秒をlongとして自分で計算していた場合、そのプログラムは2038年はじめには使えなくなる。
 どの程度そういうプログラムがあるかわからないが、既に標準で関数があっても、自分で何でもやりたがるバカなプログラマーが作ったプログラムはすべて破綻する。
 標準関数を使用していれば、time_t型がなんであろうと、最悪再コンパイルで何とかなるかもしれない。
 ハードウェア的に万年カレンダーが組み込まれていてもどうしようもない。

 ハードウェアの問題では、ワークステーションではほとんどブラックボックスになってしまっているが、パーソナルコンピューターの場合、BIOSが対応していない場合がほとんどである。各自の BIOSを見てもらえばわかると思うが、20??年で一周してしまうはずである。


 これらを考えると、今回の2000年問題と同様に、問題先送りをしてしまっているのではないだろうか?
 まあ、そのころまで現在のアーキティクチャーのまま行くかどうかわからないが、2000年問題も根本的な考え方は同様に「2000年までには変わっているんちやうかな?」ということだったのではないだろうか。


 これが4桁の西暦に対応しているが、処理系によっては問題が発生するということである。

 2桁の西暦でやっているプログラムは、10年以上前から既にわかっている問題を先送りしただけである。
 なぜ2桁で処理していたかもわかる。
 理由はほとんど金銭的(技術的)な問題である。
 メモリも補助記憶装置(HDD等)も高価な時代に、年を4桁も持っていたらいくらかかることか。
 2桁なら、00〜99までなので、2バイトですむところが、4桁の場合は、最低3バイト必要になる。
 ビットで見れば2桁なら7ビット(1バイト弱)だが、4桁なら14ビット(2バイト弱)必要になる。
 データベースで見ると、1データに付き1バイト少なくなれば、10万件なら約98Kバイト、100万件なら約980Kバイト、1000万件なら約9.5Mバイトも節約できる。
 昔の事情なら、現状必要ないなら無駄になってしまう。
 ほんの十数年前は10Mバイトのハードディスクが数十万したのだ。
 そりゃあ、2桁で持っても仕方がない。
 しかし、どんどん「バイト単価」は下がってきた。その間何もせずにそのまま使っていたのが悪い。と思う。

 コンピューターが使われ始めたときに、時代の先端を狙って早くシステムを入れてしまったが、それからあまりバージョンアップをしていない企業などが困ったことになる可能性がある。

 とまあ、いろいろ書いてきたが、ちゃんとしたSEやPGならこんなことは百も承知なので、2000年問題をクリアした時点で、もろもろの処置が加えられていると信じたい。
 すべてがすべてこのような問題をはらんでいるわけではないことも憶えていて欲しい。
 2000年問題や、20??年問題も、それを狙って一儲けたくらんでいる奴も多いので、気をつけよう。