2038年問題は心配しなくていい(と思う)(346号)
前回、複数のサーバ間での時刻同期についてのお話をしました。
今回はその続きというわけではないですが、2038年問題についてお話をします。
日時情報の持ち方
一般にコンピュータが扱える値には上限があります。
これは、データ領域をどれだけの大きさに定義するのかによります。
さて、コンピュータでは数値を表現する時、必ず領域の大きさを事前に決めておきます。
例えば、4ビット(二進数で4ケタ分)なら0~15(16種類)しか表現できません。
これは月を示すには十分ですが、時分秒には使えません。
これが5ビットなら、0~31(32種類)になりますので日付や時間(0時~23時)が表現できます。
さらに、6ビットだと、0~63(64種類)ですので、分や秒が表現できるようになります。
これを全て満たそうとすると、以下のようなデータ構造となります。
年:12ビット(4096種)
月:4ビット(16種)
日:5ビット(32種)
時:5ビット(32種)
分:6ビット(64種)
秒:6ビット(64種)
----------
計:38ビット
これでも問題はあって、西歴4096年には日付が表示できなります。
とはいえ、そんな未来のことはその時代の方におまかせするとして、ここでは無視します。
一見何の問題もなさそうなデータ様式ですが、これ、コンピュータにとっては扱いづらい方式なんです。
シンプルに書く技術
例えば、上記のデータ構造で10分を加える手順(プログラム)を考えます。
通常は「分」のデータに10を加えればOKです。
ですが「分」データは60を越えてはいけません。
60以上なら「分」データから60を引き、「時」データに1を加える処理が必要です。
さらに「時」データが24を越える場合は、「時」データから24を引いて「日」データを1加える、その「日」データが30や31の場合は...と続きます。
これを実現するのはかなり面倒ですよね。ちょっとしたミスでバグを仕込むことにもなりかねません。
プログラマの格言に「バグを出さない方法はプログラムを書かないことだ」というのがあります。
別にプログラムを作るなということではありません。
本当に必要なプログラムだけを作ろう、そしてできる限りシンプルかつコンパクトに書こう、ということです。
こう考えると、どうも上述の日付データの構造に問題がありそうです。
一つの解法として、日付データを単一の値にする方式があります。
特定の年月日からの累計秒数だけを覚えておこうという考え方です。
これなら、時間の足し算は恐ろしくシンプルに書けます。
10分加えたいなら、10*60=600秒 の値を現在の秒数に加えるだけです。
時のケタ上がりも日付も考慮する必要はありません。
3日を加えたいなら、3*(24*60*60)を加えれば良いのです。
確かに計算は多くなりますが、それこそコンピュータの得意中の得意分野ですので問題ありません。
足し算だけではなく、時間差計算だって同様です。
時刻AとBの差分(秒数)はA-B だけで計算できてしまいます。
これ、最初の例だと面倒極まりないプログラムが必要になります。
こういった累計秒数での時間計算の代表格がUNIXタイム(UNIX時間)です。
UNIXタイム
UNIX(ユニックス)と呼ばれるOSがあります。Windowsよりさらに古いOSで、1970年代に登場したOSです。UNIXはサーバと呼ばれる業務用コンピュータのOSによく使われています。
余談
昔はUNIXが動作するコンピュータは高価でした。
筆者が学生の頃はUNIXマシンはン百万円があたりまえでした。
(ApplloとかSunとか)
当時、Sonyが発表したNEWS(ニューズ)100万円代~は衝撃的でした。
それでも筆者には手が届きませんでしたが。
今はLinuxやFreeBSDといった無償のUNIX系OSがあります。
どれもフツーのパソコンで動作します。
長生きはするもんです。
そのUNIXでは最初期から、時刻は1970年1月1日からの累計秒数を用いていました。
これをUNIXタイム(UNIX時間)と呼びます。
1970年からの累計秒数としているのは、UNIXが作られたのが1970年代だったからです。
一般に、過去の正確な日時(特に秒単位)を使って計算したいケースがほとんどない一方で、未来の時間計算や現在時刻との差分が必要となることは応々にあります。
なので、西歴0年からの累計ではなく、1970年からの累計値としているのです。
2038年問題
年配の方なら2000年問題というものを覚えている方も多いと思います。
これは、多くのコンピュータでの日付計算がUNIXタイムのような累計時間ではなかった時代ならではの問題でした。
当時は、年月日時分秒を個別に記録しているシステムが多く、年号を2ケタしか持っていないシステムも多かったのです。
これは、メモリが高価だった&ケタ区切りでデータを持つのが当然だった時代故のトラブルだったと言えます。
2000年問題では、銀行システムの誤動作で預金が消滅する、コンピュータを利用している公共交通機関がのきなみ動かなくなる、あげくは核ミサイルが勝手に発射される、などとマスコミがセンセーショナルに騒ぎたてました。
ですが、実際には大きなトラブルはほとんど起きませんでした。
筆者が所属していた会社(ハードウェア開発+システム開発会社)でも念のためということで年末年始を交替で出勤しましたが、トラブルはゼロだったようです。
さて、UNIXタイムでは2038年問題というものが危惧されています。
これは、累計時間の秒数が決められたデータ領域で表現できる値を越えることを示しています。
当初のUNIXタイムの累計秒数は31ビットでした。
これは21億秒超(2,147,483,647)まで計算可能な値です。
この21億秒は年数に直すと、68年0ヶ月19日3時間14分7秒となります。
UNIXタイムは1970年からの累計秒数ですので、上の数字を足すと2038年1月19日3時14分7秒までしか時間表記ができません。
とはいえ、この問題は既に2000年頃から指摘されており、現在はUNIXタイムの累計時間を63ビットにするなどの対策済です。
ですので、この10年以内くらいに作成されたシステムは余程特殊な事情がない限り、2038年問題の対象となりません。
それよりも前に作られたシステムでは問題となる可能性がありますが、そのような古いシステムを2038年まで稼動させ続けることは相当難しそうです。
例えば2010年に稼動し始めたシステムで、28年間動作し続けないといけませんが、その前にハードウェア寿命や経済寿命を迎えるだろうと思われます。
そうそう、UNIXタイムを63ビットにしたって、いつかはいっぱいになるんでしょ?と思われる方に補足しておきます。
この63ビットというのは、先の31ビット(68年)に32ビット(約43億)を掛けたものになります。
計算すると、68年×43億=2924億年(!)、ですね。
太陽系の寿命が100億年程度だそうですので、太陽系が30回ほど生まれたり死んだりを繰り返すまで大丈夫です。
それでも溢れる時のことは未来の人に考えてもらいましょう。
まとめ
UNIXというシステムでは伝統的に秒数を1970年1月1日からの累計時間で保持しています。
コンピュータではどんなデータでも領域の大きさが決まっています。
UNIXシステム上での時刻データは31ビットのものが主流でした。
31ビットというのは、だいたい21億までの値を表現できます。
これを秒数と考えると、約21億秒、年数で言うと、68年程度になります。
UNIXタイムが1970年からのカウントですので、いっぱいになるのが2038年1月19日になります。これを2038年問題と呼びます。
とはいえ、筆者はあまり2038年問題を心配していません。
まず、最近のUNIXシステムではより大きな値が表現できるようにUNIXタイムのビット数を増やす作業が完了しています。
ですので、今後作られるシステムはほぼ間違いなく2038年問題の対象となりません。
一方で、古いシステムでは、そもそも2038年まで継続利用するのか?という疑問があります。UNIXタイムが31ビットだったのはせいぜい2010年頃までだと思います。
とすると、2038年を迎えた頃には28才以上になっている計算です。
皆さんのお手元でも28年以上前のコンピュータは残っていないと思います。
もちろん、陰ながら動き続けるネットワーク機器や工場などのライン監視機器などは20年以上稼動することも多いですが、故障や経済寿命で引退するものが大多数でしょうし、使い続けたものについても2038年に必ず不具合が出るとは限りません。
仮に不具合が出たとしても、その機器を再起動すれば、(過去に生きることになるかもですが)多くの場合は気嫌よく動いてくれると思われます。
以上より、筆者は2038年問題は大きな問題にはならないだろうと考えています。
だからといって放置はダメですよ。
不要なトラブルを避けるためにも、こういった古い機器の更新可否を販売元に確認しておきべきです。
今回は2038年問題についてお話しました。
次回もお楽しみに。
(本稿は 2024年2月に作成しました)
この記事が気に入ったらサポートをしてみませんか?