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
本当はややこしい日時のFormatPattern
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Saji
July 08, 2026
34
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
本当はややこしい日時のFormatPattern
Saji
July 08, 2026
More Decks by Saji
See All by Saji
tpac_study (2026)
sajikix
0
43
業務に残された「良くない型」で考える「TypeScriptの難しさ」
sajikix
4
7.2k
It’s “Time” to use Temporal
sajikix
3
360
ユーザーが作成したコードをブラウザ上で安全に実行できる Plugin システムへのアプローチ
sajikix
1
760
Branded Typesで日時の複雑さと戦う
sajikix
4
1.2k
推しProposalと広がる夢~Intl.MessageFormatとDomLocalization~
sajikix
1
710
自作JSエンジンに推しプロポーザルを実装したい!
sajikix
1
360
Lookback TypeScript ESM support and what should we do now.
sajikix
5
820
フロントエンドで日時処理と戦うために 2025 ver
sajikix
6
4.7k
Featured
See All Featured
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
180
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Bash Introduction
62gerente
615
220k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
25k
Designing Powerful Visuals for Engaging Learning
tmiket
1
430
Making the Leap to Tech Lead
cromwellryan
135
9.9k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
How Software Deployment tools have changed in the past 20 years
geshan
0
34k
Amusing Abliteration
ianozsvald
1
210
Build your cross-platform service in a week with App Engine
jlugia
234
18k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
150
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
210
Transcript
本当はややこしい 日時のFormatPattern Nihonbashi.js #11 Saji (Ryusei Sajiki) / @sajikix
(主に国際化の文脈で ) 日時のフォーマットは 結構面倒くさい
⚠ 今回しない話 • タイムゾーンの話 ◦ 時差の変換とかサマータイムとか • 暦にまつわる話 ◦
非グレゴリウス暦の面倒なところなど • 人間の可読性特に考えなくて良い or 厳密なもの ◦ ISO8601 / RFC3339 とかの話
先に結論とその上で話すこと Intl.DateTimeFormatでいいならそれに越したことない • 今回のトークの結論としては実質これが全て • このあと話す「めんどくささ」を極力踏まないようにできる Intl.DateTimeFormatを使わないで頑張ろうとした時... • パンドラの箱は開かれます この辺りについて何が面倒なんだ?という話をします
みんながよくやりがち 大体以下の2択になると思ってる • FormatPattern文字列を使ってフォーマット • 一から全部自分で組み立てる 一から全部組み立てるのは国際化とかまで考えると大変 • 使い回しがしづらい /
ロケールデータをどこから持ってくる? …etc → なのでFormatPattern文字列を使いがち(今回はこの話)
FormatPattern文字列 「YYYY年MM月DD日」みたいなPatternを渡してフォーマットする方法 • 対応するSymbolのまとまり (YYYYなど) に実際の日時を入れてくれる • 大抵の日時系ライブラリでサポートされている方式 • (言語・ライブラリによっては実際の値を渡すものもある)
自由度が高いため、webフロントエンドでも各所で使われているが...
問題1: ライブラリ間互換性 ライブラリごとにFormatPatternのルールが微妙に違う JSのライブラリでは大きく2系統ある • Moment.js / Day.js 系 :
YYYY/MM/DD パターン • date-fns / Luxion 系 : yyyy/MM/dd パターン ただ同じ系統でもそれぞれ微妙に受け入れるsymbolやパターンに差がある → 相互運用性に問題がある
どれが正解なのか? (正解はある? ) 一番ちゃんとしていそうな仕様としてUnicodeのLDMLがある • Table: Date Field Symbol Table
• ※ Unicodeは国際化における多くの仕様やデータセット・ライブラリを持つ date-fns はこのLDMLに準拠することを明言している > Format of the string is based on Unicode Technical Standard #35
じゃあ、date-fns 使えば解決?
問題2 : 参照するロケールデータの違い そのライブラリがどんなロケールデータ(月名とか)を参照してるか • 多くのフォーマット機能を持つ日時系ライブラリは独自にデータを持つ • date-fnsの例 const dayValues
= { narrow: ["d", "l", "m", "m", "j", "v", "s"], short: ["do", "lu", "ma", "mi", "ju", "vi", "sá"], abbreviated: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"], //… }
Intl (ICU) の大元はCLDR Unicodeは様々なロケール固有の情報をCLDRという名前で公開・管理してる • 日時のフォーマット以外にも言語名や数値の形式など... • 全世界で最も統一的で網羅的なデータセットと言える OSの国際化機能やJSエンジンもライブラリ(ICU)を経てこのCLDRを利用してる →
CLDRのデータを利用するのが一番確実と言えそう (ちなみにdate-fnsのデータは結構CLDRとズレてたりする。多分他も...)
LDML準拠 + CLDRがデータソース なら解決?
問題3 : CLDRにもバージョンがある CLDRは常にupdateされている • 近年だと4月頃と10月頃にメジャーアップデートがある データ更新がある = フォーマット結果は変わりうる •
(メジャーなロケールではそこまで多くないけど) すごく厳密なことを言い出すと... • 「OSやBEと参照しているCLDRを揃えたい」みたいなことになる
つまり理想的には ... 以下があれば良い • pattern symbolはLDML準拠 • ロケールデータのデータソースはCLDR • ソースのCLDRバージョンは選べる
• (とはいえサイズが大きすぎるのは勘弁....) そんなライブラリあるのか .....? (パッと調べた感じなかなかなさそう )
じゃあ、作るっきゃない
作ってみた https://github.com/sajikix/datetime-pattern-formatter
作ったライブラリの特徴 • formatPatternはLDMLに完全に準拠 (一部未サポートSymbolあり) • 参照するのはCLDRそのままのデータ • ロケールを明示的に指定するのでそこまでバンドルサイズは肥大しない • 参照するCLDRのバージョンも明示的に指定できる
import { en } from "@sajikix/datetime-pattern-formatter/cldr/48_2/en"; format(new Date(), "yyyy-MM-dd", en, { inUTC: true}); // → 2026-07-08
これで全て解決?
突然ですがクイズです
以下の指定は正しい? 例: 「September」のような省略しない表記で月選択のDropDownUIを作った • 月だから使うシンボルはMで wide形式だから MMMM だな! • const
label = format(date,”MMMM”) • 英語ではちゃんと 「September」になった!ヨシ 👈
A. 月名が格変化する言語がある 日付の一部として表記する時と単体で表記する時で変化する 例 : チェコ語で 1月と1月5日をそれぞれ表記する場合 • 1月 :
leden • 1月5日 : 5. ledna MMMMの場合は ledna の方になってしまい、好ましくない....
月のformatSymbol : MとL このような月の格変化に対応するため月を表すsymbolには • M : 日付のの中の月名を示す時 • L
: 月名単体を表記する時 (standalone 形式と呼ばれる) の2種類が定義されている。 今回の例の場合 : • より広いロケールに対応することを見越すならLLLLの方が良い
そもそもFormat Pattern自体が難しい そもそも皆さんはFormatPattern文字列をうまく扱えているのか? • LとMを使い分けられていますか? • yとYの違いは説明できますか? • etc… 文法・文化慣習的に不自然なフォーマットを作ることが容易
→ 自由度が高い分、こういった部分は自力で使いこなすしかない
大いなる力には、 大いなる責任が伴う
Intl.DateTimeFormatなら Intl.DateTimeFormat では文法・慣習的に間違ったフォーマットはされづらい • 今回の例でもちゃんと格変化を踏まえてフォーマットされる Intl.DateTimeFormatの挙動 • ロケールごとに文法・慣習的に正しいPattern集みたいなものを持ってる • 渡されたオプションから一番近いものを選択する
• よく使われるformatPatternによる日時フォーマットは難点が多い • 一応公式と言えそうな仕様とメジャーなロケールデータセットはある ◦ LDMLとCLDR • 可能な限りLDMLとCLDRに準拠したフォーマットライブラリを作ってみた • それでも根底にあるformatPattern自体が難しいという問題は残る
• ここら辺を気にしたくないなら、Intl.DateTimeFormat が安全 • formatPatternのご利用は計画的に まとめ
終わり