30年のバグファイト

初版では、20年のバグが取り上げられました。 実際、彼は30歳です。 シドネキンに感謝します



今日、いくつかのデータを読み取って、私のプログラムは36,916の可能な日付を処理しました。 36,916のうち2つがテストに失敗しました。 これらの日付はクライアントから提供されたデータからのものであるため、私はこれを重要視しませんでした。そのようなデータはしばしば驚くべきものです。 しかし、ソースデータを見ると、2011年1月1日と2007年1月1日に検証がパスしなかったことがわかりました。1か月前に書いたプログラムにバグがありました。 しかし、このバグは30年前のものであることが判明しました。



ソフトウェアエコシステムを実際に理解していない人にとっては、以下の文章は奇妙に思えますが、それは理にかなっています。 昔、ある会社にお金を持ち込むという決断があったため、私の$クライアントは、ある会社が誤って、別の会社が作ったバグを修正するためにお金を払ってくれました。 これを説明するには、最終的にバグになった機能を追加した3番目の会社と、今日修正した不可解なバグに影響を与えた他のいくつかの事実について話さなければなりません。



古き良き時代には、Appleコンピューターは1904年1月1日に日付をリセットすることがありました。 その理由は簡単です。当時、Appleコンピューターはバッテリー駆動のシステム時刻使用して日付と時刻を追跡していました。 バッテリーが少なくなったときに何が起こりましたか? Appleコンピューターは、時代の始まりから経過した秒数として日付をカウントしました。 この場合の時代は、単にカウントダウンの開始日です。 Appleコンピューターの場合、その日付は1904年1月1日でした。 バッテリーが切れると、この数字は新しい日付になりました。 しかし、なぜこれが本当に起こったのでしょうか?



当時、Appleは32ビットを使用して、開始日からの秒数を保存していました。 1ビットには2つの値(0または1)を含めることができます。2ビット-4つの値:00、01、10、11。3ビット-8つの値:000、001、010、011、100、101、110、111など。 。 32ビットにはいくつの値が含まれていますか? 32ビットには2 32 (または4'294'967'296)値が含まれます。 Appleの日付の場合、これは約136年前であったため、 古いAppleコンピューターは2040年以降の日付で動作できず 、システムクロックのバッテリーが切れると、日付は再び0秒後になり、コンピューターをオンにするたびに現在の番号を手動で設定する必要がありました(新しいバッテリーを購入する前)。



しかし、時代を過ぎた秒数として日付を保存するためのAppleのソリューションは時代まで日付を保存することができなかったことを意味していました。 後で見るように、これは広範囲にわたる結果をもたらしました。 これは、Appleによって追加された機能であり、バグではありません。 とりわけ、これはMacintoshオペレーティングシステムがY2K問題の影響を受けないことを意味します(多くのMacプログラムは、Macの制限を回避する独自の日付を持っていたため、そうではありませんでした)。



続いて、 Lotus 1-2-3に出会います。Lotus1-2-3は、PC革命の立ち上げに貢献したキラーIBMアプリケーションですが、AppleのVisiCalcは実際にパーソナルコンピューターを生み出しました。 1-2-3でなければ、PCはニッチとコンピューターテクノロジーをまったく別の方法で開発しなかった可能性が高いと言えます。 ただし、Lotus 1-2-3は1900年のうるう年を誤って考慮していました。 Microsoftが最初のスプレッドシートプログラムであるMultiplanをリリースしたとき、市場を征服することはできませんでした 。 そのため、Excelを開発する際、Lotus 1-2-3から列の命名規則をコピーするだけでなく、1900年からのap年としての意図的な処理など、製品をバグに完全に対応させることも決定されました。 以来 したがって、1-2-3の場合、これはバグでしたが、Excelの場合、1-2-3のすべてのユーザーがスプレッドシートをExcelにインポートできることを保証する機能でした。



時間が経つにつれて、MicrosoftはApple Macintosh用のExcelをリリースすることにしましたが、問題がありました。 すでに述べたように、Macintoshは1904年1月1日まで日付を理解できませんでした。Excelの場合、時代は1900年1月1日でした。 そのため、Excelは時代を認識し、対応する時代に関連する日付を保存するように調整しました。 マイクロソフトのサポート記事で、この問題は非常に明確に説明されています。 そしてそれは私のバグにつながります。



私の現在の$クライアントは、彼の多くのクライアントからスプレッドシートを受け取ります。 これらのテーブルは、Windowsで作成することも、Macで作成することもできます。 結果として、これらの表の時代は1900年1月1日または1904年1月1日です。 どれを見つけるには? Excelのファイル形式はそのような情報を保存しますが、 私が使用するパーサーはそれを提供せず、このファイルでどの時代を扱っているかをあなた自身が知っていると信じています。 おそらく、Excelバイナリ形式を読み取ってパッチを開発者に送信する方法を見つけるのに長い時間を費やすべきでしたが、$クライアントに対して他にやることがあったので、このファイルがどの時代に属しているかを判断するためのヒューリスティックを作成しました。 彼女はシンプルでした。



Excelでは、たとえば1998年7月5日に保存できますが、この番号は「07-05-98」(役に立たないアメリカ形式)、「Jul 5、98」、「July 5、1998」、「5-JUL- 98」および多くの無駄なオプション(皮肉なことに、私のバージョンのExcelが提供していない唯一の形式はISO 8601です)。 内部では、フォーマットされていない値は、1900年の時代では35981、1904年の時代では34519です(これらの数値は、その時代から経過した日数に対応しています)。 永続的なパーサーを使用して、書式設定された日付から年を抽出しました。 そして、書式なしの値から年を抽出するExcelパーサー。 それらが4つ異なる場合、ファイル内の日付は1904年から考慮されました。



書式設定された日付をすぐに使用しないのはなぜですか? 1998年7月5日は1998年7月としてフォーマットできるため、1日が失われます。 私たちは非常に多くの企業からスプレッドシートを入手し、彼らは私たち(この場合は )に理解する能力を期待する非常に多くの異なる方法でそれらを作成します。 Excelは何を理解しているので、私はしなければなりません!



それは39082であり、私にプッシュを与えました。 ロータス1-2-3が1900年のうるう年をどのように考慮し、どのように正直にExcelにコピーしたかを覚えていますか? これにより1日が1900に追加されるため、多くの日付計算関数が1日間間違っている可能性があります。 つまり、39082 2011年1月1日(Macの場合)、2006年12月31日(Windowsの場合)になる可能性があります。 もちろん、パーサーがフォーマットされた値から2011を抽出するのは素晴らしいことです。 しかし、Excelパーサーはこのファイルの日付がどの時代から計算されているかを知らないため、デフォルトでは1900年であるとみなし、2006年を返します。値。



これを回避するために、次の(擬似コード)を思い付きました。



difference = formatted_year - parsed_year if ( 0 == difference ) assume 1900 date system if ( 4 == difference ) assume 1904 date system if ( 5 == difference and parsed month is December and parsed day is 31 ) assume 1900 date system
      
      







現在、36'916の日付はすべて正しく解析されています。



:楽しみのために、Excelを搭載したMacをお持ちの場合は、1904年より前の日付を入力して別の形式でフォーマットしてみてください。 入力することはできますが、Excelではプレーンテキストと見なされるため、書式設定することはできません。 同時に、Microsoft Excelの場合、1983年1月にリリースされたプログラムのバグにより、1900年3月1日までのすべての曜日が正しくありません。



更新Spreadseet :: ParseExcelは1904フラグを理解していると言われました 。 残念ながら、私は理解できないスプレッドシート:: ParseExcel ::ストリームを使用しています。 巨大なマシンであっても、標準のパーサーを使用するときには十分なメモリがないため、ストリーミングを使用します。 この制限を回避しようとする私の試みは別のバグに出会いました。



更新2MicrosoftがMacintosh用のExcelを最初にリリースしたことが判明しました



更新3Joel Spolskyよると 、Lotus 1-2-3のバグは、プログラムを単純化するための意図的な試みである可能性があります。 私は以前、ロータスが意図的にそれをしたことをほのめかしていましたが、100%確信がないので、それについては書きませんでした。



All Articles