ブログ時間

タイムゾーン、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時」が別の場所では深夜であることが一目でわかります。