const dtString = "2000-1-23 12:34:56"; // なんかAPIとかからやってきた値
// やりたいこと Luxon
console.log(DateTime.fromFormat(dtString, "y-L-d H:m:s").toFormat("y年LL月dd日 HH時mm分ss秒"));
// 現実 Temporal
tmp = dtString.split(/[\-\s:]/);
temporal = new Temporal.PlainDateTime(
Number(tmp[0]),
Number(tmp[1]),
Number(tmp[2]),
Number(tmp[3]),
Number(tmp[4]),
Number(tmp[5])
);
console.log(
String(temporal.year).padStart(4, '0') + "年" +
String(temporal.month).padStart(2, '0') + "月" +
String(temporal.day).padStart(2, '0') + "日 " +
String(temporal.hour).padStart(2, '0') + "時" +
String(temporal.minute).padStart(2, '0') + "分" +
String(temporal.second).padStart(2, '0') + "秒"
);
仕様書&polyfillとにらめっこした結果こうなりました。
もっと楽な書き方ある?
proposalの感想
めんどくさい。
Temporalは、TC39が導入を目指している次世代の日付時刻管理APIです。
具体的には、ローカル時刻とUTC、タイムゾーンのあるなし等を厳密に峻別します。
そして、その使い分けをユーザにも強制してきます。
Temporalを使う際は常にそのあたりを意識しながら、目的に応じて多数のクラスを使い分ける必要があります。
タイムゾーン情報のみを持つTimeZone、年月のみを持つPlainYearMonth、月日を持つPlainMonthDay、年月日を持つPlainDate、時分秒を持つPlainTime、年月日時分秒を持つPlainDateTime、年月日時分秒オフセットを持つInstant、年月日時分秒オフセットタイムゾーンを持つZonedDateTime、週の情報を持つCalendar。
これらを正しく使い分けましょう。
アホかと。
そこはまあいいとしても、致命的な問題として、任意のフォーマットでのパース・出力が極めて困難です。
JSで日付を触る理由なんてここが99%だろ。
日時文字列のパース関数は存在しますが、パース可能な文字列は何故か特定の形式に限られています。
任意のフォーマットを引数で渡してパースするみたいなことができません。
汎用的なパース関数は提唱されてこそいるものの今のところ実装される予定はなく、フォーマットを渡す形式のパースはそもそも考慮されてすらいないようです。
このあたり、既存の解説記事は何故か何れも『できない』としか書かれておらず、じゃあ具体的にどうすればいいんだよってのは解説記事どころか公式ドキュメントですら触れられていません。
なんで。
出力についてはIntl.DateTimeFormatを使用しているため、一応これを使って形式を変更することができます。
しかしこれ、使い方が異様にめんどくさい上に再現困難な形式まで存在しており実用性に疑問を感じます。
それなら普通に.year
とかで取り出した方が手っ取り早いし、なんなら.format("Ymd")
寄こせって話ですね。
感想
なんというか、理想主義というか教条的で融通が利かないというか。
正しさを追い求めるあまり利用する側のことを全く考えていないというか。
結局厚いラッパーライブラリが出てくるまで、Temporalをそのまま使う需要はほとんど出てこないのではないでしょうか。
なおTemporalリポジトリの初出は2017年ですが、それから5年経った今でも未だに仕様が固まりきっていません。
たとえば2019年の紹介記事に出てきたCivilDateTime
やOffsetDateTime
とかは、現在の仕様からは既に消滅しています。
最初に書いた"現実"も、いつまで使えるかわかったものではありません。
今後は使いやすいAPIが追加されるとよいですね。
おまけ
当初、冒頭の例を2000-01-23 12:34:56
として記事を書いてたのですが、ほぼ書き上げてからTemporal.PlainDateTime.from("2000-01-23 12:34:56")
がpolyfillで動くことに気付いてしまったという。
気付いたんですけど、これは正常な動作なのだろうか?
Temporalが準拠しているとされるISO 8601にもRFC 3339にも存在しない形式なんだけど。
本当にこの形式も許容するのか、単にpolyfillがやらかしてしまっただけなのかはよくわかりません。
ということで動かない例に差し替えました。
微妙に作為的な感じはするけどままえやろ。