rails の時間、日付に関する便利な機能。ちなみに動作確認は rails 4 です。
time_point = Time.now.strftime('%Y%m%d%H%M%S')
みたいな時間のタグを使って、クエリの結果をキャッシュするようなコードを書いていた時に、このフォーマット %Y%m%d%H%M%S
を定数にするか迷って、rails のコンソールで当てずっぽうに '20140305'.to_date
って打ったら「おおっ」となったので、ActiveSupport を少し調べました。
Digit to date. Date to digit.
8桁の数字(String)を Date オブジェクトに、また逆に Date オブジェクトを8桁の数字に。
以下のソースコードを参考にしました。
github rails/activesupport/lib/active_support/core_ext/date/conversions.rb
# 8桁の数字を Date オブジェクトに変換
date = '20140305'.to_date
# => Wed, 05 Mar 2014
# その逆
date.to_s(:number)
# => "20140305"
Digit to time. Time to digit.
14桁の数字(String)を Time オブジェクトに、また逆に Time オブジェクトを14桁の数字に。
rails のソースコード
github rails/activesupport/lib/active_support/core_ext/date_time/conversions.rb
# 14桁の数字を Time オブジェクトに変換
time = '20140305184233'.to_time
# => 2014-03-05 18:42:33 +0900
# その逆
time.to_s(:number)
# => "20140305184233"
8桁の方はヘビーユーザー向けのUIに便利だし、14桁の方はデータに時間のタグを付ける時に便利です。
追記 2014/03/12
String.to_time
には気をつけなくてはいけないことがありました。
このメソッドは ActiveSuppoer::TimeWithZone
ではなく、 Time
のインスタンスをマシンのタイムゾーンで返しますので、アプリケーションのタイムゾーンとマシンのタイムゾーンが異なる場合は、Time.zone.parse()
を使う必要があります。
# 例えば、マシンが UTC、アプリケーションが JST の場合。
last_update_time = record.updated_at
# => Wed, 12 Mar 2014 11:20:14 JST +09:00
timestamp = last_update_time.to_s(:number)
# => "20140312112014"
# to_time ではマシンのロケール時間になってしまう。
time = timestamp.to_time
# => 2014-03-12 11:20:14 +0000
# これをクエリに使うと以下の値が使われてしまい、UTC オフセットが加算されてしまう。
time.in_time_zone
# => Wed, 12 Mar 2014 20:20:14 JST +09:00
# アプリケーションのタイムゾーンのインスタンスにするには。
time = Time.zone.parse(timestamp)
# => Wed, 12 Mar 2014 11:20:14 JST +09:00
追記 2014/03/13
更に、現在時間と現在日時を扱う時の注意点。
異なるロケールからアクセスしてくるユーザーにビューを提供する場合などには重要です。
# 例などではよくこう書いてあります。
now = Time.now
today = Date.today
# でも上記はいずれもマシンローカルな時間に基づきます。
# アプリの設定に基づきたいのであれば、以下のように書きます。
now = Time.zone.now
today = Time.zone.today