Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
書き換えて学ぶTemporal #fukts
Search
Hiroyuki ANAI
May 07, 2026
Programming
390
2
Share
書き換えて学ぶTemporal #fukts
https://fukuoka-ts.connpass.com/event/387858/
Hiroyuki ANAI
May 07, 2026
More Decks by Hiroyuki ANAI
See All by Hiroyuki ANAI
fukuoka.ts #3 社内でESLintの共通設定を配りたい2025年春版
pirosikick
3
470
compilerOptions、全部読んだ
pirosikick
1
280
Step Functionsの設計時に知っておいたほうがいいかもしれないこと
pirosikick
0
520
Go言語による並行処理「4.4 orチャネル」の図
pirosikick
0
470
サイボウズWebフロントエンド脱レガシーの今までとこれから
pirosikick
6
17k
@cybozu/eslint-configから学ぶ、全社共通ESLint configの運用
pirosikick
4
1.9k
Web Share Target API #w3fukuoka
pirosikick
0
730
Google I/O '19のWebをまとめる会
pirosikick
2
890
PuppeteerでいらないCSSを消す
pirosikick
23
29k
Other Decks in Programming
See All in Programming
開発とはなにか、Essenceカーネルで見えるもの
ukin0k0
0
200
Zod v4 Codec でスキーマに型変換を埋め込む REST API 設計 #TSKaigi2026
ryutaro_yako
0
100
横断組織出身のQAEがインプロセスQAEでつまずいたこと・活かせたこと
ty89
0
170
要はバランスからの卒業 #yumemi_grow
kajitack
0
190
Modding RubyKaigi for Myself
yui_knk
0
390
Agent Skills を社内で育てる仕組み作り
jackchuka
1
2.3k
開発体験を左右するライブラリの API 設計 - GraphQL スキーマ構築ライブラリから考える #tskaigi
izumin5210
2
370
Moments When Things Go Wrong
aurimas
3
100
iOS26時代の新規アプリ開発
yuukiw00w
0
180
Cloudflare で始める Data Platform
ta93abe
0
210
[BalkanRuby 2026] Drop your app/services!
palkan
3
630
Transactional Change Stream Processing With Debezium and Apache Flink
gunnarmorling
1
120
Featured
See All Featured
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
65
54k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
180
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Context Engineering - Making Every Token Count
addyosmani
9
900
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.2k
The Cost Of JavaScript in 2023
addyosmani
55
9.9k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
570
The browser strikes back
jonoalderson
0
1.1k
Building AI with AI
inesmontani
PRO
1
1k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
65
55k
Transcript
書き換えて学ぶTemporal 2026-05-07 fukuoka.ts #4 @pirosikick
自己紹介 © LayerX Inc. @pirosikick / 穴井宏幸 株式会社LayerX バクラク勤怠のソフトウェアエンジニア 趣味:
プロ野球観戦 今年のホークス、みんなどう思うか? 2
今日の話 © LayerX Inc. 「Temporal?Dateの進化版ね」くらいの理解から進んでいない Stage 4になったし、 バクラク勤怠という日付・時刻を扱うプロダクトに関わっているので、 重い腰を上げてちゃんと向き合うぞ!という話 3
先に結論 © LayerX Inc. APIが豊富: 勤怠管理という日付・時刻を扱うドメインでも十分 APIが直感的: 統一感があり、ちょっと書けばしっくりくる 型が豊富: コードの意図が明確に
Stage 4になったし、乗り換え待ったなし 4
目次 © LayerX Inc. 今日の話 Date のつらさ Temporal とは バクラク勤怠のコードを書き換えてみる
基礎編 応用編 気づき 5
Date のつらさ
Dateのつらさ © LayerX Inc. Dateのつらさ タイムゾーンの扱い システムのローカル or UTC ミュータブル
パースが微妙 new Date("2026-05-07") はUTC、 new Date("2026/05/07") はローカル時刻 月だけが0始まり(1月 → new Date(2026, 0, 1) ) APIが貧弱 ⋯ etc 7
Dateの仕様 © LayerX Inc. Dateのつらさ ES5で少し機能追加されたが、ベースの部分は初期から変わってない 短い設計期間の中で、Java 1.0の java.util.Date をそのままコピー
8
Temporalとは
Temporalとは © LayerX Inc. Temporalとは ECMAScript の新しい日時API Date の問題点をすべて解決するために設計された 2021年にStage
3、2026年3月にStage 4 到達 10
タイムゾーンを型レベルで表現できる 型 用途 Temporal.PlainDate 日付のみ(タイムゾーンなし) Temporal.PlainTime 時刻のみ Temporal.PlainDateTime 日時(タイムゾーンなし) Temporal.ZonedDateTime
タイムゾーン付き日時 Temporal.Instant 絶対時刻(Unix時刻相当) © LayerX Inc. Temporalとは 型が多いぶん、意図が明確になる 11
イミュータブル © LayerX Inc. Temporalとは 12
バクラク勤怠のコードを書き換えてみる
バクラク勤怠 © LayerX Inc. https://bakuraku.jp/attendance/ LayerX が提供する勤怠管理 SaaS Slackアプリ、PCログ、AIによるシフト変換機能 ...
etc 14
プロダクト画像は現地のみ! © LayerX Inc. 15
これは置き換え甲斐がありそうだぜ.... 勤怠管理アプリは日付・時刻がいっぱい
基本編 豊富なAPIをいっちょ試してみるかのコーナー
タイムゾーン付きで現在時刻の取得 © LayerX Inc. 現在時刻の取得: Temporal.Now ※バクラク勤怠では、日付・時刻処理にはDay.jsを利用し、 new Date をESLintで禁止している
18
現在時刻の取得: Temporal.Now © LayerX Inc. 型ごとの現在時刻関数 instant() plainDateISO(timeZone?) plainDateTimeISO(timeZone?) plainTimeISO(timeZone?)
zonedDateTimeISO(timeZone?) timeZoneを省略するとtimeZoneId()が設定される timeZoneId() システムで設定されているタイムゾーンを返す ex) "Asia/Tokyo 19
値の取得 Date Temporal getFullYear() year getMonth() (0始まり) month (1始まり) getDate()
day ⋯ ⋯ © LayerX Inc. Dateは関数、Temporalはプロパティ 20
プロパティ 意味 dayOfWeek 曜日(1=月曜、7=日曜) dayOfYear 年通算日(1〜366) weekOfYear 年通算週番号 daysInMonth 月の日数(28〜31)
daysInYear 年の日数(365 or 366) inLeapYear うるう年かどうか microsecond , nanosecond マイクロ秒/ナノ秒(0〜999) © LayerX Inc. プロパティ 21
曜日はちょっと注意 © LayerX Inc. 曜日: dayOfWeek Date( getDay() )は0始まり、0=日曜日、6=土曜日 Temporal(
dayOfWeek )は1始まり、1=月曜日、7=日曜日 故に、 getDay() === dayOfWeek % 7 22
特定の日付・時刻を作成 © LayerX Inc. 23
.from , .with © LayerX Inc. 特定の日付・時刻を作成 24
比較: .compare , .equals © LayerX Inc. 25
加算・減算: .add , .subtract © LayerX Inc. 26
応用編 勤怠管理のドメインに寄った話
どの型を使うか? © LayerX Inc. 出勤簿の年月: PlainYearMonth 出勤簿の各日付: PlainDateTime 28
打刻時間はPlainTime? © LayerX Inc. どの型を使うか 18:00 など。 PlainTime でよさそうじゃね? 29
退勤時刻は24:00を超える場合がある © LayerX Inc. どの型を使うか ex: 25:00 は翌日の1時 深夜残業や、深夜シフトなど 30
PlainTimeは〜23:59なので、 © LayerX Inc. どの型を使うか 31
PlainDateTime or ZonedDateTime がよさそう バクラク勤怠では ZonedDateTime がよさそう。 © LayerX Inc.
どの型を使うか 32
出勤・退勤時刻から労働時間の計算 © LayerX Inc. どの型を使うか 33
31日締め × 2月問題 © LayerX Inc. 締め日の設定は1〜31日。でも2月は最大28日(うるう年は29日) 現状は Math.min で手動クランプ:
34
overflow オプション © LayerX Inc. 31日締め × 2月問題 35
constrain と reject を用途で使い分けるとよさそう: © LayerX Inc. overflowオプション 36
constrain と reject を用途で使い分けるとよさそう: © LayerX Inc. overflowオプション 37
「業務月」はカレンダー月ではない © LayerX Inc. 14日締めの会社の「4月」の出勤簿に表示される期間 = 4/15 ~ 5/14 14日締めの会社の
5/10 の業務月は 「4月」 38
「業務月」の取得 締め日で分岐して、カレンダー月の前月・次月・当月を返す © LayerX Inc. 39
「次の月」の取得 © LayerX Inc. 「業務月」はカレンダー月ではない getNextYearMonth は12月を手書きで処理している: 前月( getPrevYearMonth )も似たようなもん
40
ただ、 .add , .subtract を使えば、よい © LayerX Inc. 「業務月」はカレンダー月ではない PlainYearMonth
を使うと 年またぎが自動処理 される: 41
Branded Typeで「業務月」を型で区別 © LayerX Inc. 「業務月」はカレンダー月ではない 現状、コード上で年月は { year: number;
month: number } で表現されており、 「これ、どっちだっけ ... ?」となりがち PlainYearMonth + Branded Type で 型レベルで業務月とカレンダー月を区別できる: 42
有給休暇「2年後の前日」× うるう年 © LayerX Inc. 有給休暇の有効期限は付与日から 2年間(労働基準法) Q. 2024年2月29日(うるう年)に付与された有給はいつまで有効? A.
2026年2月27日 有効期限は「付与された日から2年後の、前日(応当日)まで」 43
うるう年の2年後 © LayerX Inc. 有給休暇「2年後の前日」× うるう年 ライブラリの場合、実装による Day.jsは、 .add(2, "year")
でOK 44
Temporal は仕様で動作が明示されている 「ライブラリによる」ではなく 仕様として保証 されている点が重要 © LayerX Inc. 有給休暇「2年後の前日」× うるう年
45
気づき その他の実際に使ってみて気づいたこと
「Temporal.型~」 、長い © LayerX Inc. 「Temporal.型.~」のコード上での存在感がすごい AIがコードを書く時代で、よかったね そうでなければ、ラップした関数を作っていたかも知れない 47
フォーマッターをどうするか © LayerX Inc. Day.jsのformat関数を結構使ってた Intl.DateTimeFormat、使いづらくないか? 任意のフォーマットで出力できる関数(ex: format('YYYY-MM-DD') )はToo Muchだと思うの
で、 特定のフォーマットで出力できる関数を作る程度でいい気がする 48
フォーマッター以外はAPIで困ることはない © LayerX Inc. API・型が豊富 日付・時刻に関するユースケースはほぼカバーされていると言っても過言ではない、か もしれない 49
ありがとうございました!