esspec

ECMAScript仕様輪読会 第97回 まとめ

1. 導入と新ツールの紹介

本編に入る前に、参加者同士でコードを共有・実行できる「同時編集プレイグラウンド(JavaScript版)」が紹介されました。

2. 読み進めている仕様のステータス

3. 前回内容の振り返り

前回は以下の内容が確認されました。


4. 今回読み進めた仕様

4.1. Date.prototype.toLocaleDateString / toLocaleString / toLocaleTimeString

これらのメソッドは国際化API(ECMA-402)との関連が深く、仕様上は以下のようになっています。

4.2. Date.prototype.toString

このメソッドは、Date.prototype.toJSONとは異なりジェネリックではありません

// 検証コード
const toStr = Date.prototype.toString;

// Dateインスタンスでないオブジェクトからの呼び出しはエラー
try {
  toStr.call({});
} catch (e) {
  console.log(e); // TypeError: Method Date.prototype.toString called on incompatible receiver
}

// Dateを継承したクラスはOK
class MyDate extends Date {}
console.log(toStr.call(new MyDate())); // 有効な日付文字列が返る

4.3. 抽象操作(Abstract Operations)の解読

Date.prototype.toString などの裏側で動く、文字列生成のアルゴリズムが詳しく読み解かれました。

ToZeroPaddedDecimalString(n, minLength)

数値を指定された長さでゼロ埋めした文字列に変換する共通処理です。

DateString(tv)

Www Mmm dd yyyy(例: Mon Jan 01 2024)という形式の文字列を生成します。

TimeString(tv)

HH:mm:ss GMT(例: 12:34:56 GMT)という形式を生成します。

TimeZoneString(tv)

タイムゾーンのオフセットと名前を生成します(例: +0900 (Japan Standard Time))。

ToDateString(tv)

Date.prototype.toString の実体となる操作です。


5. 検証と議論

ミリ秒の欠落とパース

Date.prototype.toString() の結果を Date.parse() で再度読み取った場合、ミリ秒単位で値が割り切れない(1000で割り切れない)Dateオブジェクトは、元の値と一致しなくなるという注意点が議論されました。

const d = new Date(1234567890123); // ミリ秒が123
const s = d.toString();
const parsed = Date.parse(s);

console.log(d.getTime() === parsed); // false (ミリ秒が削れるため)

※仕様書のノートには「1000で割り切れる(ミリ秒が0)場合は、パースした結果が一致する」と記載されています。

異常値の挙動

const d = new Date();
d.setFullYear(-1);
console.log(d.toDateString()); // "Sat Mar 22 -0001" (曜日は計算による)

6. 次回予告