プロンプトとコンテキスト
グローバルな予約システムが「ニューヨーク時間 2026-11-01 01:30」を受け取り、参加者それぞれのタイムゾーンで表示および通知を行います。JavaScript Temporal を使用して、夏時間の移行時における存在しない現地時刻や重複する現地時刻を処理しながら、パース、タイムゾーンのバインド、永続化、表示を設計してください。日付、時刻、タイムゾーンのセマンティクスを1つの文字列や Date オブジェクトにまとめて潰さないでください。
面接官がテストしていること
評価のポイントは、Temporal.Instant、Temporal.ZonedDateTime、Temporal.PlainDateTime、および Temporal.PlainDate の区別、IANA ルール、DST の曖昧さ、精度、シリアライズの理解です。優れた回答では、ビジネス上のカレンダー日付がなぜ自動的に UTC インスタントにならないのか、そしてカレンダーシステムをどのように保持するかを説明します。
最初に確認すべき明確化のための質問
入力のセマンティクス
入力が名前付きタイムゾーンにおける壁時計時刻なのか、すでに解決されたインスタントなのか、そしてそのタイムゾーンがイベント、組織、ブラウザのどれに由来するのかを確認します。タイムゾーンがなければ、現地時刻は曖昧になります。
DST の曖昧さに関するポリシー
存在しない時刻や重複する時刻を拒絶するのか、早い方または遅い方を選択するのか、あるいは確認を要求するのかを尋ねます。このポリシーは製品の仕様(コントラクト)に属するものであり、ランタイムの偶発的なデフォルトに任せるべきではありません。
永続化の要件
リマインダーが単一の絶対的なインスタントなのか、現地カレンダーで毎年繰り返されるものなのかを特定します。1回限りの予約と誕生日のようなルールでは、異なる Temporal の型が必要です。
30秒の回答フレームワーク
「ユーザー入力を PlainDateTime と明示的な IANA タイムゾーンとして保持し、製品のポリシーを適用して ZonedDateTime と Instant を作成します。1回限りのリマインダーには Instant を永続化し、表示時に各閲覧者のタイムゾーンに変換します。定期的なイベントには、現地の日付、時刻、タイムゾーン、カレンダールールを永続化します。DST の曖昧さ解消を明示的に拒否または選択し、元のセマンティクスを保持します。Date の暗黙的なローカルゾーンのパースは避けます。」
ディープダイブ回答ステップ
ステップ 1: 正しい型を選択する
PlainDate はタイムゾーンのないカレンダー日付、PlainDateTime はタイムゾーンのない壁時計の日付と時刻、ZonedDateTime は IANA タイムゾーンをバインドしたもの、Instant はタイムライン上の1点です。まずはビジネス上の意味から型を選択します。
ステップ 2: パースしてタイムゾーンをバインドする
ユーザー入力をパースして PlainDateTime にし、信頼できるタイムゾーン識別子を取得して、それらを組み合わせて ZonedDateTime にします。ブラウザやサーバーのデフォルトのタイムゾーンをイベントのタイムゾーンとして暗黙的に使用してはなりません。
ステップ 3: DST の移行を処理する
春の進み(Spring-forward)は存在しない現地時刻を生み出し、秋の戻り(Fall-back)は重複する現地時刻を生み出します。拒絶してユーザーに再確認する、あるいは要件で許可されている場合は早い方/遅い方を選択するなど、明示的な曖昧さ解消を適用します。その選択を予約情報とともに記録します。
ステップ 4: リマインダーのインスタントに変換する
1回限りの予約の場合は、ZonedDateTime から Instant を取得し、正規化された文字列を永続化します。Instant によってスケジュールを設定し、元の壁時計テキストを再解釈するのではなく、表示時にのみ閲覧者のタイムゾーンに変換します。
ステップ 5: 定期イベントのセマンティクスを保持する
現地時刻 09:00 の年次イベントは、DST によってオフセットが変化するため、単一の UTC オフセットとして保存することはできません。PlainDate、PlainTime、IANA タイムゾーン、カレンダーシステムを永続化し、発生ごとに新しい ZonedDateTime を解決します。
ステップ 6: 精度とカレンダーを定義する
ミリ秒、マイクロ秒、ナノ秒のいずれが必要かを指定します。シリアライズ時に切り捨てて順序を壊さないようにします。非 ISO のビジネスカレンダーの場合は、その日付を ISO 日付として扱うのではなく、カレンダー識別子を永続化します。
ステップ 7: 境界値をテストする
春の進みと秋の戻り、年の境界、うるう日、タイムゾーンデータベースの更新、ロケールの違い、シリアライズのラウンドトリップをカバーします。文字列の比較のみに頼るのではなく、インスタント、ローカル表示、繰り返しルールを個別にアサートします。
高品質な回答サンプル
入力を PlainDateTime としてパースし、IANA タイムゾーンを必須とし、明示的な DST ポリシーを適用して ZonedDateTime を作成します。1回限りのリマインダーには Instant を永続化して閲覧者ごとに変換し、繰り返しの場合は現地の日付、時刻、タイムゾーン、カレンダールールを永続化して毎回新しいインスタントを解決します。テストでは、存在しない時刻や重複する時刻、うるう日、タイムゾーンデータベースの更新、精度をカバーします。これにより、Date の暗黙的なタイムゾーン動作を回避できます。
よくある間違い
- 間違い:
PlainDateTimeを UTC として扱う。 → 理由: タイムゾーンのセマンティクスがありません。 → 改善策: まず明示的な IANA タイムゾーンをバインドします。 - 間違い: 年次イベントに対して UTC オフセットのみを永続化する。 → 理由: DST によって現地オフセットが変わります。 → 改善策: 現地時刻とタイムゾーンルールを永続化します。
- 間違い: 秋の戻りによる重複時刻を無視する。 → 理由: 1つの壁時計時刻が2つのインスタントにマッピングされます。 → 改善策: 拒絶するか、明示的に早い方/遅い方を選択します。
- 間違い: 文字列の一致のみを検証する。 → 理由: 文字列はインスタントやカレンダーのセマンティクスを証明しません。 → 改善策: Instant、ZonedDateTime、および繰り返しの動作を個別にアサートします。
フォローアップの質問と回答
フォローアップ 1: Instant を永続化すべきなのはどのような場合ですか?
リマインダーの送信や支払いの記録など、イベントがタイムライン上の1つの絶対的な発生を意味する場合です。閲覧者のタイムゾーンは表示を変更するだけであり、インスタント自体は変更されません。
フォローアップ 2: なぜ誕生日を Instant として保存すべきではないのですか?
誕生日は現地のカレンダー日付であり、通常は世界全体で同時発生する1つのインスタントではないためです。日付、タイムゾーン、カレンダールールを保存し、発生ごとにインスタントを計算します。
フォローアップ 3: タイムゾーンデータベースの更新は保存された予約に影響しますか?
はい。将来の現地時刻のルールが変更される可能性があります。元のタイムゾーンとセマンティクスを保持し、必要に応じてルールバージョンを記録し、再計算の処理方法を定義してください。
フォローアップ 4: Temporal は DST の曖昧さを自動的に決定しますか?
API は曖昧さ解消のオプションを提供しますが、拒絶、早い方、遅い方、または互換性動作のどれにするかはプロダクト側で選択する必要があります。デフォルトのオプションはビジネスポリシーではありません。