※ この記事にはアフィリエイトリンクが含まれます
日付の差分を扱うときに戸惑っていませんか?
・日付型とタイムスタンプの違いがわからず結果が変わる
・日付同士の引き算や月単位・年単位の差分がうまく取れない
・タイムゾーンや閏年を考慮する必要があるか迷ってしまう
結論から言うと、PostgreSQLでは日付差分を正確に扱うための関数と演算子が充実しています。
・単純な日数は「date – date」で取得可能です。
・年・月・日までの差を人間向けに扱うならage()を使います。
・秒やミリ秒単位で差を取るならextract(epoch from ...)を使います。
この記事では、PostgreSQLで日付差分を安全かつ効率的に扱うための基本操作
から実践的なテクニック、よくある落とし穴と対策までを、初心者向けに丁寧に解説します。
日付型とタイムスタンプの違いを理解する
まずは基本用語から確認しましょう。
PostgreSQLには主にdateとtimestampという型があります。
dateは日付のみを表します。
時刻やタイムゾーンの情報は含みません。
一方、timestampは時刻も含む型です。timestamp with time zone(略してtimestamptz)という型もあり、
タイムゾーンを考慮した時刻処理ができます。
なぜ違いを意識する必要があるか
日付だけを比較する場合はdate同士で問題ありません。
しかし、時刻が絡むと同じ瞬間でもタイムゾーンや夏時間で結果が変わります。
間違えてtimestamp with time zoneをdateと混在させると
意図しないオフセット処理が走ることがあります。
型に注意して使い分けることが重要です。
基本操作:日数の差を求める
最もシンプルなのはdate型同士の引き算です。
結果はinterval型ではなく整数(日数)になります。
SELECT '2026-03-01'::date - '2026-02-20'::date AS days_diff;このクエリは11を返します。
日数の差を求める分にはこれで十分です。
timestamp同士の差
timestamp同士を引くとinterval型が返ります。intervalは年・月・日・時間・分・秒を保持できます。
SELECT '2026-03-01 12:00'::timestamp - '2026-02-28 09:30'::timestamp AS diff_interval;上の例では”2 days 2:30:00″のような形式で返ります。
これを日数や秒に変換して使うことも可能です。
年・月・日を人間向けに求める(age関数)
年や月での差分を自然な表現で取得したいときはage関数が便利です。
年・月・日を考慮した差分をintervalで返します。
SELECT age('2026-03-01'::date, '1990-06-15'::date) AS human_age;上のクエリは”35 years 8 mons 14 days”のように返します。
生年月日から年齢を計算する際によく使われます。
ageの注意点
ageは年や月を考慮して差を出すため、単純な日数換算と結果が異なることがあります。
“1 month”が常に30日ではない点を理解しておきましょう。
秒やミリ秒単位で差を扱う(epoch)
秒やミリ秒単位の差が必要な場合はextract(epoch from interval)を使います。
これでintervalを秒数に変換できます。
SELECT extract(epoch FROM (timestamp '2026-03-01 12:00' - timestamp '2026-02-28 09:30')) AS seconds_diff;戻り値は小数を含む数値(秒)です。
必要に応じて整数に切り捨てや丸めを行ってください。
よくある具体例とSQL(初心者向け)
1) ユーザー登録からの経過日数を求める
登録日(register_date)から今日までの経過日数を取得する場合の例です。date型で管理している前提でシンプルに書けます。
SELECT id, current_date - register_date AS days_since_signup
FROM users;この結果は整数(days)になります。
レポートや条件式にそのまま使えます。
2) 2つのタイムスタンプ間の秒数を取る
ログの開始と終了の差を秒で取得したい場合です。extract(epoch from ...)を利用します。
SELECT id,
extract(epoch FROM (end_time - start_time)) AS duration_seconds
FROM tasks;秒数をミリ秒にしたいときは*1000をしてください。
数値型のまま集計しやすいです。
3) 生年月日から年齢を求める
年齢を正しく表示するにはageを使い、yearsを抽出します。
その後整数部分だけを取りたい場合の例です。
SELECT id,
date_part('year', age(current_date, birth_date))::int AS age_years
FROM persons;この方法なら閏年や月の日数差を気にせずに年数が取れます。
ただし生年月日がdate型であることを確認してください。
よくある落とし穴と対策
型の不一致に注意する
dateとtimestampを無理に計算すると意図しない型変換が起きます。
明示的に::dateや::timestampで型変換しておくと安全です。
特にtimestamp with time zoneを扱う場合は注意が必要です。
アプリ側とDB側でタイムゾーンの取り扱い方針を統一しましょう。
月や年の差分は単純換算に注意
「1ヶ月=30日」と決め打ちするとズレが出ます。
人間向けの差(年月日)を出すならage、その後date_partなどで抽出するのが良いです。
日付の境界(タイムゾーン・夏時間)
夏時間やタイムゾーンの影響で同じ日の瞬間がずれることがあります。
グローバルなサービスではtimestamp with time zoneを推奨します。
パフォーマンス面の注意
インデックスが効くかどうかはクエリの書き方で変わります。
関数をWHERE句で使うとインデックスが無効化されることがあります。
可能ならクエリ側で計算した固定値の範囲を指定して、
演算子や関数の使用を最小限にすると高速化できます。
よく使う便利テクニック
固定期間のフィルタ(例:過去30日)
過去30日分のレコードを取得する例です。date型ならcurrent_dateを使うとわかりやすいです。
SELECT * FROM events
WHERE event_date >= current_date - 30;timestampの場合はnow() - interval '30 days'のように書きます。intervalは柔軟に使えます(’1 month’, ‘2 years’など)。
日付を丸める(例:日単位・月単位)
日付を日単位や月単位で丸めたい場合はdate_trunc関数を使います。
集計時に便利です。
SELECT date_trunc('day', created_at) AS day_start, count(*)
FROM logs
GROUP BY 1;
SELECT date_trunc('month', created_at) AS month_start, count(*)
FROM logs
GROUP BY 1;date_truncの第一引数は’year’,’month’,’day’,’hour’などが使えます。
集計の粒度を揃えたいときに役立ちます。
まとめ:初心者が押さえるべきポイント
最後に本記事のポイントを整理します。
日付差分を正しく扱うために知っておくべき基本です。
dateは日付のみ、timestampは時刻を含む。型を意識する。- 日数はdate – dateで整数。
timestamp差はinterval。 - 年・月・日を人間向けに得るならage()を使う。
- 秒単位の差は
extract(epoch from ...)で取得。 - タイムゾーンや夏時間は
timestamptzで統一管理すること。
これらを押さえれば、一般的な日付差分の課題はほぼ解決できます。
実際のデータで試してみてください。役に立つ操作の多くはシンプルです。
もし具体的なテーブル構成や目的があれば、実例に合わせた最適なクエリを
さらに詳しく一緒に考えることもできます。お気軽にご相談ください。
postgreSQLは、現場でも広く使われている信頼性の高いデータベースです。もしこれから本格的に学び、実務で通用する力をつけたい方には、RareTECHをチェックしてみてください。実案件ベースのカリキュラムで、あなたのスキルを次のステージへ引き上げてくれるはずです。
なんくる「本当にエンジニアとしてやっていけるか不安…」という方も、実践的な開発に関わることで、転職後の働き方を事前に体感できますよ。
実務で使えるDBスキルとともに、プログラミングスキルをちゃんと身につけたいなら、
RareTECHの無料カウンセリングで、学ぶ目的やゴールをプロと一緒に明確にしてみましょう。独学では得られない「実践的な成長の道筋」が見えてきます。


もしこの内容を通して、PostgreSQLについてさらに理解を深めたいと感じられたなら、信頼できる講座や書籍を紹介した別記事をご覧いただくのも良いかと思います。ご自身の学びに、きっとお役立ていただけるはずです。










コメント