如何将字符串与find子句中的日期进行比较?

时间:2010-08-25 20:37:50

标签: ruby-on-rails

我想得到日期在日期范围内的模特。 所以我想做一些像

这样的事情

MyModel.find_all_by_field1_id_and_field2_id(value1, value2, :conditions => { :date => nb_days_ago..Date.yesterday })

问题是,我的模型的日期属性是一个字符串(格式为“08-24-2010”),我无法修改它。 所以为了将它与我的日期范围进行比较,我尝试了这个:

MyModel.find_all_by_field1_id_and_field2_id(value1, value2, :conditions => { Date.strptime(:date, "%m-%d-%Y") => nb_days_ago..Date.yesterday })

但是我得到一个错误,基本上说strptime无法处理:date符号。我认为我的解决方案并不好。

如何将我的字符串与我的日期范围进行比较?

由于

2 个答案:

答案 0 :(得分:1)

您必须将数据库字符串转换为数据库中的日期而不是Ruby代码:

Model.all(:conditions => [ "STR_TO_DATE(date,'%m-%d-%Y') BETWEEN ? AND ? ",
               nb_days_ago, Date.yesterday])

更好的解决方案是通过添加阴影字段来规范化模型。

class Model

  after_save :create_shadow_fields
  def create_shadow_fields
    self.date_fld = Date.strptime(self.date_str, "%m-%d-%Y")
  end
end

现在您的查询可以写成如下:

Model.all(:conditions => {:date_fld => nb_days_ago..Date.yesterday})

不要忘记在date_fld列上添加索引。

修改1

对于SQLLite,可以按如下方式重写第一个解决方案:

Model.all(:conditions => [ "STRFTIME('%m-%d-%Y', date) BETWEEN ? AND ? ",
               nb_days_ago, Date.yesterday])

答案 1 :(得分:0)

首先,我不羡慕你的情况。这是一个非常难看的日期格式。我唯一能想到的是生成一个字符串数组,以该格式表示开始日期和结束日期之间的所有日期,然后使用SQL“IN”语法查找该集合中的日期(您可以使用从ActiveRecord's:conditions param)。

例如,如果您想在10天前搜索:

num = 10 #number of days ago for search range
# range starts at 1 because you specified yesterday
matching_date_strings = (1..num).to_a.map{|x| x.days.ago.strftime("%m-%d-%Y")}
=> ["08-24-2010", "08-23-2010", "08-22-2010", "08-21-2010", "08-20-2010"]
# then...
records = MyModel.all(:conditions => { :date => matching_date_strings })
# or in your case with field1 and field2
records = MyModel.find_all_by_field1_id_and_field2_id(value1, value2, :conditions => { :date => matching_date_strings })

这个想法应该生成SQL,例如“...... WHERE date IN(”08-24-2010“,”08-23-2010“,”08-22-2010“,”08-21- 2010“,”08-20-2010“)