はじめに
Webアプリを作っていて、「日付フィルターをかけたのにデータが漏れる」現象に出くわしたことはありませんか?
今回は、実際に私が体験した 「日付フィルターのタイムゾーン落とし穴」 を解説します。 私と同じく、初心者の方でも理解できるよう、仕組み・原因・解決策までしっかりまとめました。
■ 発生した問題
Vue.jsの画面で「2024-03-25のデータ」を絞り込みたいと考えました。 ユーザーが「2024-03-25」を選択すると、API(Laravel)に以下のようなクエリを投げます。
{
"order_date_from": "2024-03-25",
"order_date_to": "2024-03-25"
}
PHP(Laravel)側ではこう受け取ってフィルターします。
if ($order_date_from) {
$tr_study = $tr_study->whereDate('order_date', '>=', $order_date_from);
}
if ($order_date_to) {
$tr_study = $tr_study->whereDate('order_date', '<=', $order_date_to);
}
■ なぜデータが漏れるのか?(原因)
原因は 「タイムゾーン」 です。
多くのサーバーやデータベース(MySQL)は UTC(協定世界時) で動いています。 一方、私たちが普段使っているのは 日本時間(JST/UTC+9) ですよね。
このズレによって、
- DBの"2024-03-25"はUTC基準(日本時間だと9時間ズレ)
- フロントはJST基準で送信
結果として「3月25日のデータなのに拾えない」「3月24日の深夜データまで拾ってしまう」現象が起きます。
■ 解決策①【MySQLのタイムゾーンをJSTに設定】
DBがJSTで動いていれば、この問題はほぼ解決します。
【手順】
XAMPPなら、C:\xampp\mysql\bin\my.ini
に以下を追記します。
[mysqld]
default-time-zone = '+09:00'
その後、MySQLを再起動しましょう。
【確認】
以下のSQLを実行して、JSTになっているかチェック!
SELECT @@global.time_zone, @@session.time_zone;
結果が +09:00
なら成功!
■ 解決策②【UTC運用の場合はフロントで変換】
もし「サーバーはUTC運用」の場合は、フロントでJST→UTCに変換してAPIへ渡しましょう。
const startUtc = dayjs('2024-03-25').startOf('day').subtract(9, 'hour').toISOString();
const endUtc = dayjs('2024-03-25').endOf('day').subtract(9, 'hour').toISOString();
Laravel側はwhere()
で日時比較する形がおすすめです。
■ 解決策③【日付は文字列のまま扱う設計】
もし「時刻は不要」という仕様なら、日付を文字列(YYYY-MM-DD)として扱う設計 も有効です。
【メリット】
- タイムゾーンの影響を受けにくい
- SQLのDATE型や
whereDate()
で安全に扱える - UIもシンプルになる
Laravelならこう書けばOK。
if ($order_date_from) {
$tr_study = $tr_study->whereDate('order_date', '>=', $order_date_from);
}
if ($order_date_to) {
$tr_study = $tr_study->whereDate('order_date', '<=', $order_date_to);
}
この形なら、MySQLのDATE()
で評価されるため、時刻のズレが影響しません。
■ 【保存時のCarbonの使い方】
ただし、DBにデータを保存する時点で UTCズレしていると意味がない ので、保存時にも注意が必要です。
Laravelでは、保存時にCarbon
を使ってJSTに揃えて保存するのがオススメです。
// 例:文字列の日付をCarbonでJST化して保存
$order_date = Carbon::parse($request->input('order_date'))->setTimezone('Asia/Tokyo');
$model->order_date = $order_date;
$model->save();
こうすることで、保存時にもズレが起こらず、後の検索も安全になります。
■ まとめ(再発防止の教訓)
✅ タイムゾーンは最初に設計・方針決め!(JST運用かUTC運用か)
✅ DB・サーバー・フロントで「基準時刻」を合わせる
✅ whereDate()
は便利だけど、タイムゾーン影響を受けるので注意
✅ JST運用なら my.ini にdefault-time-zone
を書く だけでも事故防止になる
✅ 時刻が不要なら、日付文字列運用+Carbonで保存時チェック が安全
■ 最後に
日付や時間はアプリ開発の永遠のテーマ。少しでも「なんでズレるの?」が減らせたらうれしいです。 この経験が誰かの役に立ちますように!