
2026/01/13 0:20
「Date は使用不可、Temporal が有効です。」
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
JavaScript のネイティブ
Date オブジェクトは、月をゼロインデックスで解釈したり、2 桁の年(例:「49」が 2049 年になる、一方「99」は 1999 年、「100」は 0100 年)と誤認したり、区切り文字(スラッシュ vs ハイフン)によって日付をシフトさせたりするなど、混乱しやすく可変です。タイムスタンプを保持し、セッターで自身を変更するため、再利用された Date は隠れた副作用を引き起こします。新しく提案された Temporal API は、これらの問題を解決するために、イミュータブルなクラス(PlainDate、PlainDateTime、ZonedDateTime)を提供します。.add() や .subtract() のような操作は元のオブジェクトを変更せず、新しいオブジェクトを返すため、偶発的なミューテーションが排除されます。Temporal は適切なタイムゾーン処理も備え、夏時間規則に対応し、グレゴリオ暦とともに動作するため、Date が無視している問題を解決します。ECMAScript の計画機能として、開発者は手動での Date 操作から Temporal の明確かつイミュータブルな API への移行が推奨されます。これにより Web アプリケーションの信頼性が向上し、不意のミューテーションや誤ったタイムゾーンによるバグが減少し、業界全体で最新の JavaScript 標準が促進されます本文
時間は私たちをすべて馬鹿にします、そして JavaScript もその点では決して例外ではありません。
正直なところ、後者についてはあまり気にしていません――JavaScript for Everyone を読んだり、ニュースレターを購読したりしているなら、私は実際には JavaScript のちょっとした奇妙さを大好きであることをご存知でしょう。
「縫い目が見える」ことが好きです。ES‑262 仕様はフォーマルで鉄壁に見えても、もし見るべき場所を知っていれば、言語を構築し続けている何百人もの人々が下した良い決定と悪い決定のすべてを見ることができる。JavaScript にはキャラクターがあります。もちろん、期待通りに全てが動くわけではありませんが――そうですね、もし私を聞けば、JavaScript は知れば知るほど本当に魅力的です!ただ、その魅力は言語のある部分ですぐに崩れ去ってしまいます。
// 数値月は 0 インデックスですが、年と日付はそうではありません: console.log( new Date(2026, 1, 1) ); // 結果: Date Sun Feb 01 2026 00:00:00 GMT-0500 (Eastern Standard Time) // 「32」〜「49」の数値文字列は 2000 年代とみなされます: console.log( new Date("49") ); // Fri Jan 01 2049 // 「33」〜「99」の数値文字列は 1900 年代とみなされます: console.log( new Date("99") ); // Fri Jan 01 1999 // …しかし「100」以上は年ゼロから始まります: console.log( new Date("100") ); // Fri Jan 01 0100 // 文字列ベースの日付は期待通りに動作します: console.log( new Date("2026/1/2") ); // Fri Jan 02 2026 console.log( new Date("2026/02/2") ); // Mon Feb 02 2026 console.log( new Date("2026-02-2") ); // Mon Feb 02 2026 console.log( new Date('2026/01/02') ); // Fri Jan 02 2026 // ただし、年・月・日をハイフンで区切る場合は… console.log( new Date('2026-01-02') ); // Thu Jan 01 2026
Date は本当に嫌いです。車で学校へ向かう途中に Java の宿題から無理やりコピーされ、同じ誤答がそのまま残されたようなものです。「Date」という名前自体が誤解を招きます――日付ではなく「時刻」を表すのです。内部的には、Date は 1,000 ミリ秒単位で分割された Unix タイムスタンプ(数値)として保存されます。Unix 時間は日付を暗示しますが、それでも:Date は時刻を表し、その時点から日付を推測できる――それはひどいです。
// 1995 年 12 月 4 日午前 0:00:00 GMT‑05(JavaScript が発表された日)の Unix タイムスタンプ: const timestamp = 818053200; console.log( new Date(timestamp * 1000) ); // Mon Dec 04 1995 00:00:00 GMT-0500
「日付」や「時刻」といった言葉は意味を持ちますが、JavaScript はそのままです。
Java は 1997 年に
Date を非推奨としました――JavaScript の Date が世の中に放たれた数年後。以来、この混乱を抱えてきました。
これらは私が
Date に対して抱く主な問題ではありません。私の不満は、単なるパースや構文、あるいは「開発者エルゴノミクス」ではなく、魂に関わるものです。Date を使うということは、時間そのものの根本的性質から逸脱することを意味します。
JavaScript のプリミティブ値はすべて不変
数値・真偽値・文字列など、すべては値として保存されます。作成後に変更できません。
const theNumber = 3; console.log(theNumber); // 3 let theOtherNumber = theNumber; theOtherNumber = 5; console.log(theOtherNumber); // 5 console.log(theNumber); // 3
一方、配列・マップ・セットなどのオブジェクト値は可変です。変数はプリミティブかオブジェクトへの参照を保持できます。
const theObject = { theValue: 3 }; theObject.theValue++; // 4 const theOtherObj = theObject; theOtherObj.theValue++; // 5 console.log(theObject.theValue); // 5
これが
Date に関係します。Date はオブジェクトを生成するコンストラクタで、不可避的に可変データ構造です。
const theDate = new Date(); console.log(typeof theDate); // "object" theDate.setMonth(10); console.log(theDate.toDateString()); // Sun Nov 30 2025
したがって
Date インスタンスを保持している変数は、変更可能なオブジェクトへの参照です。次の例を見てください。
const today = new Date(); const addDay = theDate => { theDate.setDate( theDate.getDate() + 1 ); return theDate; }; console.log(`Today is ${today.toLocaleDateString()}, tomorrow is ${addDay(today).toLocaleDateString()}.`);
today と addDay が返す値は同じ可変オブジェクトを指しています。結果として「今日」が「明日」になってしまいます。この副作用は微妙ですが危険です。
Temporal:Date
の代替
DateTemporal はコンストラクタではなく、名前空間オブジェクトです。
const today = new Temporal(); // ❌ TypeError: Temporal is not a constructor
代わりに
Temporal は組み込みの Math オブジェクトのように振る舞います――静的プロパティとメソッドを持つ単なるオブジェクトです。
console.log(Temporal); /* Result (expanded): Temporal { … } Duration: function Duration() Instant: function Instant() Now: Temporal.Now { … } PlainDate: function PlainDate() … */
現在の日付を取得
Temporal.Now.plainDateISO() は YYYY-MM-DD の形式で日付のみのオブジェクトを返します。
const nowTemporal = Temporal.Now.plainDateISO(); console.log(nowTemporal); // Temporal.PlainDate 2025-12-31
new Date() と違い、時間成分はありません。
日付の操作
Temporal オブジェクトに対するすべての変更操作は 新しいオブジェクトを返し、元のものは変更されません。
const today = Temporal.Now.plainDateISO(); console.log(today.add({ days: 1 })); // 2026-01-01 console.log(today.add({ months: 1, days: 1 }).subtract({ years: 2 })); // 2024-01-31 // 元のオブジェクトは変わらない: console.log(today); // 2025-12-31
Temporal オブジェクト自体は可変(任意のプロパティを追加できます)が、ビルトインメソッドは日付値を変更しません。
「Today is X, tomorrow is Y」を書き直す
Date ではヘルパー関数内で新しいインスタンスを作成する必要がありました。
const today = new Date(); const addDay = theDate => { const tomorrow = new Date(); tomorrow.setDate(theDate.getDate() + 1); return tomorrow; }; console.log(`Tomorrow will be ${addDay(today).toLocaleDateString()}. Today is ${today.toLocaleDateString()}.`);
Temporal を使えば、1 行で完結します。
const today = Temporal.Now.plainDateISO(); console.log(`Tomorrow will be ${today.add({ days: 1 })}. Today is ${today}.`);
結論
Temporal は JavaScript にモダンかつ不変に近い日付処理をもたらします。Date の奇妙さを排除し、操作とフォーマットのための明確な API を提供し、偶発的な副作用をなくします。まだドラフト(ステージ 3)ですが、最新ブラウザで既に利用可能です。正式実装が完成する前にぜひ試してみてください。
使ってみる:
const today = Temporal.Now.plainDateISO(); const jsShipped = Temporal.PlainDate.from("1995-12-04"); const sinceDate = today.since(jsShipped, { largestUnit: 'year' }); console.log(`${sinceDate.years} years, ${sinceDate.months} months, and ${sinceDate.days} days.`);
やがて JavaScript は合理的でモダンな日付処理を手に入れます。古い
Date は棚の奥にしまい、日付を扱う際の第一選択肢ではなくなるでしょう。