我想要一个ActiveSupport::TimeWithZone
实例的日期部分。我使用to_date
函数,但它提前一天返回日期。
例如,如果日期时间为2012-04-11 09:05:00 UTC
,并且我致电to_date
,则会返回2012-04-10
但2012-04-11
。
此外,我没有使用特定时区(默认为UTC)
该应用程序正在Ruby 1.8.7
和Rails 3.0.2
任何人都可以告诉我为什么错误的日期?另请建议我是否有更好的方法来获取日期(Date
)的一部分来自给定的DateTime
(ActiveSupport::TimeWithZone
的实例)
编辑: 有人在这里面临同样的问题http://pastebin.com/sn8ExZiQ
注意:Time.zone
返回'UTC'
答案 0 :(得分:1)
谢谢Jignesh。在这里,我将分享您的发现和解决方案。
可能有一些gem覆盖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 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
实例。
当我们执行<TimeWithZone>.to_date
时,从rails应用程序返回
日期2012-04-10
不正确。
上述错误行为涉及的罪魁祸首是to_date
方法的实现
由ruby-units
gem
以下是演示上述错误行为的示例程序。 to_date
方法与ruby-units
gem实现的方法相同,只是在方法中添加了一个参数,即date_time
,并且实现中的self
被参数替换
'DATE_TIME'。
示例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
gem或在rails gem datetime.to_date
datetime.to_s.to_date
醇>