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
Branded Typesで日時の複雑さと戦う
Search
Saji
November 23, 2025
4
1.1k
Branded Typesで日時の複雑さと戦う
TSKaigiHokuriku2025 LT
-
https://hokuriku.tskaigi.org/talks/41
X
-
https://twitter.com/sajikix
Saji
November 23, 2025
Tweet
Share
More Decks by Saji
See All by Saji
ユーザーが作成したコードをブラウザ上で安全に実行できる Plugin システムへのアプローチ
sajikix
1
300
推しProposalと広がる夢~Intl.MessageFormatとDomLocalization~
sajikix
1
480
自作JSエンジンに推しプロポーザルを実装したい!
sajikix
1
280
Lookback TypeScript ESM support and what should we do now.
sajikix
5
760
フロントエンドで日時処理と戦うために 2025 ver
sajikix
6
4.5k
先取り!Temporal
sajikix
0
260
アプリ文言のパースで学ぶ 文字列Literal型パズル入門
sajikix
3
1.2k
The Future of Frontend i18n : Intl.MessageFormat
sajikix
1
4.1k
Temporalを取り巻く仕様を整理する
sajikix
3
1k
Featured
See All Featured
How to train your dragon (web standard)
notwaldorf
97
6.5k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
210
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Done Done
chrislema
186
16k
Scaling GitHub
holman
464
140k
BBQ
matthewcrist
89
10k
Utilizing Notion as your number one productivity tool
mfonobong
2
200
Code Review Best Practice
trishagee
74
19k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
0
290
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
0
120
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
How To Stay Up To Date on Web Technology
chriscoyier
791
250k
Transcript
3ZVTFJ4BKJLJ!TBKJLJY #SBOEFE5ZQFTͰ࣌ͷෳࡶ͞ͱઓ͏
͍࣌͠Ͱ͢ΑͶʁ
ࣗͷνʔϜͰ՝ͩͬͨ
ҙࣝΛڞ༗͢ΔͨΊʹ ؆୯ʹLJOUPOFͷઆ໌
LJOUPOFʹ͍ͭͯ LJOUPOFɺϓϩάϥϛϯάͷ͕ࣝͳͯ͘ۀʹ߹ΘͤͨγεςϜΛ͢ ͘։ൃͰ͖ΔϊʔίʔυɾϩʔίʔυͰ͢ɻ σʔλΛੵɾҰཡɾݕࡧͰ͖ΔσʔλϕʔεػೳͱɺۀΛԁʹਐΊΔͨ Ίͷίϛϡχέʔγϣϯػೳ͕උΘ͍ͬͯ·͢ɻ
LJOUPOFͷʮΞϓϦʯػೳʹ͍ͭͯ LJOUPOFͷϝΠϯػೳʹʮΞϓϦػೳʯͱݺΕΔͷ͕͋Δ w ̎࣍ݩతʹ༷ʑͳϑΟʔϧυΛஔͯ͠ɺϑΥʔϜΛ࡞ w ϢʔβʔσʔλΛཷΊ͍ͯ͘͜ͱ͕Ͱ͖Δ w ଞʹɺϓϩηεཧίϝϯτଞΞϓϦͷࢀরͳͲ͕Ͱ͖Δ w ݱࡏɺ$MPTVSF-JCSBSZ+4ˠ3FBDU54ʹ৽த
LJOUPOFʮΞϓϦʯͷೖྗը໘
LJOUPOFͷʮΞϓϦʯʹ͋Δ࣌ܥͷϑΟʔϧυ ҎԼͷϑΟʔϧυ͕͋Δ w ϑΟʔϧυΛೖྗͰ͖ΔϑΟʔϧυ w ࣌ࠁϑΟʔϧυ࣌ࠁΛೖྗͰ͖ΔϑΟʔϧυ w ࣌ϑΟʔϧυͱ࣌ࠁΛ߹ΘͤͯೖྗͰ͖ΔϑΟʔϧυ w ࡞࣌
ΈࠐΈϑΟʔϧυ σʔλΛ࡞͕ͨ࣌ࣗ͠ಈͰೖΔ w ߋ৽࣌ ΈࠐΈϑΟʔϧυ σʔλΛߋ৽͕ͨ࣌ࣗ͠ಈͰೖΔ
LJOUPOFͷʮΞϓϦʯʹ͋Δ࣌ܥͷϑΟʔϧυ
࣌ܥͷϑΟʔϧυ࣮ͷ՝ ΞϓϦͷϑΥʔϜͷঢ়ଶΛཧ͢Δ࣌ʹɺશ෦4USJOHܕͰΛཧ͍ͯͨ͠ export type DateFieldValue = { type: typeof FORM_INPUT_FIELD_TYPE.DATE;
value: string; }; export type TimeFieldValue = { type: typeof FORM_INPUT_FIELD_TYPE.TIME; value: string; };
શ෦ಉ͡ܕͩͱ߹͕ѱ͍ʁ
ಉ͡ੑ࣭ͷσʔλ͡Όͳ͍ ؾ͕͢ΔΜͩΑͳ͊
ྨͷ؍͕ͭ͋Δͱߟ͑ͨ
؍ಛఆͷҰॠΛࢦ͢σʔλ͔ʁ ࣌ͷσʔλʹಛఆͷҰॠΛʮࢦ͢ͷʯͱʮࢦ͞ͳ͍ͷʯ͕͋Δ ྫʮੜ݄ʯͱ͍͏ใ࣌ͷσʔλ͕ͩɺಛఆͷҰॠࢦ͞ͳ͍ ͦΕͧΕผͷ֓೦Ͱ͋ΓɺมʹෆՄٯੑ͕͋Δ 2025-11-23 2025-11-23 16:40 16:40 ❌ ❌
؍ϢʔβʔͷೖྗΛ͏͔ʁ ϢʔβʔϩʔΧϧ࣌ؒʹੜ͖͍ͯΔ w Ϣʔβʔ͕ೖྗ͢ΔͷৗʹϩʔΧϧ࣌ؒ w Ͳ͔͜ͰϑΥʔϜͷঢ়ଶˠ65$ͷม͕ඞཁʹͳΔ ٯʹϢʔβʔͷೖྗ มߋ ͕ͳ͍ͷͰ͋Ε w
දࣔલʹϩέʔϧͱλΠϜκʔϯΛՃຯͨ͠ϑΥʔϚοτΛ͢Δ͚ͩ w format(datetime)
݁શવಉ͡ੑ࣭ͷσʔλͰͳ͍ ؍ಛఆͷҰॠΛࢦ͢σʔλ͔ʁ w ಛఆͷҰॠΛࢦ࣌͢ߋ৽࣌࡞࣌ w ಛఆͷҰॠΛࢦ͞ͳ͍࣌ࠁ ؍ɿϢʔβʔೖྗΛ͏σʔλ͔ʁ w ೖྗΛ͏࣌࣌ࠁ w
ೖྗΛΘͳ͍ߋ৽࣌࡞࣌
݁ಉ͡ੑ࣭ͷσʔλͰͳ͍ ಛఆͷҰॠΛࢦ͢ ಛఆͷҰॠΛࢦ͞ͳ͍ ϢʔβʔೖྗΛ͏ ࣌ϑΟʔϧυ ࣌ࠁϑΟʔϧυϑΟʔϧυ ϢʔβʔೖྗΛΘͳ͍ ߋ৽࣌࡞࣌ϑΟʔϧυ
͡Ό͚͋Α͏
ϧʔϧ࣌ͱͯ͠ѻ͏σʔλΛྨ͠ݶఆ͢Δ ࣌ͱͯ͠ѻ͏ อ࣋͢Δ σʔλΛҎԼͷͭʹݶఆͨ͠ 65$*404USJOH"2025-11-23T07:40:00.000Z" %BUF4USJOH"2025-11-23" 5JNF4USJOH"16:40"
-PDBM%BUF5JNF0CKFDU{date: "2025-11-23", time: "16:40"} w %BUF4USJOHͱ5JNF4USJOHΛ߹Θͤͨͷ
ϧʔϧ࣌ͱͯ͠ѻ͍͍ͬͯσʔλ ಛఆͷҰॠΛࢦ͢ ಛఆͷҰॠΛࢦ͞ͳ͍ ϢʔβʔೖྗΛ͏ -PDBM%BUF5JNF0CKFDU ˣ 65$*404USJOH %BUF4USJOH5JNF4USJOH ϢʔβʔೖྗΛΘͳ͍ 65$*404USJOH
ؒ %BUFμϝͳͷ %BUFͷ··σʔλͷอ࣋ΓऔΓ͢Δ͜ͱඇਪʹͯ͠Δ ཧ༝ w ͦͦγεςϜλΠϜκʔϯ ↔︎ 65$͔͠αϙʔτ͍ͯ͠ͳ͍ w ೖग़ྗΛ65$γεςϜͷͲͬͪͰѻ͏͔͕҉త
w จࣈྻͷύʔε͕͔ͳΓτϦοΩʔ w ͜͜ʹօ͞Μͷࢥ͏ҙͷ%BUFͷෆຬΛೖΕΔ
ܕͰ͚͍ͨʂ
#SBOEFE5ZQFTͩʂ #SBOEFE5ZQFTͱ w ʮߏ͕ಉ͡ͳΒಉ͡ܕͱ͢Δʯͱ͍͏54ͷݪଇΛճආ͠ɺ w ߏ͕ಉ͡ܕͰޓ͍ʹ۠ผ͕ͭ͘Α͏ʹ͢Δख๏ ࣗͳΜͰ͔ΜͰಋೖ͢Δͷʹ৻ॏɻͰ࣌ʹؔͯ͠ w ಘΒΕΔԸܙ ࣌ͷ͜͠͞
#SBOEFE5ZQFTʹΑΔσϝϦοτ ͱࢥͬͯΔ
࣮ࡍͷίʔυ #SBOEFE5ZQFͷఆٛ ྫUTCISOStringܕ const utcisoStringBrand = Symbol('for UTCISOStringBrand'); export
type UTCISOString = string & { [utcisoStringBrand]: unknown; };
࣮ࡍͷίʔυ "TTFSUJPOؔηοτͰ࡞Δͱศར export function createUTCISOString( rawString: string, strict: boolean =
true ): UTCISOString { if (strict && !UTC_ISO_DATE_TIME_REGEX.test(rawString)) { throw new Error(`Invalid UTC ISO String : ${rawString}`); } return rawString as UTCISOString; }
'&Ͱ#SBOEFE5ZQFTʹҠߦ͢Δ࣌ͷίπ ֎෦͔ΒͷσʔλɾϢʔβʔೖྗɾ4UBUFͷ̏ํ͔ΒݫີԽ͢Δͱྑ͍ ίʔυ ϕʔε ֎෦σʔλ "1* 4UBUF Ϣʔβʔೖྗύʔπ ;PE4DIFNB "TTFSUJPO7BMJEBUJPO
ܕఆٛݫີԽ
#SBOEFE5ZQFTΛ࣌σʔλʹಋೖͯ͠Έͯ ܕΛݟΔ͚ͩͰɺԿΛͯ͘͠ΕΔͷ͔Ұྎવ w ྫҾ͕-PDBM%BUF5JNF0CKFDUฦΓ͕65$*404UJOH w ˠ*40ܗࣜͳΜͩͳʂฦΓ65$ͳͷͰ࣌ࠩมͯ͠Δʂ ܕΤϥʔ͕ग़ΔͷͰؒҧ͍ͬͯͦ͏ͳͱ͜ΖΛൃݟɾ༧Ͱ͖Δ w ࣌ͷυϝΠϯʹৄ͘͠ͳ͍δϡχΞϝϯόʔͰ҆৺ νʔϜͰͷڞ௨ݴޠʹͳΔ
Α͏ʹؤுͬͯΔͱ͜Ζ
͜͜·ͰͰेศར͚ͩͲ
কདྷΛݟਾ͑Δ
࣌Yকདྷ
࣌Yকདྷ5FNQPSBM
5FNQPSBMΛҙࣝͯ͠Δ ࣮͜ͷྨ5FNQPSBMΛࢀߟʹ͍ͯ͠Δ ͱ͍͏͔͓ͷͣͱͦ͏ͳΔ 5FNQPSBMͱͷରԠؔ w 65$*404USJOHTemporal.Instant w %BUF4USJOHTeporal.PlainDate w
5JNF4USJOHTeporal.PlainTime w -PDBM%BUF5JNF0CKFDUTeporal.PlainDateTime
5FNQPSBMΛҙࣝͯ͠Δ UTCISOString LocalDateTimeObj DateStiring TimeString
5FNQPSBMͷੴ ݁ہ5FNQPSBM͕ղܾ͔ͨͬͨ͜͠ͱͱಉࠜͷͩͬͨ w ͦΕΛ#SBOEFE5ZQFͰղܾͯ͠Δ w ·ͩ5FNQPSBM͔͔࣌ؒΓͦ͏ͳͷͰ ٯʹݴ͑ɺ5FNQPSBMҠߦ؆୯ʹͳΔͣͰ͢Ͷʂ w ରରԠͯ͠ΔͷͰมͯ͠Δ͚ͩͰ͍͍
·ͱΊ ࣌ͷσʔλΛѻ͏ͷ͍͠ w ಛʹಠཱͨ࣌͠ࠁΛѻ͏߹%BUFͷ͍উख͕ LJOUPOFͷΞϓϦը໘৽Ͱ#SBOEFE5ZQFTͰ࣌σʔλΛྨɾ੍ݶͯ͠Δ w ϝϦοτڗडͰ͖ͯΔ ͱࢥ͏ ࣌σʔλͷྨ5FNQPSBMΛࢀߟʹ
ݟӽͯ͠ ࡞͍ͬͯΔ w ૣ͘5FNQPSBM͕͘Εղܾ͢Δͷʹͳ͊ ࣌σʔλͷཧͰࠔͬͨͱ͖#SBOEFE5ZQFT͕ॿ͚ʹͳΔ͔͠Εͳ͍
4BKJ3ZVTFJ4BKJLJ 'SPOUFOE%FWFMPQFSBU$ZCP[V JOD 𝕏 !TBKJLJY
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠