【JavaScript】Temporalは理想主義すぎて実用に堪えないのではないか


```js
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](https://github.com/tc39/proposal-temporal)の感想

めんどくさい。

[Temporal](https://tc39.es/proposal-temporal/)は、TC39が導入を目指している次世代の日付時刻管理APIです。

[Date](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date)の[反省](https://qiita.com/labocho/items/5fbaa0491b67221419b4)を生かし、間違いのない仕様を目指しています。

具体的には、ローカル時刻とUTC、タイムゾーンのあるなし等を厳密に峻別します。
そして、その使い分けをユーザにも強制してきます。
Temporalを使う際は常にそのあたりを意識しながら、目的に応じて多数のクラスを使い分ける必要があります。
タイムゾーン情報のみを持つTimeZone、年月のみを持つPlainYearMonth、月日を持つPlainMonthDay、年月日を持つPlainDate、時分秒を持つPlainTime、年月日時分秒を持つPlainDateTime、年月日時分秒オフセットを持つInstant、年月日時分秒オフセットタイムゾーンを持つZonedDateTime、週の情報を持つCalendar。
これらを正しく使い分けましょう。

アホかと。


そこはまあいいとしても、致命的な問題として、任意のフォーマットでのパース・出力が極めて困難です。
JSで日付を触る理由なんてここが99%だろ。

日時文字列のパース関数は存在しますが、パース可能な文字列は何故か[特定の形式](https://github.com/tc39/proposal-temporal/blob/main/docs/plaindatetime.md#temporalplaindatetimefromthing-any-options-object--temporalplaindatetime)に限られています。
任意のフォーマットを引数で渡してパースするみたいなことができません。
汎用的なパース関数は[提唱されてこそいるものの今のところ実装される予定はなく](https://github.com/tc39/proposal-temporal/blob/main/docs/parse-draft.md)、フォーマットを渡す形式のパースはそもそも考慮されてすらいないようです。

このあたり、[既存の](https://qiita.com/sangotaro/items/8ee4b0f40cbcf3f12784#%E6%97%A5%E6%99%82%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E3%83%91%E3%83%BC%E3%82%B9%E3%81%97%E3%81%A6%E6%97%A5%E6%99%82%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B)[解説記事](https://qiita.com/uhyo/items/5f34f5d6f33aa091a104#%E6%96%87%E5%AD%97%E5%88%97%E3%81%8B%E3%82%89%E3%81%AE%E5%A4%89%E6%8F%9B)は何故か何れも『できない』としか書かれておらず、じゃあ具体的にどうすればいいんだよってのは解説記事どころか[公式ドキュメント](https://tc39.es/proposal-temporal/docs/cookbook.html)ですら触れられていません。
なんで。


出力については[Intl.DateTimeFormat](https://tc39.es/ecma402/#datetimeformat-objects)を使用しているため、一応これを使って[形式を変更することができます](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#options_%E3%81%AE%E4%BD%BF%E7%94%A8)。
しかしこれ、[使い方が異様にめんどくさい](https://qiita.com/kyntk/items/a8072e6f0d7a71863438#formatmatcher)上に[再現困難な形式](https://qiita.com/ota-meshi/items/4b525e0bfce931c9c504)まで存在しており実用性に疑問を感じます。
それなら普通に`.year`とかで取り出した方が手っ取り早いし、なんなら`.format("Ymd")`寄こせって話ですね。


# 感想

なんというか、理想主義というか教条的で融通が利かないというか。
正しさを追い求めるあまり利用する側のことを全く考えていないというか。
結局厚いラッパーライブラリが出てくるまで、Temporalをそのまま使う需要はほとんど出てこないのではないでしょうか。

なおTemporalリポジトリの初出は2017年ですが、それから5年経った今でも未だに仕様が固まりきっていません。
たとえば[2019年の紹介記事](https://qiita.com/uhyo/items/5f34f5d6f33aa091a104)に出てきた`CivilDateTime`や`OffsetDateTime`とかは、現在の仕様からは既に消滅しています。
最初に書いた"現実"も、いつまで使えるかわかったものではありません。

今後は使いやすいAPIが追加されるとよいですね。


# おまけ

当初、冒頭の例を`2000-01-23 12:34:56`として記事を書いてたのですが、ほぼ書き上げてから`Temporal.PlainDateTime.from("2000-01-23 12:34:56")`が[polyfill](https://github.com/js-temporal/temporal-polyfill)で動くことに気付いてしまったという。
気付いたんですけど、これは正常な動作なのだろうか？
Temporalが準拠しているとされる[ISO 8601](https://ja.wikipedia.org/wiki/ISO_8601)にも[RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339)にも存在しない形式なんだけど。
本当にこの形式も許容するのか、単にpolyfillがやらかしてしまっただけなのかはよくわかりません。

ということで動かない例に差し替えました。
微妙に作為的な感じはするけどままえやろ。