メインコンテンツへ
プログラミング

データベースの日時設計 - カラム型の選択から多タイムゾーン対応まで

カラム型の選択 - DATE, TIME, TIMESTAMP, TIMESTAMPTZ

データベースの日時型は用途に応じて使い分ける必要があります。DATE は日付のみ (2026-05-15)、TIME は時刻のみ (14:30:00)、TIMESTAMP は日付と時刻の組み合わせ (2026-05-15 14:30:00) を格納します。PostgreSQL の TIMESTAMPTZ (TIMESTAMP WITH TIME ZONE) は入力をUTC に変換して保存し、取得時にセッションのタイムゾーンで返す特殊な型です。

最も重要な設計判断は「この日時データにタイムゾーン情報が必要か」です。イベントの発生時刻 (ログ、トランザクション) は絶対的な瞬間を表すため TIMESTAMPTZ が適切です。一方、誕生日や記念日は特定のタイムゾーンに依存しない「日付」であり DATE で十分です。営業時間 (9:00〜18:00) はタイムゾーンなしの TIME が適切ですが、どのタイムゾーンの時刻かは別途管理が必要です。

予約システムの設計 - 「現地時間」を保持する必要性

ホテルやレストランの予約システムでは、予約時刻は施設の現地時間で意味を持ちます。「東京のレストランを 19:00 に予約」という情報は、UTC に変換して 10:00 として保存すると、サマータイムのない日本では問題ありませんが、ニューヨークのレストランでは季節によって UTC オフセットが変わるため、保存時と表示時で異なる現地時間になるリスクがあります。

この問題の解決策は、TIMESTAMPTZ に加えて施設のタイムゾーン名 (IANA 名) を別カラムに保存することです。表示時には保存されたタイムゾーンで TIMESTAMPTZ を変換し、常に正しい現地時間を表示できます。あるいは、予約時刻を TIMESTAMP (タイムゾーンなし) で「現地時間そのまま」保存し、タイムゾーン名を別カラムに持つ方式も有効です。

イベント管理の設計 - 将来の日時とタイムゾーン変更

将来のイベント (来年のカンファレンス、数か月後の定期会議) の日時を保存する際は、特有の問題があります。イベントの開催国がサマータイムの規則を変更した場合、UTC で保存された時刻は正しい現地時間を指さなくなります。たとえば「2027 年 3 月 15 日 10:00 ニューヨーク時間」を UTC (15:00) で保存した後、アメリカがサマータイムを廃止すると、正しい UTC は 14:00 に変わります。

この問題への対策は、将来のイベントは「ローカルタイム + タイムゾーン名」で保存し、UTC への変換は表示時やリマインダー送信時に動的に行うことです。IANA データベースが更新されれば、変換結果も自動的に正しくなります。過去のイベント (既に発生済み) は UTC で保存して問題ありません。

監査ログの設計 - 改ざん検知と時系列の保証

監査ログのタイムスタンプは、イベントの発生順序を証明する法的な証拠となりうるため、最も厳密な設計が求められます。TIMESTAMPTZ を使用し、アプリケーションサーバーの時刻ではなくデータベースサーバーの NOW() 関数で生成することで、クライアント側の時刻操作による改ざんを防止します。

分散システムでは、複数のデータベースノード間で時刻が微妙にずれる可能性があります。厳密な順序保証が必要な場合は、単調増加するシーケンス番号をタイムスタンプと併用するか、前述の HLC (Hybrid Logical Clock) を採用します。金融規制 (MiFID II など) では取引のタイムスタンプにマイクロ秒精度と UTC への追跡可能性が要求されるため、NTP/PTP による時刻同期の監視も設計に含める必要があります。

既存システムの移行 - タイムゾーン非対応からの脱却

タイムゾーンを考慮せずに設計された既存システムを移行する際は、まず「現在のデータがどのタイムゾーンを暗黙的に仮定しているか」を特定する必要があります。日本で開発されたシステムなら JST、AWS 上のシステムなら UTC が仮定されていることが多いですが、混在している場合もあります。

移行手順としては、新しい TIMESTAMPTZ カラムを追加し、既存データを適切なオフセットで変換して格納し、アプリケーションを新カラムに切り替え、検証後に旧カラムを削除する段階的アプローチが安全です。一括変換時には、サマータイムの切り替え日のデータが正しく変換されているか (特にオーバーラップ期間のデータ) を重点的に検証します。

XB!LINE

この記事は役に立ちましたか?

関連記事