ほんとの2000年問題対策って?
2000年対策と称して、
LimitYY=50
if(YY<LimitYY)then YY=YY+2000 else YY=YY+1900
ってなコードを追加しただけなんてのが結構ありそうだ。(注1)
当然、これでは2050年に破綻する。
言い訳は知っている。
- 西暦を4桁にするだけの記憶域が無いのだよ。
- 後50年もすればハードが壊れるから、作り直せばいいじゃない。
しかし、こんなコードは知ってて手抜きしてるか、無知の産物!
チャンと何年でも使える対策方法はあったのだ。
え? LimitYYを2001年に51にして 2002年に52にしてって? ...ダメダメ もっとスマートな方法があるよ
移動窓方式
座標のように本来は無限に続く、だけど今を基準にその前後だけを記述出来れば良い場合、相対表現と移動窓表現という2つの手法が使える。
- 相対表現
これは良く知られている。
特定の絶対値からの相対値として表現する。
位置座標とかには便利だが、時間には不便
時間は現在時刻が動いているからだ
- 移動窓表現
一般に知られていない。(注2)
通常、下位ワード値がそのまま記録される
ページングと似てる。(注3)
有限範囲を無限範囲の窓として見る。戦車のキャタピラのイメージ
その窓の範囲を指定する絶対座標を指定する
たとえば、西暦2桁で年を表現する。その範囲を絶対座標から前後50年とする。
- 絶対座標を2000とすれば 1950〜2049年がその範囲となる。
つまり00〜49は2000年代 50〜99は1900年代となる
- 絶対座標が2001年なら 1951〜2050年をその範囲とする。
つまり00〜50が2000年代 51〜99は1900年代となる
- 絶対座標がyear年ならyear-50〜year+49年をその範囲とする
00〜((year+50) MOD 100) 年が上位桁が同じ年
それより大きいなら過去の年だ。
- 予定情報なら 未来のデータしかない
絶対座標を予め40年くらい先に設定すれば良い。
- 結果情報なら 過去のデータしかない
絶対座標を逆に40年くらい前に設定すれば良い。
移動窓方式の実際のコード
2桁xx年をyyyy絶対年±50年に変換する
■pascal(delphi)
-
//理屈通りに書くと
function YYtoYYYY(xx,yyyy:integer):integer;
begin
xx := ( xx + 100 - ( yyyy mod 100 ) ) mod 100;
if xx>( 100 div 2 ) then xx := xx-100;
result := yyyy + xx;
end;
//3万年先迄使用出来れば十分ならばもっと簡単に
function YYtoYYYY(xx,yyyy:integer):integer;
begin
yyyy := yyyy - (100 div 2);
result := yyyy + ( (xx + 32000 - yyyy ) mod 100);
end;
■C
-
/* 理屈通りに移動窓をコーデングすると */
int YYtoYYYY(int xx,int yyyy)
{
xx=( xx + 100 - (yyyy%100) ) % 100;
if( xx > (100 / 2) ) xx -= 100;
return yyyy + xx;
}
/*3万年先迄使用出来れば十分ならば、*/
int YYtoYYYY(int xx,int yyyy)
{
yyyy -= 100/2;
return yyyy+ ( ( xx + 32000 - yyyy ) % 100 );
}
もし移動窓をchar(8bitなら -128〜+127)とすれば 非常に簡潔だ。
int yWtoYYYY(char yW,int yyyy)
{
char y8f = yW - yyyy;
return yyyy + y8f;
}
え?「この方法だと同じ 50って数字が 当年が2000年なら 1950年で 来年には2050年になるじゃないか」って?
それで問題あるかい? 問題あるなら最初から2桁ってのが間違いなんだよ。
誕生日の記録なら最初から2桁ってのが間違ってるよね? だって100才以上の人って大勢居るんだから
でも、製造日の記録なら、20年も同じ場所に保存される事はないでしょう?
せいぜい数年で、記録として別の場所に移される
そんな記録には年が2桁でも十分使えるし、使えたんじゃない。
え?「この方法だと大小比較出来ない」って?
そんな事はないよ。4桁年に変換してから比較すりゃいいし、差が小さければ移動窓で表現された値をモジュラ数として扱えばいいんだよ
YY年と XX年の差は ((YY-XX+100+50) mod 100)-50
とすれば求まる
2のべき乗の移動窓ならもっと簡単だ。mod を and で代用出来る。
char/int のようなサイズ丁度の移動ならもっともっと簡単だ。単に引算して判定すればいいだけだからね。
応用問題
MS/DOSのファイル日付の問題がある。 これは 7bitで 1980年からの日付を表現している。
少し前は、2079年でファイル日付はエラーになった。
さらに、MSDOSなら現在の所、2100年の日付には出来ない。
アプリ側ではこれはどうしようも無い問題として捨てても良いだろう。
しかし、それでも100年動かしたいと言われたら、日付管理を自分でするしかあるまい。
困った事に2000年は閏年だ。つまり100年日付を戻した場合、閏日を処理しなければならない。
パソコンの管理してる曜日との差から調整するような事が必要になるだろう。
本資料参照数 =