Upgrade to Pro — share decks privately, control downloads, hide ads and more …

It’s “Time” to use Temporal

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Saji Saji
March 16, 2026

It’s “Time” to use Temporal

Avatar for Saji

Saji

March 16, 2026
Tweet

More Decks by Saji

Other Decks in Technology

Transcript

  1. ⚠ 注意 ⚠ • 個人の主張・予測・思想がそれなりに含まれます ◦ みんなの意見もぜひ聞きたい • Temporalの全体像を話すというわけではない ◦

    自分が大事だと思ってるところ(好きな所)をひたすら話す感じです • Temporalの基礎的な話はスキップしてる ◦ ほぼ英語版しかないけどMDNがすごく詳しい(読み物としても👍)
  2. JSのDateがつらいこと • システム以外のタイムゾーン(サマータイム)サポートがない ◦ UTC ↔ システムタイムゾーン しかできない (しかも変換が暗黙的) •

    日時文字列のパース動作の信頼性が低い ◦ 渡す文字列によってタイムゾーン解釈が変わる・そもそも環境差がある • 日付オブジェクトの可変性の問題 ◦ set系のメソッドで書き換えられてしまう • 日時計算が行いづらい ◦ 加減算や比較ですら一旦値を取り出す + Setし直しという工程が発生
  3. Temporalで解決すること • IANAで管理されているタイムゾーン全てに対応 ◦ システムのタイムゾーン以外でも自由に変換できる • パースできる文字列・数値を厳密化 ◦ RFC3339 とその拡張であるIXDTFだけに限定

    • immutableなAPI ◦ 計算後は新しいTemporalのオブジェクトを返す • 基礎的な日時計算メソッドの搭載 ◦ 日時の加減算や比較などは標準で搭載するようになった
  4. 今回のテーマ Temporalで • 変わること / 変わらないこと • Scopeじゃないこと / まだできないこと

    を考えることで Temporal Native 時代の解像度が上がる そこから自ずとどう使っていくべき か、どう移行する かが分かってくる
  5. タイムゾーンのデータはExactTimeとWallClockTime の橋渡しで必要 • 逆にそこの橋渡しをしない場合は必ずしも必要ないなる 暦の指定は WallClockTime を明確化するのに必要 • 暦が確定できないと WallClockTime

    で示しているデータの意味が変わる • 例 : 2026年1月28日 ◦ 中国で使われる旧暦の場合 → 2026年3月16日(グレゴリオ暦) タイムゾーンと暦を指定するところ
  6. Temporalによる整理 WallClockTime vs ExactTime の分離 • WallClockTIme : Teporal.PlainXX という名前のクラス

    • ExactTime : Temporal.Instant これらの2つは Temporal.ZonedDateTimeで橋渡しされ、変換できる
  7. Temporalによる整理 PlainXX という命名のClassたち = WallClock Time • PlainDateTime : 特定の年月日時刻のデータ

    • PlainDate : 時刻のデータを持たない日付だけのデータ • PlainTime : 日付のデータを持たない時刻だけのデータ • PlainMonthDay : 特定の月と日だけのデータ • PlainYearMonth : 特定の月(年と月だけ)のデータ
  8. 型 = 意味 = 振る舞い が違う もちろんデータの型と意味が違うと言うことは • 生えているプロパティ・メソッドも違う ◦

    例 : PlainMonthDay にyearは生えていない • 生成時や変換時の制約も違う ◦ 生成に必要なデータ・補完されるデータもが違う ◦ 変換で求められるデータ・補完されるデータが違う
  9. 日時の扱いを考え直すところから 「日時」と言う安易な一言で本来異なるものを一括りにしてなかったか? • Dateを使ってる限りは「日時? → Dateにしとけ」で済ましていた ◦ (で、痛い目を見ていた ) •

    違うものを一緒にしてたらそりゃうまくいかない この考え方を変えない限りTemporalにする旨みは活かせない • TemporalでどのObject / API を使うべきか選べない
  10. Temporalだと... それぞれ • データベースに保存する更新タイムスタンプ → Instant / Now • 日時入力フォームに入力された日時

    → PlainDateTime • ユーザーの生年月日 → PlainDate • カレンダーで表示してる月 → PlainYearMonth
  11. 入力と保持するデータ ユーザーが入力するのは基本WallClockTime (= PlainXX) 保存する時を考えると... • 一瞬を表しているもの → タイムスタンプで保存したい ◦

    大抵 PlainDateTime → ZonendDateTime → timestampに変換でいける ◦ 逆もまた然り • 特定の一瞬を表してない → 別途違うフォーマットで保存する ◦ PlainDate / PlainYearMonth → 文字列に変換とかが安全そう
  12. よくありそうなデータの変換 ローカルな日時 → タイムスタンプで保存したい const inputDateTime = Temporal.PlainDateTime.from('2026-03-16T10:00:00'); const zonedDateTime

    = inputDateTime.toZonedDateTime('Asia/Tokyo'); const instant = zonedDateTime.toInstant(); console.log(instant.epochMilliseconds); // 1773622800000
  13. よくありそうなデータの変換 タイムスタンプ → ローカルでの解釈 const savedTimestamp = 1773622800000; const instant

    = Temporal.Instant.fromEpochMilliseconds(savedTimestamp); const zonedDateTime = instant.toZonedDateTimeISO('Asia/Tokyo'); const plainDateTime = zonedDateTime.toPlainDateTime();
  14. 特定の一瞬じゃないデータの保存 案 : そのまま toStringした値を保存してしまうのが良い? • 変にInstant化するとタイムゾーンでずれるミスをしたりすることも • どうせTemporal の

    fromメソッドで復元できる const birthday = Temporal.PlainDate.from('1988-09-20'); const dbValue = birthday.toString(); console.log(dbValue); // '1988-09-20' const restored = Temporal.PlainDate.from(dbValue);
  15. 閑話 : 自分のいるチームでは Dateでの値の保存・やり取りを非推奨にしてる (内部的には仕方ないが) 代わりに文字列ベース(+それらを持つObject)のBrandedTypesを導入 • 基本の4つ : UTCISOString

    / DateString / TimeString / LocalDateTimeObject • それぞれ Temporalの Instant / PlainDate / PlainTime / PlainDateTime に対応 常に「この日時データはどれ?」ということを意識させる
  16. Temporalが受け入れる文字列は厳密にRFC3339/IXDTFとその部分文字列だけ • 2026-03-16T19:00:00.00000000+09:00[Asia/Tokyo] Dateのように曖昧なParse挙動はなくなった • Parseできない : “Mon Mar 16

    2026 19:00:00”,“2026/3/16 19:00” 逆にいうとParseの機能は限定的になったとも言える • ややこしいよりは全然いいけど parseはより厳密で限定的に
  17. Temporalの話とはズレるので深入りしないが、日時のformatはとてもややこしい • 日時表記として / 文法的におかしい形にformatできてしまう可能性 • ライブラリでformatPattern文字列の仕様あんまり守れてない問題 • そもそも formatPatternを正しく使うの知識いる問題

    • 参照するデータが現地のユースケースをちゃんと反映できるか問題... ↑ みたいなことを考え出すと本当に面倒なのでIntlで済むならそれが一番 日時のformatって複雑で ...(早口)
  18. メソッドチェーン形式だと大変そう • dateX(date).setYear(2026).toUTCString() date-fns みたいな関数合成パターン + 各関数の引数の型を制限 / 引数から推論 •

    formatUTCISOString(addDays(plainMonthDay,9)) ライブラリの Temporalサポート(想像) PlainMonthDay だったら? TimeZone情報 まだないよ? PlainMonthDayは 渡せないよ!