はじめに
PostgreSQLを業務で使っていると、意外と混乱しやすいのが「データ型」です。
日付や時刻を扱う場面では、型を間違えたり、型変換が必要だったりと手間取ることが多いです。
私は、特にinterval型に何度も悩まされました。
そこで今回は、日付・時刻まわりのデータ型を整理し、実際によく使うSQLを書きながら振り返ってみたいと思います。
日付・時刻
PostgreSQLには、date型、timestamp型、time型、interval型など、いくつかの型があります。
その中でも日付の計算やフォーマット変換はよく使用しているので、代表的なパターンを整理していきます。
interval型について
まず、個人的に一番つかみにくいinterval型から。
これは「時間の長さ」を表すデータ型で、数値と単位をセットにして扱います。
例えば「1日」や「2時間30分」といったものを保持できます。
日付や時刻に足したり引いたりすることで、柔軟に計算できるのが特徴です。
よく使うSQL例
文字を日付に変える
文字列を date型 に変換するには to_date を使います。
select to_char(to_date('2025-09-27', 'YYYY-MM-DD'), 'YYYY/MM/DD');
-- 実行結果: 2025/09/27
select to_char(to_date('2025-09-27', 'YYYY-MM-DD'), 'YYYY年MM月DD日');
-- 実行結果: 2025年09月27日
- timestamp型を日付に変える
select to_char('2025-09-27 20:38:40'::timestamp , 'YYYY/MM/DD');
-- 実行結果: 2025/09/27
- 現在の日付から自分の年齢を算出
select EXTRACT(YEAR FROM AGE(CURRENT_DATE, TO_DATE('2005-09-27', 'YYYY-MM-DD')));
-- 実行結果: 20 (実行日が2025年09月27日の場合)
select to_char(
date_trunc('month', '2025-09-27'::date) -- 月初に切りそろえる
+ '1 month'::interval -- 翌月の月初に進める
- '1 day'::interval, -- 1日戻る = 当月末
'YYYY/MM/DD'
);
-- 実行結果: 2025/09/30
- 日付の連番を生成する
以下のSQLは指定した期間の日付を1日ごとに生成するSQLです。
select generate_series(
to_timestamp('2025-09-01'||'00:00:00', 'YYYY-MM-DDHH24:MI:SS'),
to_timestamp('2025-09-30'||'00:00:00', 'YYYY-MM-DDHH24:MI:SS'),
'1 day'::interval
) as SerialDate;
-- 実行結果
2025-09-01 00:00:00
2025-09-02 00:00:00
2025-09-03 00:00:00
2025-09-04 00:00:00
2025-09-05 00:00:00
2025-09-06 00:00:00
2025-09-07 00:00:00
――――――――――――――――――
個人的な疑問点
- なんでこんなに色々とデータ型がある?
- 国ごとに日付・時刻のフォーマットが違ったりするのでそれが影響している?
- データ型を毎回確認するのが面倒
- ちゃんと設計を統一しないと各テーブルに違うデータ型が入ることがある
- PostgreSQL関数を使って各データ型ごとに変換する処理を組み込めば比較的楽になる?
- その場合パフォーマンスはどうなる?
- EXTRACTとAGEを使った年齢算出で、日付まで参照した年齢算出できる?
- うるう年の場合は、date型に影響がある?
おわりに
PostgreSQLのデータ型は一見複雑に思えますが、特徴をつかめば強力な武器になります。
特にinterval型は最初わかりにくいですが、「日付に足す・引く」「繰り返しを作る」といった処理に役立ちます。
今後も実際の業務でつまずいたときに振り返り、少しずつ整理していきたいと思います。