CodeGym /コース /SQL SELF /タイムゾーンの扱い: TIMEZONE

タイムゾーンの扱い: TIMEZONE

SQL SELF
レベル 32 , レッスン 2
使用可能

例えば、航空券予約アプリを作ってるとしよう。フライトはニューヨーク現地時間で10:00に出発して、ロンドン現地時間で22:00に到着する。でもタイムゾーンを無視すると、サーバーが到着時間をめちゃくちゃに表示しちゃうかも。

タイムゾーンは、君の一番の味方(でも、うまくいかない時は最悪の敵)。ユーザーがいろんな国にいたり、現地時間に依存するスケジュール(例えばフライト時間やイベントの予定)を扱うなら、タイムゾーンの考慮は超重要だよ。

時間データ型の種類

すでに話したけど、タイムスタンプを扱うデータ型は2つある:

  • TIMESTAMP: 日付と時間(タイムゾーンなし)。
  • TIMESTAMPTZ: 日付と時間(タイムゾーンあり)。

もう一度、例で見てみよう。

-- 2つのカラム(TIMESTAMPとTIMESTAMPTZ)でテーブルを作成
CREATE TABLE flight_schedule (
    flight_id SERIAL PRIMARY KEY,
    departure_time TIMESTAMP,
    departure_time_with_tz TIMESTAMPTZ
);

-- データを挿入
INSERT INTO flight_schedule (departure_time, departure_time_with_tz)
VALUES
    ('2023-10-25 10:00:00', '2023-10-25 10:00:00+00');

-- データを確認
SELECT * FROM flight_schedule;

結果はサーバーのタイムゾーンによって変わるよ。例えば:

flight_id departure_time departure_time_with_tz
1 2023-10-25 10:00:00 2023-10-25 10:00:00+00

ポイントはここ:

  • departure_timeカラムは、単に日付と時間をタイムゾーンなしで保存してるだけ。
  • departure_time_with_tzカラムは、日付と時間にタイムゾーン情報(この場合は+00)も一緒に保存してる。

時間を別のタイムゾーンに変換する

PostgreSQLでタイムゾーンを扱うには、AT TIME ZONE関数を使うよ。

UTCからローカル時間への変換

例えば、UTC(協定世界時)形式のタイムスタンプがあるとしよう。これをAmerica/New_Yorkタイムゾーンのユーザー向けに表示したい場合:

SELECT
    '2023-10-25 14:00:00+00'::TIMESTAMPTZ AT TIME ZONE 'America/New_York' AS local_time;

結果:

local_time
2023-10-25 10:00:00

AT TIME ZONEはまるで魔法みたいに、UTCから指定したタイムゾーンに時間を変換してくれる。

ローカル時間からUTCへの変換

今度は逆に、America/New_Yorkの時間をUTCに変換したい場合:

SELECT
    '2023-10-25 10:00:00'::TIMESTAMP AT TIME ZONE 'America/New_York' AS utc_time;

結果:

utc_time
2023-10-25 14:00:00+00

結果はTIMESTAMPTZ形式になるよ。なぜならタイムゾーン(この場合はUTC)情報も含まれるから。

TIMESTAMPTZデータ型の扱い

TIMESTAMPTZを使うと、PostgreSQLはサーバーのタイムゾーン(または自分で指定したもの)を自動的に考慮してくれる。

現在のセッションのタイムゾーンを設定するには、次のコマンドを使う:

SET TIMEZONE = 'Europe/Istanbul';

これ以降、TIMESTAMPTZを使った操作はこのタイムゾーンで行われるよ。

例:データの挿入と取得

-- タイムゾーンを設定
SET TIMEZONE = 'Europe/Istanbul';

-- データを挿入
INSERT INTO flight_schedule (departure_time_with_tz)
VALUES ('2023-10-25 10:00:00+00');

-- データを確認
SELECT departure_time_with_tz FROM flight_schedule;

Europe/Istanbulタイムゾーンでの結果:

departure_time_with_tz
2023-10-25 13:00:00+03

PostgreSQLは指定したタイムゾーンを考慮して、UTCから自動的に時間を変換してくれる。

実践例

スケジュールのタイムゾーン考慮。 例えば、フライトスケジュールのテーブルがあって、各レコードはUTCで出発時間を保存してるとしよう。各フライトの出発時間をローカル時間で表示したい場合:

SELECT
    flight_id,
    departure_time_with_tz AT TIME ZONE 'America/New_York' AS local_time
FROM flight_schedule;

異なるタイムゾーンの時間データの比較。 例えば、別々の都市で起きた2つのイベントを比較したい場合。PostgreSQLは自動的に同じタイムゾーンに揃えて比較してくれるよ。

SELECT
    '2023-10-25 10:00:00+03'::TIMESTAMPTZ > '2023-10-25 07:00:00+00'::TIMESTAMPTZ AS event_one_later;

結果:

event_one_later
t

比較結果はtrue。なぜなら10:00+0307:00+00と同じだから。

コツとよくある落とし穴

時間を扱うのは本当にややこしい。よくあるミスはこんな感じ:

  • TIMESTAMPTIMESTAMPTZの代わりに使って、「なんで時間が合わないの?」ってなる(タイムゾーンが無視されてるから)。
  • サーバーがどのタイムゾーンで動いてるか知らずに、データを挿入した時間と取得した時間がズレる。
  • AT TIME ZONEでタイムゾーン名を間違えて、エラーや変な時間になる。

こうならないために:

  • ほとんどの場合、TIMESTAMPTZを使おう。特にタイムゾーンに依存するデータなら必須。
  • 時間はUTCで保存して、表示時にユーザーのタイムゾーンに変換しよう。
  • もっと詳しく知りたいなら、PostgreSQL公式ドキュメント(時間とタイムゾーン)が超便利だよ。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION