「今日の日付を取得したいだけなのに、色々な関数があって迷う…」
「CURRENT_DATEとNOW()って何が違うの?」
「タイムゾーンとか考えると訳わからない…」
PostgreSQLで日付を扱う時、こんな悩みありませんか?
実は、PostgreSQLには現在の日付・時刻を取得する方法がたくさんあるんです。それぞれに特徴があって、使い分けることで、より正確で効率的なデータベース処理ができます。
この記事を読めば、状況に応じて最適な日付取得方法を選べるようになり、タイムゾーンの罠にもハマらなくなります!
今すぐ使える!現在日付を取得する5つの方法

方法1:CURRENT_DATE(日付だけ欲しい時)
一番シンプルに「今日の日付」だけを取得する方法です。
SELECT CURRENT_DATE;
-- 結果: 2024-12-27
-- テーブルに挿入する例
INSERT INTO orders (order_date, product_id)
VALUES (CURRENT_DATE, 100);
特徴:
- 時刻情報なし(00:00:00として扱われる)
- DATE型で返される
- タイムゾーンの影響を受ける
こんな時に使う:
- 営業日の記録
- 誕生日の管理
- 日次レポートの日付
方法2:NOW()(日付と時刻両方欲しい時)
現在の日付と時刻を両方取得する、最もよく使われる関数です。
SELECT NOW();
-- 結果: 2024-12-27 14:30:45.123456+09
-- 作成日時の記録
INSERT INTO posts (title, created_at)
VALUES ('新しい記事', NOW());
特徴:
- TIMESTAMP WITH TIME ZONE型で返される
- マイクロ秒まで記録
- タイムゾーン情報付き
こんな時に使う:
- ログの記録
- 作成・更新日時の管理
- タイムスタンプが必要な処理全般
方法3:CURRENT_TIMESTAMP(NOW()とほぼ同じ)
SQL標準の関数で、NOW()とほぼ同じ動作をします。
SELECT CURRENT_TIMESTAMP;
-- 結果: 2024-12-27 14:30:45.123456+09
-- 精度を指定することも可能
SELECT CURRENT_TIMESTAMP(0); -- 秒まで
-- 結果: 2024-12-27 14:30:45+09
SELECT CURRENT_TIMESTAMP(3); -- ミリ秒まで
-- 結果: 2024-12-27 14:30:45.123+09
NOW()との違い:
- 精度を指定できる
- SQL標準準拠
- 他のデータベースとの互換性が高い
方法4:CURRENT_TIME(時刻だけ欲しい時)
現在の時刻のみを取得します。
SELECT CURRENT_TIME;
-- 結果: 14:30:45.123456+09
-- 精度指定も可能
SELECT CURRENT_TIME(0);
-- 結果: 14:30:45+09
こんな時に使う:
- 営業時間の判定
- 定時処理の時刻記録
- 時刻のみの比較処理
方法5:LOCALTIMESTAMP(タイムゾーンなし)
タイムゾーン情報を含まない現在日時を取得します。
SELECT LOCALTIMESTAMP;
-- 結果: 2024-12-27 14:30:45.123456
-- NOW()との比較
SELECT
NOW() AS with_tz,
LOCALTIMESTAMP AS without_tz;
使い分けのポイント:
- アプリケーション側でタイムゾーンを管理する場合
- すべてのデータを同一タイムゾーンで扱う場合
日付の加工テクニック集
日付の切り捨て・切り上げ
DATE_TRUNCを使って、指定した単位で切り捨てができます。
-- 現在時刻を時間単位で切り捨て
SELECT DATE_TRUNC('hour', NOW());
-- 結果: 2024-12-27 14:00:00+09
-- 月初めの日付を取得
SELECT DATE_TRUNC('month', CURRENT_DATE);
-- 結果: 2024-12-01
-- 週の始まり(月曜日)を取得
SELECT DATE_TRUNC('week', CURRENT_DATE);
使える単位:
- ‘year’:年
- ‘quarter’:四半期
- ‘month’:月
- ‘week’:週
- ‘day’:日
- ‘hour’:時
- ‘minute’:分
- ‘second’:秒
日付の計算
INTERVALを使った日付計算が便利です。
-- 明日の日付
SELECT CURRENT_DATE + INTERVAL '1 day';
-- 1週間前
SELECT CURRENT_DATE - INTERVAL '7 days';
-- 3ヶ月後
SELECT CURRENT_DATE + INTERVAL '3 months';
-- 複雑な計算も可能
SELECT NOW() + INTERVAL '1 year 2 months 3 days 4 hours';
実用例:有効期限の設定
-- 30日間有効なクーポンを作成
INSERT INTO coupons (code, expires_at)
VALUES ('SAVE10', CURRENT_DATE + INTERVAL '30 days');
日付のフォーマット
TO_CHARを使って、好きな形式で表示できます。
-- 日本式の表記
SELECT TO_CHAR(NOW(), 'YYYY年MM月DD日');
-- 結果: 2024年12月27日
-- 曜日付き
SELECT TO_CHAR(NOW(), 'YYYY-MM-DD (Day)');
-- 結果: 2024-12-27 (Friday )
-- 時刻も含めて
SELECT TO_CHAR(NOW(), 'YYYY/MM/DD HH24:MI:SS');
-- 結果: 2024/12/27 14:30:45
-- AM/PM表記
SELECT TO_CHAR(NOW(), 'YYYY-MM-DD HH12:MI:SS AM');
-- 結果: 2024-12-27 02:30:45 PM
よく使うフォーマット文字:
- YYYY:4桁の年
- MM:2桁の月(01-12)
- DD:2桁の日(01-31)
- HH24:24時間制の時(00-23)
- HH12:12時間制の時(01-12)
- MI:分(00-59)
- SS:秒(00-59)
タイムゾーンの扱い方
タイムゾーンの確認と設定
-- 現在のタイムゾーン設定を確認
SHOW timezone;
-- 結果: Asia/Tokyo
-- セッション単位でタイムゾーンを変更
SET timezone = 'America/New_York';
-- UTCに設定
SET timezone = 'UTC';
タイムゾーン変換
AT TIME ZONEを使った変換方法です。
-- 東京時間をニューヨーク時間に変換
SELECT NOW() AT TIME ZONE 'America/New_York';
-- UTCに変換
SELECT NOW() AT TIME ZONE 'UTC';
-- 複数のタイムゾーンで表示
SELECT
NOW() AS tokyo_time,
NOW() AT TIME ZONE 'UTC' AS utc_time,
NOW() AT TIME ZONE 'America/Los_Angeles' AS la_time;
実用例:世界各地の現在時刻
SELECT
'Tokyo' AS city,
(NOW() AT TIME ZONE 'Asia/Tokyo')::TIME AS local_time
UNION ALL
SELECT
'London',
(NOW() AT TIME ZONE 'Europe/London')::TIME
UNION ALL
SELECT
'New York',
(NOW() AT TIME ZONE 'America/New_York')::TIME;
実践的な使用例
デフォルト値として使う
テーブル作成時にデフォルト値として設定する方法です。
-- created_atカラムに自動で現在時刻を設定
CREATE TABLE articles (
id SERIAL PRIMARY KEY,
title VARCHAR(255),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- CURRENT_TIMESTAMPも使える
CREATE TABLE logs (
id SERIAL PRIMARY KEY,
message TEXT,
logged_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
日付での条件検索
-- 今日のデータを取得
SELECT * FROM orders
WHERE order_date = CURRENT_DATE;
-- 過去7日間のデータ
SELECT * FROM logs
WHERE created_at >= CURRENT_DATE - INTERVAL '7 days';
-- 今月のデータ
SELECT * FROM sales
WHERE DATE_TRUNC('month', sale_date) = DATE_TRUNC('month', CURRENT_DATE);
-- 営業時間内の判定(9:00-18:00)
SELECT * FROM appointments
WHERE CURRENT_TIME BETWEEN TIME '09:00:00' AND TIME '18:00:00';
年齢計算
誕生日から現在の年齢を計算する方法です。
-- AGE関数を使う方法
SELECT
name,
birth_date,
AGE(CURRENT_DATE, birth_date) AS age
FROM users;
-- 年数だけ取得
SELECT
name,
EXTRACT(YEAR FROM AGE(CURRENT_DATE, birth_date)) AS age_years
FROM users;
-- 誕生日が今日の人を探す
SELECT * FROM users
WHERE
EXTRACT(MONTH FROM birth_date) = EXTRACT(MONTH FROM CURRENT_DATE)
AND EXTRACT(DAY FROM birth_date) = EXTRACT(DAY FROM CURRENT_DATE);
よくあるトラブルと解決法
トラブル1:タイムゾーンの不一致
-- 問題:異なるタイムゾーンでデータが保存されている
-- 解決:統一的にUTCで保存し、表示時に変換
-- 保存時はUTC
INSERT INTO events (event_time)
VALUES (NOW() AT TIME ZONE 'UTC');
-- 表示時にローカルタイムに変換
SELECT
event_time AT TIME ZONE 'Asia/Tokyo' AS local_time
FROM events;
トラブル2:日付の比較がうまくいかない
-- 問題:TIMESTAMPとDATEの比較
-- NG例
SELECT * FROM orders
WHERE created_at = '2024-12-27'; -- 時刻があるため一致しない
-- OK例
SELECT * FROM orders
WHERE DATE(created_at) = '2024-12-27';
-- または
SELECT * FROM orders
WHERE created_at >= '2024-12-27'
AND created_at < '2024-12-28';
トラブル3:NULL値の扱い
-- COALESCE を使ってNULLの場合のデフォルト値を設定
SELECT
COALESCE(updated_at, created_at, NOW()) AS last_modified
FROM articles;
-- NULLの場合は現在日付を使う
UPDATE tasks
SET completed_at = COALESCE(completed_at, NOW())
WHERE status = 'completed';
パフォーマンスを考慮した日付処理
インデックスを活用した高速検索
-- 日付カラムにインデックスを作成
CREATE INDEX idx_orders_date ON orders(order_date);
-- 範囲検索に有効
CREATE INDEX idx_logs_created ON logs(created_at);
-- 関数インデックスも使える
CREATE INDEX idx_events_month ON events(DATE_TRUNC('month', event_date));
集計処理の最適化
-- 日別の集計
SELECT
DATE(created_at) AS date,
COUNT(*) AS count
FROM orders
WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY DATE(created_at)
ORDER BY date;
-- 時間帯別の分析
SELECT
EXTRACT(HOUR FROM created_at) AS hour,
COUNT(*) AS count
FROM access_logs
WHERE DATE(created_at) = CURRENT_DATE
GROUP BY EXTRACT(HOUR FROM created_at)
ORDER BY hour;
まとめ:状況に応じて最適な日付関数を選ぼう!
ここまで読んでいただき、ありがとうございました!
今すぐ使える選び方ガイド
用途別の使い分け:
- 日付だけ必要 →
CURRENT_DATE
- 日付と時刻が必要 →
NOW()
またはCURRENT_TIMESTAMP
- 時刻だけ必要 →
CURRENT_TIME
- タイムゾーンなし →
LOCALTIMESTAMP
覚えておくべき3つのポイント
- NOW()が最も汎用的
- 大抵の場合はこれでOK
- タイムゾーン付きで安心
- DATE_TRUNCとINTERVALは超便利
- 日付の切り捨てと計算の基本
- これだけで大抵の処理ができる
- タイムゾーンは最初に決める
- UTCで統一するか、ローカルタイムか
- 後から変更は大変
よく使うパターン集
今日のデータ取得:
WHERE DATE(column) = CURRENT_DATE
過去N日間:
WHERE column >= CURRENT_DATE - INTERVAL 'N days'
今月のデータ:
WHERE DATE_TRUNC('month', column) = DATE_TRUNC('month', CURRENT_DATE)
PostgreSQLの日付関数をマスターすれば、時系列データの処理が格段に楽になります。
まずは基本のCURRENT_DATEとNOW()から始めて、徐々に応用的な使い方を覚えていきましょう!
コメント