ActiveSupport :: TimeWithZone#to_date返回错误的日期 [英] ActiveSupport::TimeWithZone#to_date returns wrong date
问题描述
我要从 ActiveSupport :: TimeWithZone
的实例中获取日期部分。我使用 to_date
函数,但它早一天返回日期。
例如,如果datetime是 2012-04-11 09:05:00 UTC
,如果我调用 to_date
,则返回 2012-04-10
但 2012-04-11
。
不使用特定的时区(默认为UTC)
应用程序正在运行 Ruby 1.8.7
和 Rails 3.0.2
任何人都可以告诉我为什么错误的日期?另外请给我建议,如果有更好的方法来获得日期(日期
的实例)部分从给定的 DateTime
ActiveSupport :: TimeWithZone
)
编辑:
有人也面临相同的问题在这里 http://pastebin.com/sn8ExZiQ
注意: Time.zone
返回'UTC'
感谢 Jignesh 。在这里,我分享你的发现和解决方案。
可能有一些宝石覆盖 to_date
实现,它可能执行不正确,这个被覆盖的版本可能会被调用。
在我的情况下,歹徒是 ruby-units
gem
根本原因: ruby-units
宝石包含在应用程序的Gemfile中>
问题分析:
Gemfile
#Ruby-units覆盖String类#to方法,因此放置在Rails之前
gemruby-units#首先加载然后rails被加载
宝石rails,3.0.11
..
..
time.rb文件(ruby-units gem codebase)
$ b除非Time.instance_methods.include?(:to_date)
#:nocov_19:
#@return [日期]
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
..
..
$ p $让我们说现在在
UTC的时间是<$ code>时区是
Wed,11 2012年4月10日10:12:17 UTC +00:00
由 ActiveSupport :: TimeWithZone
实例表示。
当我们执行< TimeWithZone> .to_date
时,从rails应用程序返回
a date 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)
日期.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)
输出(当时的日期)写这个是Wed, 2012年4月11日08:35:12 UTC +00:00
):
$ ruby test_date_time.r b
2012-04-10
解决方案: p>
- 从
Gemfile中删除 ruby-units
gem, code>或载入rails gem
- 解决方法:而不是执行
datetime.to_date
,使用 datetime.to_s.to_date
I want date part from an instance of ActiveSupport::TimeWithZone
. I used to_date
function for that but it returns date one day earlier.
For example, if datetime is 2012-04-11 09:05:00 UTC
, and if I call to_date
then it returns 2012-04-10
but 2012-04-11
.
Also I am not using specific timezone (defaults to UTC)
The application is running on Ruby 1.8.7
and Rails 3.0.2
Can anyone please tell me why it gives wrong date? Also please suggest me if there is better way to get date (instance of Date
) part from given DateTime
(instance of ActiveSupport::TimeWithZone
)
EDIT :
someone is also facing same issue here http://pastebin.com/sn8ExZiQ
NOTE : Time.zone
returns 'UTC'
解决方案 Thanks Jignesh. Here I am sharing your findings and solutions.
There may be some gem that is overriding to_date
implementation and it may be implemented incorrectly and this overridden version might be getting called.
In my case the culprit was ruby-units
gem
Root Cause : ruby-units
gem included in the application’s Gemfile
Problem Analysis :
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 file (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
..
..
Lets say that current time in UTC
time-zone is
Wed, 11 Apr 2012 10:12:17 UTC +00:00
represented by a ActiveSupport::TimeWithZone
instance.
From the rails application when we execute <TimeWithZone>.to_date
it returns
a date 2012-04-10
which is incorrect.
The culprit involved in above incorrect behavior is the implementation of to_date
method
provided by ruby-units
gem
Below is a sample program to demonstrate the above incorrect behaviour. The to_date
method is identical to one implemented by ruby-units
gem, except that an argument is added to the method namely date_time
and the self
in the implementation is replaced by the argument
'date_time'.
Sample Ruby Program to confirm the findings above:
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)
Output (date at the time of writing this was Wed, 11 Apr 2012 08:35:12 UTC +00:00
):
$ ruby test_date_time.rb
2012-04-10
Solution:
- Remove the
ruby-units
gem from the Gemfile
or load it after rails gem
- Workaround: Instead of executing
datetime.to_date
, use datetime.to_s.to_date
这篇关于ActiveSupport :: TimeWithZone#to_date返回错误的日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!