投稿日:2024年1月24日

何やら訳の分からないタイトルでスミマセン。
2038年問題とは、

2038年1月19日3時14分7秒(UTC、以下同様)を過ぎると、コンピュータが誤動作する可能性があるとされる年問題。
ウィキペディアより引用

「日本標準時では2038年1月19日12時14分7秒。閏秒は考慮してない」とも記載されています。

2038年問題は32bitのコンピューターの使用が起因とされますが、取り巻く環境はほぼ64bitのものばかり。
しかも、JavaScriptにおいては起こらないと紹介しているページもありました。

何が起こったかというと、前回の記事 で紹介した下記のJavaScriptのタイマー設定の記述。

let nowTime = new Date(); // 現在時刻を取得
let setTime = new Date("2024/01/21 10:12:40"); // 指定する時刻
let resultTime = setTime - nowTime; // 指定する時刻 - 現在時刻(ミリ秒)
if (resultTime > 0) { // 指定する時刻 - 現在時刻が0より大きい場合
  setTimeout(function () {
    location.reload();
  }, resultTime); // 指定する時刻 - 現在時刻秒後にリロード
} else {
  $("h1").css("color", "red");
}

指定する時刻 - 現在時刻 が、2038年問題でとりあげている「2147483647」を超えると挙動がおかしくなります。
厳密には「2147483647.999」では大丈夫で、「2147483648.000」だと起こります。

▲このように何回もリロードします。
例えば、下記だと起こりません。

setTimeout(function () {
   location.reload();
}, 2147483647); 

しかし、下記だと起こります。

setTimeout(function () {
   location.reload();
}, 2147483648); 

なんででしょうね?

さらにググったらMDN に以下のような記事を見つけました。

最大の遅延時間
Internet Explorer、Chrome、Safari、Firefox を含むブラウザーは、内部で遅延時間を 32 ビット符号付き整数値で保存します。このため 2,147,483,647 ms (約 24.8 日) より大きな遅延時間を使用すると整数値がオーバーフローして、その結果直ちに実行されるタイムアウトになります。

結局のところ2038年問題と何か関係があるのか? と疑問に思いつつ以下のようなものを作ってみました。

 仕様

ページを開いたときに現在日時を秒単位で表示します。
設定日時は秒単位で入力できます。
「日時確認」ボタンをクリックすると「現在日時」 – 「設定日時」を計算します。
「設定日時」が空だと「設定日時を入力してください。」と表示します。
「設定日時」が過去だと「現在時刻より未来の日時を入力してください。」と表示します。
「現在日時」 – 「設定日時」の差が2147483647以内だったら「問題なく設定できます。」と表示します。
「現在日時」 – 「設定日時」の差が2147483648以上だったら、設定可能な開始日時設定可能な下限を表示します。

まとめ

昨年作ったプログラムを流用したのですが、上に書いたようにリロードが続き無限ループに陥りました。

「JavaScript 数値 最大値」などでググるとヒットするNumber.MAX_SAFE_INTEGER定数
これによると9007199254740991がJavaScriptで扱える最大値になります。
9007199254740991がJavaScriptで扱える最大値と言っておきながら、setTimeoutでは2147483647が最大値という、少々納得できない結論に至っています。

Webの仕事に就いてから6年目。
まだまだ知らないこともあります。
引き続き精進したいと思います。

最後までお読みいただき、ありがとうございます。

Pocket