SQLでは、日時やインターバルを扱うための関数が豊富にあります:DATEDIFF、DATEADD(T-SQL)、INTERVAL型の操作(PostgreSQL)、異なるタイムゾーンへの時間変換機能(AT TIME ZONE)など。日時を正しく処理するためには、タイムゾーンを考慮したデータ型(TIMESTAMP WITH TIME ZONE、timestamptz)を使用することが重要で、単にDATEやDATETIMEを使用するべきではありません。特にグローバルなサービスの場合はなおさらです。
異なるDBMSによって、構文と機能が異なります:
DATEDIFF、DATEADD、FORMATが使用できるが、完全なINTERVALはありません。タイムゾーンを明示的に管理します。UTC/ローカル時間の不一致や、違いを考慮しない操作の混同から、エラーが発生することがよくあります。
SELECT EXTRACT(EPOCH FROM (event_end AT TIME ZONE 'UTC' - event_start AT TIME ZONE 'UTC')) / 3600 AS hours FROM events
DATEDIFFでの日時の差が負の数になることはありますか?また、その順序は何を意味しますか?
回答:はい、DATEDIFF(DATEDIFF(day, d1, d2))は、d2 < d1の場合、負の数を返します。パラメータの順序を混同しないことが重要です:最初に単位、次に開始日、最後に終了日が続きます。
例:
SELECT DATEDIFF(day, '2024-05-01', '2024-04-25') -- -6を返します
物語
グローバルユーザーを対象としたプロジェクトで、各地域のサーバーのローカル時間に基づいてレポートが生成されました。その結果、異なるタイムゾーンのユーザー向けに日付がずれ、日付の境界に"穴"ができました。すべての日時データをUTCに変換し、表示のためにのみ再計算することで修正しました。
物語
DATEDIFFを使用してサブスクリプションの期間を計算する際、日付の順序を誤って解釈しました。その結果、一部のユーザーが意図的に負の遡及期間を持つ"スーパーユーザー"と誤って認識されました。日付の順序をチェックすることで修正しました。
物語
開発者がタイムゾーンを考慮せずにDATETIMEを保存していたため、PostgreSQLに移行した際に値がUTCとして解釈され、元々はGMT+3だったため、レポート内のイベントが3時間前にずれてしまいました。結論として、常にゾーンを考慮して日付を保存・変換することが重要です!