SQLiteのCURRENT_TIMESTAMPのタイムゾーンはUTC固定っぽい


SQLite3ではtimestamp型のデフォルトとしてCURRENT_TIMESTAMPが使えるんですが、どうやらこのCURRENT_TIMESTAMPで得られる時刻はローカルタイムゾーンではなくUTC(協定世界時)に従うらしく変更も出来ないっぽいです(CURRENT_DATE、CURRENT_TIMEも同様)。


datetime()などの関数群の場合デフォルトのタイムゾーンはUTCですが、オプションを設定してやることでローカルタイムゾーンを適用した値を取得することが出来ます。

SQLite Query Language: Date And Time Functions

sqlite> select datetime('now'), datetime('now', 'localtime');
2009-06-19 10:29:03|2009-06-19 19:29:03


設定できるのは、以下の12種類。

  1. NNN days(NNN日後)
  2. NNN hours(NNN時間後)
  3. NNN minutes(NNN分後)
  4. NNN.NNNN seconds(NNN.NNNN秒後)
  5. NNN months(NNN月後)
  6. NNN years(NNN年後)
  7. start of month(その月の初め)
  8. start of year(その年の初め)
  9. start of day(その日の初め)
  10. weekday N(今日以降の特定の曜日)
  11. unixepoch(timestringをUNIX時間として扱う)
  12. localtime(ローカルタイムゾーン)
  13. utc(UTC)

こんな感じに重複して指定することも出来ます。

sqlite> select datetime('now'), datetime('now', 'localtime'), datetime('now', 'localtime', '-3 days');
2009-06-19 10:33:36|2009-06-19 19:33:36|2009-06-16 19:33:36



で、CURRENT_TIMESTAMP。
こちらは関数ではないので、オプションの設定がありません。

SQLite Query Language: SQLite Keywords

なので、結局こういうことになります。

sqlite> select datetime('now'), datetime('now', 'localtime'), CURRENT_TIMESTAMP;
2009-06-19 10:42:29|2009-06-19 19:42:29|2009-06-19 10:42:29


「なります」って言われてもねぇ。正直これだと、使えないって言うか仮にテーブル内にこれを設定したとしても目安くらいにしかできない気がします。うっかり忘れてバグとか出しそうですし、クエリ書くのにいちいちUTCに直して範囲決めるとか面倒ですし。あと、バグとか出しそうだし。バグとか。


仕方がないので、デフォルトとしてのCURRENT_TIMESTAMPは使わないか気休め程度にしておいて、登録日については別途DATETIME型でフィールドを設けた方がよさそうですね。実際、海外のコード眺めてみたけどみんなdatetime()とかで対応してました。Firefoxのテーブルでは全部INTEGER型でやってますね。SQLiteではこっちの方が主流なのかな。面倒くさいなぁ。