とーますメモ

Ruby on Rails / Goなどの学習メモ

【Rails】難しすぎる!? Timezone(タイムゾーン)についてのメモ

自分用メモ。

大事なことは全て以下のページにあった。
qiita.com
qiita.com

上記の内容から重要なポイントを抜き出すと以下の通り。

1)タイムゾーンの設定

システムまたは環境変数のタイムゾーンとapplication.rb(time_zone)が同じならば、
Time.nowでもTime.current(Time.zone.now)でも同じ。

2)Rails経由でDBに保存されるtimeについて

[config.active_record.default_timezon]を[:local]に設定していなければ、RailsはMySQLのタイムゾーンを無視して時間をUTCで保存する。

3)Datetime.newはUTCタイムゾーンを返す。

parse や new では、環境変数のタイムゾーンでもapplication.rbのタイムゾーンでもなく、UTCのタイムゾーンになる点も注意が必要です。(UTCからのオフセットを指定しない場合)

RubyとRailsにおけるTime, Date, DateTime, TimeWithZoneの違い - Qiita

4)MySQLのDateTime型はタイムゾーンを情報を持っていない。

Railsと周辺のTimeZone設定を整理する (active_record.default_timezoneの罠) - Qiita

5)MySQLのTIMESTAMP型は厄介?

TIMESTAMP型は書き込む時にサーバのタイムゾーン設定を確認してUTCに変換してからデータを保存する。取得する時はUTCからサーバのタイムゾーンに変換してから表示する。
なので、記録時と異なるタイムゾーンに変更すると取得した時の時間がズレてしまう。

by Railsと周辺のTimeZone設定を整理する (active_record.default_timezoneの罠) - Qiita

またTIMESTAMP型は「2038年問題」などの問題もあるため
将来的なことを考えた場合、時間を保持する型としては「Datetime型」一択だと思う。(個人的見解)
Railsのcreated_atやupdated_atもDatetime型だし、migrationにtimestampを選択できるけど、rake db:migrateしたらDatetime型になってるし。

他にも「CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP」のせいで、レコードが更新されると勝手に日付が更新されてしまうといった仕様ですし。

MySQLの timestamp型が、なかなか厄介。
MySQL TIMESTAMP 2つ以上のCURRENT_TIMESTAMP - Oboe吹きプログラマの黙示録

結論

上記の記事で言ってることと同じだが
Time.nowやDateTime.nowなどの環境タイムゾーンを使用している関数を使うよりも
Time.currentなどのapplication.rbで使用しているタイムゾーンを元にした関数を使うほうが良い。

備考

DateTime型のカラムに対して、Date型で検索をかけるときは十分注意すること。

リファレンスマニュアルに書かれているとおりで、最近のMySQLではDateTime型のカラムに対してDate型で検索をしようとすると自動的に '00:00:00' が付与されてDateTime型として計算されます。

by MySQLでDateTime型のカラムをDate型で検索するときに気をつけること - (゚∀゚)o彡 sasata299's blog