PostgreSQL EXTRACT(EPOCH) ガイド

PostgreSQLでのUnix timestamp操作ガイド。EXTRACT(EPOCH)、to_timestamp()、timestamptz型の使い方とタイムゾーン処理のベストプラクティス。

Database

EXTRACT(EPOCH FROM NOW())

詳細な説明

PostgreSQLは、適切なタイムゾーン処理が組み込まれた堅牢なtimestampサポートを持っています。EXTRACT(EPOCH FROM ...)関数はtimestampをUnix time(epochからの秒数)に変換し、to_timestamp()はその逆を行います。

基本操作:

-- 現在のUnix timestamp取得(秒、小数部あり)
SELECT EXTRACT(EPOCH FROM NOW());            -- 1700000000.123456

-- 整数の秒に変換
SELECT FLOOR(EXTRACT(EPOCH FROM NOW()));     -- 1700000000

-- 特定のtimestampをepochに変換
SELECT EXTRACT(EPOCH FROM TIMESTAMP '2024-01-15 09:30:00 UTC');

-- Unix timestampをPostgreSQLのtimestampに変換
SELECT to_timestamp(1700000000);
-- '2023-11-14 22:13:20+00'

-- 演算:1時間後のtimestamp
SELECT NOW() + INTERVAL '1 hour';

timestamp vs timestamptz:

PostgreSQLには2つのtimestamp型があります:timestamp(タイムゾーンなし)とtimestamptz(タイムゾーンあり)。よくある誤解に反して、timestamptzはタイムゾーンを格納しているわけではありません。値をUTCで格納し、セッションのtimezone設定に基づいて表示時に変換します。

SET timezone = 'America/New_York';
SELECT '2024-01-15 09:30:00 UTC'::timestamptz;
-- '2024-01-15 04:30:00-05'  (ET東部時間に変換)

SET timezone = 'Asia/Tokyo';
SELECT '2024-01-15 09:30:00 UTC'::timestamptz;
-- '2024-01-15 18:30:00+09'  (JSTに変換)

ベストプラクティス — 常にtimestamptzを使用する: PostgreSQLのドキュメント自体が、ほぼすべてのユースケースでtimestamptzを推奨しています。タイムゾーンなしのtimestampを使用すると、UTC変換なしでリテラル値が保存されるため、サーバーやクライアントが異なるタイムゾーンにいる場合に曖昧になります。

よくある落とし穴:

EXTRACT(EPOCH FROM ...)は整数ではなくdouble precisionの値を返します。比較を行う際にはこれが重要です。正確な整数比較にはFLOOR()を使用するかBIGINTにキャストしてください。また、to_timestamp()は常にtimestamptzを返すため、timestampカラムに代入する際はタイムゾーン変換に注意が必要です。

ミリ秒timestamp: PostgreSQLのtimestamptzはマイクロ秒精度を持ちます。ミリ秒でepochを取得するには:FLOOR(EXTRACT(EPOCH FROM NOW()) * 1000)

ユースケース

PostgreSQLでイベントソーシングシステムを構築する際、EXTRACT(EPOCH)はイベント間の時間差の計算や、API経由で利用するマイクロサービスへのUnix timestampの提供に不可欠です。

Try It — Timestamp Converter

フルツールを開く