DjangoとMySQLでUSE_TZを使う時の注意

しんぺい

こんにちは!しんぺいです。

Djangoの基本設定で、タイムゾーンを有効にするための「USE_TZ」というのがあります。

DjangoのデータベースとしてMySQLを使用した場合に、この「USE_TZ」でハマるポイントがあるので紹介します!

USE_TZについて

DjangoではUSE_TZTrueに設定すると、datetimeをUTCベースでデータベースに保存します。

おそらく、多くの場合はDjangoの設定が以下のようになっていると思います。

TIME_ZONE = 'Asia/Tokyo'

USE_TZ = True

つまりこれは、「datetimeはUTCベースで保存し、表示上は日本時間を使用する」ということになります。

MySQLもUTCにする必要がある

これでDjango側はUTCベースになりましたが、MySQL側もUTCベースにしないと、データを取得するときにおかしな挙動になります。
Django側はUTCベースで保存しているつもりなのに、MySQL側がUTCベースになっていないわけです。

そこで、MySQL側もUTCベースになっているかをチェックします。
まずはMySQLにログインして以下のコマンドで確認します。

mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | JST    |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set (0.00 sec)

time_zoneのValueがUTCになっていません。
UTCに変更する必要がありそうです。

次にやるべきはタイムゾーンテーブルのロードです。
一度MySQLが抜けて、以下のコマンドを実行します。

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

次に、MySQLの設定ファイルであるmy.cnfを編集します。
my.cnfがどこにあるか分からない場合は、以下のコマンドで確認しましょう。一番左に表示されるパスが正解です。

$ mysql --help | grep my.cnf
                order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /usr/local/etc/my.cnf ~/.my.cnf

my.cnfを編集します。

[mysqld_safe]
timezone = UTC

[mysqld]
default_time_zone = UTC

設定が完了したら、MySQLを再起動します。

$ mysql.server restart

Shutting down MySQL
.. SUCCESS!
Starting MySQL
. SUCCESS!

もう一度確認してみましょう。

mysql> show variables like '%time_zone%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| system_time_zone | UTC   |
| time_zone        | UTC   |
+------------------+-------+
2 rows in set (0.01 sec)

大丈夫そうですね!