Thanks Jignesh https://stackoverflow.com/users/936494/jignesh。在这里,我分享您的发现和解决方案。
可能有一些宝石是压倒一切的to_date
实现,它可能会被错误地实现,并且可能会调用这个覆盖的版本。
就我而言,罪魁祸首是ruby-units
gem
根本原因 : ruby-units
gem 包含在应用程序的 Gemfile 中
问题分析 :
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 代码库)
..
..
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
这是不正确的。
上述错误行为的罪魁祸首是执行to_date
方法
由...提供ruby-units
gem
下面是一个示例程序来演示上述不正确的行为。这to_date
方法与实现的方法相同ruby-units
gem,除了将参数添加到方法中之外,即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
或者在 Rails gem 之后加载它
- 解决方法:而不是执行
datetime.to_date
, use datetime.to_s.to_date