CodeGym /コース /SQL SELF /日付と時間の扱いでありがちなミス

日付と時間の扱いでありがちなミス

SQL SELF
レベル 32 , レッスン 4
使用可能

今日はまたミスの話をしようと思う。だって日付や時間を扱うのって、地雷原を歩くようなもんでさ、最初の一歩を踏み外すまでは大丈夫なんだけどね。

データ型の選び方のミス

ここが全てのトラブルの始まりだったりする。データ型を間違えて選ぶと、日付や時間の扱いが全部台無しになることもあるよ。

ケース1: DATETIMESTAMPの代わりに使っちゃう

イベントが日付だけじゃなくて時間も持ってるのに、DATEだけで記録しちゃうと、大事な情報を失うことになる。

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    order_date DATE -- 日付だけ
);

こんな設計だと、朝と夜に注文があったかどうかも分からない。せっかくコーヒー飲みながら、きれいなタイムスタンプを眺めるチャンスを逃すことになるよ?

ケース2: タイムゾーンを忘れる

アプリが海外ユーザーにも対応してるのに、TIMESTAMPだけで日付と時間を保存して、タイムゾーンを考慮しないと、データが「ホームレス」状態になる。TIMESTAMPTZならこの問題を解決できるよ。

CREATE TABLE events (
    event_time TIMESTAMP -- タイムゾーンなし
);

誰もニューヨークの夜のイベントと東京の朝のイベントを間違えたくないでしょ。TIMESTAMPTZを使おう!

関数の使い方のミス

ケース1: TO_CHAR()のフォーマットミス

フォーマットを間違えると、問題が始まる。例えば:

SELECT TO_CHAR(NOW(), 'YYYY-DD-MM'); -- あっ、月と日を逆にしちゃった

これだと普通の年-月-日じゃなくて、年-日-月になっちゃう。ユーザーにとっては笑える(けど嬉しくない)状況になるかも。フォーマットは必ずチェックしよう。

ケース2: TO_DATE()の使い方ミス

逆に、文字列を日付に変換しようとしてフォーマットが合ってないと、PostgreSQLはエラーを返す。

SELECT TO_DATE('10/31/2023', 'YYYY-MM-DD'); -- エラー!フォーマットが合ってない。

文字列のフォーマットは、指定したものとピッタリ合ってないとダメ。例えば:

SELECT TO_DATE('2023-10-31', 'YYYY-MM-DD'); -- これならOK。

時間のインターバルでのミス

ケース1: 暗黙の型変換を忘れる

型変換のクセを忘れがち。例えば:

SELECT NOW() + '1'; -- エラー!'1'って何?

PostgreSQLは「1日足したい」って意味が分からない。正しいやり方は:

SELECT NOW() + INTERVAL '1 day';

ケース2: インターバルの引き算で混乱

インターバルを足したり引いたりする時は注意:

SELECT NOW() - INTERVAL '-1 day'; -- これだと1日足しちゃう!

マイナスが二重になると逆の効果になる。こういう書き方は避けよう。

丸めや切り捨てのミス

ケース1: DATE_TRUNC()の切り捨てミス

DATE_TRUNC()でデータをグループ化する時は、ちゃんと必要なレベルを選んでるか確認しよう。例えば:

SELECT DATE_TRUNC('hour', NOW()); -- 時間の先頭に切り捨て
SELECT DATE_TRUNC('minute', NOW()); -- 分の先頭に切り捨て

期待した結果と違うなら、レベルの選び方を間違えてるかも。

ケース2: DATE_TRUNC()でタイムゾーンを忘れる

いろんなタイムゾーンの時間を扱う時、結果が予想外になることも:

SELECT DATE_TRUNC('day', NOW() AT TIME ZONE 'UTC');

タイムゾーンがちゃんと指定されてるか確認しないと、本当に時間の迷子になるよ。

Unix時間:失われた秒

Unix時間(EPOCH)は便利だけど、ちょっとクセがある。よくあるミスは、秒とミリ秒を混同しちゃうこと。

SELECT TO_TIMESTAMP(1680000000); -- これが正しい(秒)。
SELECT TO_TIMESTAMP(1680000000000); -- これはミス!ゼロが多すぎ。

タイムスタンプが何単位か、ちゃんと確認して、余計な秒を保存しないようにしよう。

タイムゾーンでのミス

ケース1: ややこしいタイムゾーン

いろんなタイムゾーンのユーザーとやりとりしてると、データが混ざっちゃうことも。例えば:

SELECT TIMESTAMP '2023-10-01 10:00:00' AT TIME ZONE 'UTC';

どのタイムゾーンのデータなのか、ちゃんと把握しておこう。

ケース2: タイムゾーンの二重指定

日付と時間を保存してから、さらにタイムゾーンを指定しようとするのはNG:

SELECT TIMESTAMP '2023-10-01 10:00:00 UTC' AT TIME ZONE 'UTC'; -- こういうのはやめよう!

これだと計算が間違っちゃう。

ミスを防ぐためのアドバイス

適切なデータ型を選ぼう。 国際的な時間データを扱うならTIMESTAMPTZを使おう。日付だけで十分ならDATEでOK。

クエリをテストしよう。 結果が期待通りか必ず確認しよう。特にインターバルやフォーマット、丸め処理を使う時は注意。

時間データはUTCで保存しよう。 タイムゾーンの混乱を避けるにはこれが一番。

フォーマットを確認しよう。 TO_CHAR()TO_DATE()のフォーマットがデータと合ってるかチェックしよう。

関数は慎重に使おう。 PostgreSQLの時間系関数のドキュメントをちゃんと読んで、思わぬトラブルを避けよう。

時間データの扱いは簡単じゃないけど、ちゃんと気をつけてやればスムーズにいくよ。日付と時間はアプリの大事な部分だし、月曜の朝にアラームかけ忘れるくらい危険だからね!

1
アンケート/クイズ
タイムゾーンの扱い、レベル 32、レッスン 4
使用不可
タイムゾーンの扱い
タイムゾーンの扱い
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION