2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Kotlin】日時(Date)を安全に送信する/解釈する【JavaScript】

Last updated at Posted at 2019-12-25

この記事は、Java Advent Calendar 2019 22日目の記事になりました。

Javaとか言いつつJavaScriptKotlinの話が出てきますが、分量的にはDateTime APIの話が主なので大体Javaです。

解決したい問題

以下の記事の通り、JavaScriptDate型には多くの罠があります。
日本人であれば「日時を送信したら1日巻き戻って届いた」的な状況は経験された方も多いのではないでしょうか?

そんな罠だらけのDate型を安全に送信/解釈します。

解決方法

ものすごくざっくり言うと、規格に則って文字列として送信し、規格に則って文字列から解釈すれば安全に取り扱えます。
今回は例として、ISO 8601規格に則って処理を行います。

具体的には以下を用います。

  • Date.prototype.toISOString()メソッド
  • DateTime APIZoned系クラス

補足

Date.prototype.toISOString()メソッドは大体の環境で動きますが、DateTime APIJava8以降のサポートです。

やり方

送信側

以下で生成したdateStrを送信すればOKです

日時文字列生成(js)
const date = Date.now();
// ISO 8601で、タイムゾーンがUTCの文字列
const dateStr = date.toISOString();

受信側

まずZonedDateTimeとして解釈して、そこからLocal系の内容に変換するのがオススメです。
ZonedDateTime.parseメソッドはDate.prototype.toISOString()で生成した文字列を直に解釈できます。

ZonedDateTime型として解釈(kt)
val dateStr = /* toISOString()した文字列 */
// タイムゾーン付き日時型
val zonedDateTime = ZonedDateTime.parse(dateStr)

タイムゾーンを設定する

型としてはZonedDateTimeに解釈した時点で安全に取り扱えますが、この方法では受け取った時点でのタイムゾーンがUTC扱いになるため、そこから更に何か扱う前にローカルのタイムゾーンに変換した方が良いでしょう。

タイムゾーンのセットは、ZonedDateTime::withZoneSameInstantメソッドで行えます。
このメソッドの引数はZoneId型で、ZoneId.systemDefault()を呼び出すことでシステムのタイムゾーンのZoneIdを得ることができます。

システムのタイムゾーンを指定(kt)
val original: ZonedDateTime
val zoned = original.withZoneSameInstant(ZoneId.systemDefault())

この処理を終えれば、後は自由に扱うことができます。
補足として、日時を厳密に扱いたいのであれば、JVM内では日時全てをZonedDateTimeとして扱い、ゲッター等で必要に応じて変換するというのがオススメです。

終わりに

今回は日時(Date)を安全に送信する/解釈する方法についてまとめました。
日時に限らず相対的な値は扱いがとても難しいですが、規格に則ることで安全に扱えるようになります。

この記事が相対的な値の扱いのお役に立てば幸いです。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?