Jigneshに感謝します。ここで私はあなたの発見と解決策を共有しています。
実装をオーバーライドしているgemがありto_date
、それが正しく実装されておらず、このオーバーライドされたバージョンが呼び出されている可能性があります。
私の場合、犯人はruby-units
宝石でした
根本原因:ruby-units
アプリケーションのGemfileに含まれているgem
問題分析:
Gemfile
# Ruby-units overrides String class #to method, hence placed before Rails
gem "ruby-units" # Loads first and then rails is loaded
gem "rails", "3.0.11"
..
..
time.rbファイル(ruby-units gem codebase)
..
..
unless Time.instance_methods.include?(:to_date)
# :nocov_19:
# @return [Date]
def to_date
x=(Date.civil(1970,1,1)+((self.to_f+self.gmt_offset)/86400.0)-0.5)
Date.civil(x.year, x.month, x.day)
end
# :nocov_19:
end
..
..
UTC
タイムゾーン
の現在の時刻がインスタンスでWed, 11 Apr 2012 10:12:17 UTC +00:00
表されているとしActiveSupport::TimeWithZone
ます。Railsアプリケーションを実行すると、誤っ<TimeWithZone>.to_date
た日付が返されます。2012-04-10
上記の誤った動作に関与している原因は、gemto_date
によって提供されるメソッドの実装です。ruby-units
以下は、上記の誤った動作を示すためのサンプルプログラムです。このメソッドはgemto_date
によって実装されたものと同じですが、引数がメソッドに追加され、実装内のが引数'date_time'に置き換えられている点が異なります。ruby-units
date_time
self
上記の結果を確認するためのサンプルRubyプログラム:
require 'rubygems'
require 'active_support/all'
class TestDT
def to_date(date_time)
#x=(Date.civil(1970,1,1)+((self.to_f+self.gmt_offset)/86400.0)-0.5)
x=(Date.civil(1970,1,1)+((date_time.to_f+date_time.gmt_offset)/86400.0)-0.5)
Date.civil(x.year, x.month, x.day)
end
end
tdt = TestDT.new
utc_time = Time.now.in_time_zone('UTC')
puts tdt.to_date(utc_time)
出力(これを書いている時点の日付は水でした11 Apr 2012 08:35:12 UTC +00:00
):
$ ruby test_date_time.rb
2012-04-10
解決:
ruby-units
から宝石を削除するGemfile
か、レールの宝石の後にロードします
- 回避策:実行する代わりに
datetime.to_date
、datetime.to_s.to_date