タイムゾーン、UTCオフセット、そしてUTCを保存すべき理由
UTCオフセットとタイムゾーンの違い、サマータイムがオフセットを信頼できないものにする理由、そしてほとんどの日付バグを防ぐルール。UTCを保存し、境界で変換します。
「東京は今何時ですか?」は、答えが一つしかない一つの質問のように 聞こえます。しかしソフトウェアは絶えずこれを間違えます。会議の時刻が 一時間ずれたり、サマータイムの切り替え後にタイムスタンプがずれたり、 ログとデータベースが別の値を示したりします。そのほとんどは、二つの 異なるものを混同することに行き着きます。一つはUTCからの固定された オフセットであり、もう一つは年間を通じてオフセットが変わる名前付きの タイムゾーンです。この区別をはっきりさせれば、ほとんどの日付処理が 解決します。
UTCが基準です
UTC(協定世界時)は世界共通の基準時計です。UTCはサマータイムに 従わず、決してずれません。他のすべての地域時刻は、UTCを基準とした オフセットとして表現されます。日本はUTC+9、ニューヨークは冬に UTC-5です。UTCは「同じ瞬間」をどこでも表現できるようにするアンカーで あり、だからこそ保存すべき対象です。
オフセットはタイムゾーンではありません
これが核心的な混同です。UTC+9はオフセット、つまり固定された
時間数です。Asia/Tokyoはタイムゾーン、つまりどのオフセットが
いつ適用されるかについてのルールを持つ名前付きの地域です。この違いが
重要なのは、多くのゾーンが年間を通じてオフセットを変えるからです。
America/New_Yorkは冬にUTC-5、サマータイム下の夏にUTC-4です。Asia/Tokyoは一年中UTC+9で、DSTはありません。
したがって、ニューヨークのイベントに「UTC-5」を保存すると一年の半分は
間違いです。America/New_Yorkを保存すれば正しく、ゾーンが自身のDST
ルールを知っているからです。オフセットはスナップショットであり、
タイムゾーンはルールブックです。
サマータイムこそオフセットが破綻する場所です
DSTは時刻バグの最大の単一原因です。なぜならオフセットがある日付で 変わり、その移行日には意外なことが起きるからです。
- 春には時計が前に進みます。午前2時30分のような地域時刻は、移行日には 存在しません。
- 秋には時計が後ろに戻ります。午前1時30分が二度発生するため、 地域タイムスタンプはあいまいになります。
固定オフセットとして保存された将来の会議は、DST切り替えの反対側で 一時間ずれます。ゾーン名と地域時刻として保存すれば、その日付で有効な ルールでUTCへの変換が計算されるため、正しく保たれます。
IANAタイムゾーンデータベース
Europe/Londonのようなゾーン名は、IANAタイムゾーンデータベース
(tzまたはzoneinfoとも呼ばれます)から来ています。これはゾーンを
その歴史的および現在のオフセットルールに対応づける共有データセットです。
政府がDST方針やオフセットを変更するたびに年に数回更新されます。だから
こそランタイムのtzデータを最新に保つことが重要です。命名に注意して
ください。ゾーンはRegion/City(America/Sao_Paulo)であり、一つの国が
複数のゾーンにまたがりうるため、国ではなく代表的な都市を使います。
ほとんどのバグを防ぐルール
UTCを保存してください。地域時刻への変換は境界でのみ、つまりユーザーに 表示するときにのみ行い、後でユーザーの地域時刻を再構築する必要がある ときは、オフセットではなくユーザーのタイムゾーン名を保存してください。
この一つの規律が、問題の一群全体を回避します。内部ではすべてがUTCで あるため、比較、ソート、算術があいまいになりません。表示時の変換は ゾーンの現在のルールを使います。例外は将来の地域イベントです。 たとえば来年3月の午前9時の歯科予約のような場合、地域時刻とゾーン名を 保持し、UTCへの解決を遅らせるべきです。それまでにDSTルールが変わる 可能性さえあるからです。
タイムスタンプがUnixエポック値であれば、それは定義上すでにUTCです。 1970-01-01 UTC以降の秒数であり、ゾーンは付いていません。これは Unixタイムスタンプと2038年問題 と併せて理解する価値のある点です。一つの瞬間を複数のゾーンで一度に 比較するには、当サイトの世界時刻ツールが複数の ゾーンの現在時刻をDSTを含むオフセットとともに表示するので、 「ここでは午後3時」が別の場所では深夜であることが一目でわかります。