データ品質

夏時間の切り替えと、その前後で壊れるリクエスト

夏時間を採用しているタイムゾーンでは、年に2回、ほとんどのソフトウェアが考慮していない奇妙なことが時計に起こります。時計が進むときには、現地時刻の1時間がまるごと存在しなくなるため、その日の「午前2:30時」のようなタイムスタンプは実際には一度も発生しません。時計が戻るときには、1時間が2回発生するため、「午前1:30時」は切り替え前に1回、切り替え後に1回発生し、ほかの情報を持たない単なる現地時刻のタイムスタンプでは、どちらを指しているのか判断できません。

これは特殊な用途でしか問題にならない、まれなエッジケースではありません。夏時間を採用しているすべてのタイムゾーンで毎年繰り返される日常的なカレンダー上の出来事であり、現地時刻が常に明確に定まっているものとして扱うコードを、気づかないうちに壊します。予約時点のUTCオフセットを保存せずに「午前1:45時で予約」とだけ保存するスケジュールシステムでは、予約が切り替えの夜にあたる場合、数か月後に2つある午前1:45時のどちらが意図されていたのかを知ることができません。

最も安全なやり方は、内部ではあらゆる場所でタイムスタンプをUTCで保存し、表示するときだけ現地時刻に変換することです。UTCには夏時間も曖昧さもないため、一度その形で時点を記録すれば、その後現地の時計のルールに何が起きても正しいままです。ユーザーの現地タイムゾーンへの変換は、ユーザーに表示する時点でのみ、その特定の時点におけるそのタイムゾーンの現在のルールを使って行ってください。だからこそ、オフセットを一度キャッシュして使い回すのではなく、場所だけでなく特定の時点を受け付けるタイムゾーン検索を使う価値があるのです。

イベントのスケジュール設定や記録を行うものを構築するなら、明示的にテストする価値のあるエッジケースとして、春の時計が進む切り替えで存在しない時間帯に入れられた予約、秋の時計が戻る切り替えで繰り返される時間帯のタイムスタンプ、そして作成時から発生時までの間に切り替えをまたぐ日付の予定イベントがあります。どれも仮定の話ではありません。これらは毎年、決まった予測可能な日程で発生します。開発中に一度テストしておくほうが、1時間ずれたように見える会議についてのサポートチケットをデバッグするよりもはるかに安く済みます。

システムがタイムゾーン名だけでなく特定の時点の正しいオフセットを必要とする場合は、キャッシュした値から導き出すのではなく、直接リクエストしてください。My Geocodeのタイムゾーン検索は特定の時点を受け付け、その日付の夏時間のルールを適用するため、切り替えのちょうど境目であっても正しいオフセットが返されます。