こんにちは。阿部です。
日本に住んでいると、北海道でも沖縄でも同じ日時なので、日時というものが、それほど複雑なものとは思っていない人も多いかと思います。
ところが、複数の国で使われるシステムを開発するには、複雑怪奇な日時と向き合う必要に迫られます。
日時の表記法
まず、表記法について説明しておきます。日時の表し方は国や地域ごとに異なります。例えば、
- 2019/09/01 15:30
- 01-09-2019 03:30 PM
- Sep 1, 2019 03.30 PM
日本人だけが読むのなら、「2019/09/01 15:30」のようなフォーマットでほとんど問題ないかと思いますが、誤解のないように表記するには、国際規格に従うのが無難です。
ISO 8601 拡張形式:
- 2019-09-01T12:34:56+09:00
「年/月/日T時:分:秒+時差」というフォーマットです。
詳細はリンク先を見てください。
JavaのAPIドキュメントなどでも、日時を示すときは ISO 8601の拡張形式で書かれていることが多いようです。
以下の説明でも、この表記法を使っていきます。
日時を構成する要素
日時を扱う上で重要な、次の3つの要素について説明していきます。
- 年月日時分秒
- オフセット
- タイムゾーン
1. 年月日時分秒
年月日時分秒は、私たちが日常的に使っている日時のことです。
細かいことを言えば、ミリ秒、ナノ秒の存在もあるのですが、そこまでの精度は必要ないものとしましょう。
ここで注意してほしいのは、年月日時分秒の情報だけでは、現実世界の「時点」を特定することができないということです。
カレンダーと時計を写した写真があったとして、どこの国で撮影されたのか分からなければ、実際の撮影時間を特定することはできませんよね。
2. オフセット
オフセットとは、いわゆる時差のことです。
日時が世界協定時(UTC)から、何時間何分ずれているかを表しています。
地球上の経度とおおよそ連動した値になります。
オフセットを表す、次のような図を見たことがあると思います。
https://commons.wikimedia.org/wiki/File:World_Time_Zones_Map.png
例えば日本なら +09:00(UTCより9時間早い)、ニューヨークなら -05:00(UTCより5時間遅い)といった具合です。
年月日時分秒とオフセットを合わせると、現実世界の一点の時刻を表すことができます。
3. タイムゾーン
タイムゾーンとは、「ある地域が、いつからいつまで、どのオフセットを採用するか」を表す情報です。
端的に言えば、夏時間の実施状況を表す情報です。
2019年現在の日本では、オフセットは一年中+09:00ですが、夏時間のある地域ではオフセットが変動します。
例えば、ロサンゼルスでは、通常-08:00のオフセットが、夏時間中は-07:00となります。
前述の年月日時分秒とオフセットは、定義の問題なので、不確実性はありませんでした。
ところが、このタイムゾーンというのは、政治的な要因でたびたび変更されてしまいます。
そのため、継続的なメンテナンスが必要な項目です。
日本人になじみ深い「元号」と同じような性質のものです。
たとえば、Javaのタイムゾーン関連のAPIは、tz databaseというデータベースを元にしています。
例えば、日本だと”Asia/Tokyo”、米国太平洋時間だと”America/Los_Angeles”のように、都市名を元にしたIDが振られています。
年月日時分秒とオフセットとタイムゾーンの3つを合わせると、ある地域のすべての時点(夏でも冬でも)における日時を表現することができるようになります。
まとめ
- 年月日時分秒(LocalDateTime):\
どこの日時かという情報がないが、日本だけを考えるならこれでも十分。 - オフセット(ZoneOffset):\
いわゆる時差。 - タイムゾーン(ZoneId):\
いつからいつまで夏時間が適用されるのかを表す情報。
参考までに、JavaとC#で該当するドキュメントへのリンクを貼っておきます。
Java | C# | |
---|---|---|
(1)年月日時分秒 | LocalDateTime | DateTime |
(2)オフセット | ZoneOffset | DateTimeOffset |
(3)タイムゾーン | ZoneId | TimeZoneInfo |
(1) + (2) | OffsetDateTime | DateTimeOffset |
(1) + (2) + (3) | ZonedDateTime | 該当なし |