🐈

FrontendにおけるDate型の取り扱い

2023/03/06に公開

はじめに

javaScriptにおけるDateはややこしい&使いにくいという印象だけあったが何がどう難しいのかわかっていなかったので調べてみる。

迷う点はこんなところになりそう

  • わからないところを挙げてみる

どんな形式で日付データを取り扱うか

  • 基本的にはJavaScriptにおけるDate型で扱いやすい形式で永続化するなら置いておいたほうがよさそう
  • JavaScriptにおけるDate型のコンストラクタを見ると、5つの形式で引数を受け付けているらしい。
  • Dateクラスの引数
    • 引数なし:現在の日付と時刻でDateインスタンスが作成される
    • 時刻値又はタイムスタンプ型: 数値
      • 世界協定時 (UTC) 1970 年 1 月 1 日午前 0 時 0 分 0 秒 (ECMAScript 元期、 UNIX 元期と等価) からのミリ秒数を整数値で表し、うるう秒は無視します。

    • 日付文字列: ISO8601形式 (YYYY-MM-DDTHH:mm:ss.sssZ)
      • Date コンストラクター(および Date.parse と同等)で日付文字列を解釈する際には、常に入力が ISO 8601 形式 (YYYY-MM-DDTHH:mm:ss.sssZ) であることを確認してください。他の形式で解釈した場合には、その挙動は実装によって定義されていて、すべてのブラウザーで動くとは限りません。

      • Date.parse()メソッドで認識される形式に対応しているが、他の形式では実装がブラウザーによってまちまちらしいので日付文字列を使う場合は必ずこの形式にしたほうがよいとのこと
    • Dateオブジェクト
      • Dateオブジェクトのコピーが作成される
    • 独立した日付と時刻の値
      • new Date(2023, 01, 01, 05, 05)のように個別指定もできる
  • ISO8601形式とは
    • ISO8601ってそもそも何?
      • ISOとはInternational Organization for Standardizationの略
      • ISO 8601は国際的な時刻の標準化
      • RFC 3339との関係
        • RFCはインターネット技術を議論し、標準化を進める団体であり、そこで定義された文書はRFC○○(番号)として閲覧可能になる。RFC 3339はインターネット上の時刻に取り扱いを定めた仕様であり、この中でISO 8601が使われている。

    • 例: 2023-01-01T14:00:40+9:00 → 2023年1月1日14:00(日本時間)
    • 時刻は日付と時間からなり、Tで区切られる
    • 時差は+や-で表され、UTCより進んでいる場合は+、遅れている場合は-で表す
      • +や-の変わりにZがつくとUTC時刻となる
  • Date型の注意点があるらしい
    • 引数なしで初期化した場合は、現在のタイムゾーンの現在の時刻を持つ Date として初期化される
    • 日付文字列:(ISO8601形式)で初期化した際は、タイムゾーンを解釈し現在のタイムゾーンに変換された Date として初期化される
    • タイムゾーンを指定してなかった場合は、現在のタイムゾーンでの時刻であるとして解釈された Date として初期化される
      • 「現在の」というのは、ブラウザだったり、OSの国設定だったりするっぽいのであまり当てにならなそう
      • 基本的にタイムゾーンを指定して初期化すべし
  • 結論
    • 総合的に考えると、ISO8601形式 (YYYY-MM-DDTHH:mm:ss.sssZ) の日付文字列で扱うのがよさそう
    • JSTで管理しようとすると思わぬバグを生みそうなので、データとしてはUTCで管理して、表示するときにJSTに変換するような運用がよさそう

日時形式

要件次第ではあるが、日本語圏以外にも読まれる想定であれば国や言語によって表示形式が違う様子。
英語圏でもアメリカ式とイギリス式で形式違うのか...

言語 表示形式
日本 yyyy/mm/dd 2023/01/02
英語(アメリカ) mm-dd-yy 01-02-23
英語(イギリス) dd/mm/yy 02/01/23
英語(カナダ) dd/mm/yy 02/01/23
ドイツ語 yyyy-mm-dd 2023/01/02
イタリア語 dd/mm/yy 02/01/23
スペイン語 dd-mm-yy 01-02-23

他ライブラリとの比較はしないけど、ひとまずdate-fnsではいずれのフォーマットも用意されていそう。
https://date-fns.org/v2.29.3/docs/format

ユーザーがどの国・言語かを判断して表示形式を変更するような実装は可能なのかはちょっとわからない...
日本語圏はyyyy/mm/dd、英語圏はmm/dd/yyyyみたいな。

まとめ

JavaScriptにおけるDateの扱いが難しいとされているのは、タイムゾーンの扱いに注意が必要なため。
日付関係のライブラリが発達したのは、そういったタイムゾーンを考慮したDateの扱いをしやすくする側面もありそう。日付をどんな形式で永続化して、表示時にはどんなフォーマットをするのか方針を決めてから取り扱うのにコツがいる。

おわりに

なぜJavaScriptにおけるDateがすっきりした。

参考

Discussion