活动记录无法正确比较数据库中的日期

时间:2011-05-03 21:30:49

标签: ruby-on-rails-3

我是一个新手,真的陷入了红宝石中不同的时间和日期格式。 到现在为止,我已经想出了如何解决这些问题。在这种情况下,我正在使用

find_or_initialize_by_sessiondate_and_person_id()并且它总是创建一个新记录,因为(显然)它不能识别从数据库中提取的日期与提供的日期相同。我正在从CSV文件中读取数据,输入如下:

Fri Apr 22 15:09:00 2011

活动记录不会抱怨这种格式 - 它将它放在数据库的日期时间字段中(SQLlite,但我希望解决方案适用于其他数据库)就好了。我尝试在输入中添加一个时区,如下所示:

createdate = DateTime.strptime(record_split[ 4 ].chomp + " UTC","%a %b %e %T %Y %Z"
session = Session.find_or_initialize_by_sessiondate_and_person_id(createdate, person.id)
    if session.new_record?
      puts "new record for #{person.name}, #{createdate.inspect}, #{session.sessiondate.inspect}"

输出如下:

new record for Mickey Mouse, Fri, 22 Apr 2011 15:09:00 +0000, Fri, 22 Apr 2011 15:09:00 UTC +00:00

这看起来和我的日期/时间相同,为什么ActiveRecord会创建新记录?

5 个答案:

答案 0 :(得分:1)

我对发生的事情感到有点困惑。从你的例子来看,最让我担忧的事实是“2010年10月5日星期二19:43:23”正在被修改为“星期五,2011年4月22日15:09:00 +0000”(除非你使用的是不同的每个例子的日期......)

为了让自己更轻松,最好只使用Time.parse而不是DateTime.strptime

ree-1.8.7-2010.02 > Time.parse("Tue Oct  5 19:43:23 2010")
 => Tue Oct 05 19:43:23 +1100 2010

另一件需要考虑的事情是,在内部,Rails 3将所有时间戳存储为UTC;然后它会在默认的时区中即时显示该时间。

最后,根据原始时间戳字段的生成方式(即Time.now vs解析字符串),您可能会遇到精度问题。如果使用Time.now填充createdate,您可能会发现它已经持有一个正确到微秒的值(例如:'19:43:23.34131'),与您的解析时间相比( '19:43:23.00000')并不完全相同。

答案 1 :(得分:0)

也许是因为person_id不同?

此日期时间也略有不同:

Fri, 22 Apr 2011 15:09:00 +0000
vs
Fri, 22 Apr 2011 15:09:00 UTC +00:00

答案 2 :(得分:0)

以UTC格式存储日期总是一个好主意,因此您可以在模型中使用以下内容:

def sessiondate=(dt)
  write_attribute(:sessiondate, Time.parse(dt).utc)
end

答案 3 :(得分:0)

您的DateTime.new ...在我的Rails 3.0.7上不起作用,但是可以通过其他方式向您提供建议,这是我在rails控制台中的测试:

ruby-1.9.2-p136 :028 > v = Video.new :title => "toto"
 => #<Video id: nil> 
ruby-1.9.2-p136 :029 > v.save
 => true 
ruby-1.9.2-p136 :030 > v
 => #<Video id: 507>   

v.id = 507

   ruby-1.9.2-p136 :032 > v.created_at = "Tue Oct  5 19:43:23 2010" #I use your datetime
     => "Tue Oct  5 19:43:23 2010" 
    ruby-1.9.2-p136 :033 > v.save
     => true 
    ruby-1.9.2-p136 :034 > v.created_at
     => Tue, 05 Oct 2010 19:43:23 UTC +00:00 

    ruby-1.9.2-p136 :035 > v2 = Video.find_or_initialize_by_created_at("Tue Oct  5 19:43:23 2010")
     => #<Video id: nil, ... , created_at: "2010-10-05 19:43:23", ... > 
    ruby-1.9.2-p136 :039 > v2.save
     => true 
    ruby-1.9.2-p136 :040 > v2
     => #<Video id: 508>   

新记录,v.id = 507,v2 = 508!

... > v3 = Video.
find_or_initialize_by_created_at("Tue Oct  5 19:43:23 2010".to_datetime)  

现在使用日期字符串

上的String.to_datetime方法
   => #<Video id: 507>  # We get v !!!
 ruby-1.9.2-p136 :043 > v == v3
   => true 

p.s:这是一个I18n应用程序,这就是为什么你没有看到title属性。

答案 4 :(得分:0)

似乎SQLite和Active Record没有很好地沟通日期时间的类型。

请参阅ActiveRecord/sqlite3 column type lost in table view?