1. 導入
グローバルに展開するアプリケーションや、複数の拠点を持つシステムを運用していると、必ず直面するのが「タイムゾーン」の問題です。サーバーの時刻設定(UTC)と、ユーザーが利用する地域の時間(JSTなど)のズレは、ログの集計やレポート作成において混乱を招きます。MySQLのCONVERT_TZ関数を適切に活用することで、アプリケーション側での複雑な時刻計算を排除し、データベース層でスマートに時差を吸収することが可能になります。
2. 基礎知識
CONVERT_TZ(dt, from_tz, to_tz) は、指定した日時(dt)を、元のタイムゾーン(from_tz)からターゲットのタイムゾーン(to_tz)へと変換する関数です。
タイムゾーンの指定には、’Asia/Tokyo’ のような「名前付きタイムゾーン」と、’+09:00′ のような「UTCとの時差」の2種類があります。特に注意が必要なのは「名前付きタイムゾーン」を使用する場合で、これはMySQLサーバーのシステムテーブル(time_zone_nameなど)にタイムゾーン情報が格納されている必要があります。ここが空の場合、関数は期待した値を返さず、NULLを返してしまいます。
3. 実装/解決策
実務では、まず変換元のタイムゾーンを正しく把握することが重要です。多くのクラウド環境やDocker上のMySQLはデフォルトでUTC(+00:00)に設定されています。したがって、UTCで保存されたレコードを日本時間に変換するには、from_tzに’+00:00’、to_tzに’Asia/Tokyo’を指定するのが定石です。
もし名前付きタイムゾーンが使えない環境(NULLが返る場合)は、OS側のタイムゾーンファイルをMySQLにインポートする必要があります。Linux環境であれば、mysql_tzinfo_to_sqlコマンドを用いて、OSのシステムタイムゾーン情報をMySQLにロードするのが最も確実な解決策です。
4. サンプルプログラム
以下は、UTCで保存されたタイムスタンプを日本時間に変換して取得するSQLの例です。
— 1. UTCから日本時間(+09:00)へ変換する標準的なクエリ
SELECT
created_at AS utc_time,
CONVERT_TZ(created_at, ‘+00:00’, ‘Asia/Tokyo’) AS jst_time
FROM
orders;
— 2. 特定の日時をニューヨーク時間に変換する例
— ‘2023-10-01 12:00:00’ (JST) を ‘America/New_York’ へ変換
SELECT
CONVERT_TZ(‘2023-10-01 12:00:00’, ‘Asia/Tokyo’, ‘America/New_York’) AS ny_time;
— 3. もしNULLが返る場合のチェック用クエリ
— タイムゾーンテーブルが読み込まれているか確認
SELECT FROM mysql.time_zone_name WHERE Name = ‘Asia/Tokyo’;
5. 応用・注意点
現場で最も多いトラブルは「サマータイム(DST)」の考慮漏れです。’Asia/Tokyo’などの名前付きタイムゾーンを使用すれば、MySQLが自動的にサマータイムを考慮して変換してくれますが、’+09:00’のように時差を直書きすると、サマータイム期間中であっても強制的に固定値で計算されてしまいます。
将来的な運用変更や海外拠点との連携を考慮するなら、可能な限り名前付きタイムゾーンを利用することを推奨します。
また、頻繁にCONVERT_TZを呼び出すクエリは、インデックスが効かなくなる可能性があるため注意してください。変換後の値でフィルタリングを行う場合は、クエリ内で変換するのではなく、アプリケーション側で変換した値を用意してからSQLを発行する方がパフォーマンス上のメリットが大きい場合があります。用途に応じて使い分けるようにしましょう。

コメント