

PostgreSQLで前日の日付を出す、Asia/Tokyoなら引き算とタイムゾーン変換の順番は気にしなくていい
この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。
前日の日付を取るクエリを書く機会があったので、やり方を整理した。
やりたいこと
CURRENT_TIMESTAMP(timestamptz型)から前日の日付だけを、Asia/Tokyo基準で取り出す。
クエリ
パターン1: 先にUTCで1日引いてからTokyoに変換
SELECT ((CURRENT_TIMESTAMP - INTERVAL '1 day') AT TIME ZONE 'Asia/Tokyo')::DATE AS yesterday_date;パターン2: 先にTokyoに変換してから1日引く
SELECT (CURRENT_TIMESTAMP AT TIME ZONE 'Asia/Tokyo' - INTERVAL '1 day')::DATE AS yesterday_date;結論から言うと、この2つはAsia/Tokyoである限り結果が一致する。
なぜ一致するか
Asia/TokyoはUTC+9固定でDST(サマータイム)を持たない。だから「UTCで1日引いてからローカルに変換」しても「ローカルに変換してから1日引いて」も、時刻がズレる要因がない。
逆にDSTがあるタイムゾーン(America/New_Yorkなど)だと、この2つの順序で結果が食い違うケースがある。日付をまたぐタイミングでDST切り替えが起きると、UTC側で1日引く操作とローカル側で1日引く操作が別の実時刻を指してしまうため。
型の変換方向のメモ
timestamptz AT TIME ZONE 'zone'→timestamp(タイムゾーンなしのローカル時刻表現)になるtimestamp AT TIME ZONE 'zone'→timestamptzになる
向きが逆になるので、CURRENT_TIMESTAMP(timestamptz)に対して使う場合は前者の変換になる。
より頑健にしたい場合
日付境界を明示したいならdate_truncを使う書き方もある。
SELECT (date_trunc('day', CURRENT_TIMESTAMP AT TIME ZONE 'Asia/Tokyo') - INTERVAL '1 day')::DATE AS yesterday_date;ただしAsia/Tokyo固定の今回のケースでは、上の2パターンのどちらでも問題なく前日の日付が取れる。DSTのあるタイムゾーンを扱う可能性がある場合は、先にローカルタイムゾーンへ変換してから日付演算する方が意図通りになりやすい。