ActiveSupport :: TimeWithZone#to_date返回错误的日期 [英] ActiveSupport::TimeWithZone#to_date returns wrong date

查看:197
本文介绍了ActiveSupport :: TimeWithZone#to_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

..
..
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>


  1. Gemfile中删除 ruby​​-units gem, code>或载入rails gem

  2. 解决方法:而不是执行 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:

  1. Remove the ruby-units gem from the Gemfile or load it after rails gem
  2. Workaround: Instead of executing datetime.to_date , use datetime.to_s.to_date

这篇关于ActiveSupport :: TimeWithZone#to_date返回错误的日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆