English 中文(简体)
如何正确地将日期范围转换或查询Rails / MySQL DateTime列
原标题:
  • 时间:2009-03-11 21:57:59
  •  标签:

I have a rails application where I store created_at as datetime (standard). I am building a form for searching and I find I have to use find_by_sql to do some complex subqueries. The form has a date range (no time) to search on for items created_at field.

The problem I find is that if I pass in just the date string for range to query...

... status_changes.created_at between  2009-01-24  and  2009-03-12  ...

我正在获取记录,它们的created_at日期为2009-01-23 17:10:39 -0800,因为它在数据库中存储为2009-01-24 01:10:39(UTC)。

我该怎么修复这个问题,使得结果不会返回有问题的记录?

似乎我需要将日期范围转换为UTC特定或告诉find_by_sql根据当前时区搜索,而不是将列读取为UTC...

拿主意的人有吗?

约翰

最佳回答

我知道这是一个老问题,但是回答Streamlines关于CONVERT_TZ的查询:

除非您已加载名为timezone的mySQL表(在普通安装中可能不太可能),否则您需要将时区输入为与UTC的偏移量。

CONVERT_TZ(status_changes.created_at,  +00:00 ,  +08:00 ) between  2009-01-24  and  2009-03-12 )
问题回答

现代的ActiveRecord方法是:

Model.where(time_field: date1..date2)

如果您不使用find_by_sql,而是使用带有:conditions子句的find,让Rails进行替换,它会自动转换所有内容。

Model.find :all, 
  :conditions => ["created_at between ? and ?", start_date, end_date]

最糟糕的情况是,如果Rails对日期感到困惑,您可以将其转换为时间,它应该可以正常运行:

Model.find :all, 
  :conditions => ["created_at between ? and ?", 
                   start_date.to_time, end_date.to_time]

MySQL有一个CONVERT_TZ函数,可以把一个日期时间从一个时区转换到另一个时区。你可以构建查询语句,把存储的值(UTC)转换成本地时区(PST)。

CONVERT_TZ(status_changes.created_at, UTC ,?) between ? and ?,  PST,  2009-01-24 ,  2009-03-10 

我尝试了Ian的回答,但它没有完全起作用。Rails在保存和加载记录时正确处理时区,但似乎在查询参数方面并没有做到同样的程度。请注意,我正在使用Rails 2.1.1开发应用程序,因此自那以后可能有所改进。

通过一次小的改动,我成功让Ian的解决方案工作了:使用getutc方法获取UTC时区的时间值,然后将其作为参数传递。由于UTC时间并未受到getutc的影响,只是时区发生了改变,因此这也不会在任何可能正确处理时间参数的后续版本的Rails中造成任何损害。

由于Rails在数据库中将日期存储为UTC时间,因此您应该对TimeDateTime使用utc方法。

即,也就是

Model.find :all, 
  :conditions => ["created_at between ? and ?", start_date.utc, end_date.utc]
Model.where(:from => "2012-01-01".to_date.."2012-06-30".to_date)

对我起了作用 (:from是日期类型的数据库字段)





相关问题
热门标签