简体   繁体   English

如何正确转换或查询Rails / MySQL DateTime列的日期范围

[英]How to Properly Convert or Query Date Range for Rails / MySQL DateTime Column

I have a rails application where I store created_at as datetime (standard). 我有一个rails应用程序,我将created_at存储为datetime(标准)。 I am building a form for searching and I find I have to use find_by_sql to do some complex subqueries. 我正在构建一个搜索表单,我发现我必须使用find_by_sql来执行一些复杂的子查询。 The form has a date range (no time) to search on for items created_at field. 表单有一个日期范围(没有时间)来搜索items_at字段的项目。

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

I am getting back records that have a created_at date of 2009-01-23 17:10:39 -0800 because this is stored in the db as 2009-01-24 01:10:39 (UTC) 我收回了创建日期为2009-01-23 17:10:39 -0800的记录,因为它存储在数据库中,如2009-01-24 01:10:39(UTC)

How can I fix this so that the result is not returning the record in question? 我如何解决这个问题,以便结果不会返回有问题的记录?

It seems I either need to convert the date range to be UTC specific or tell the find_by_sql to search based on current time zone instead of reading the column as utc... 我似乎需要将日期范围转换为UTC特定的,或者告诉find_by_sql根据当前时区进行搜索,而不是将列读取为utc ...

Any takers? 任何接受者?

John 约翰

现代ActiveRecord的做法是:

Model.where(time_field: date1..date2)

If you don't use find_by_sql , but rather use a find with a :conditions clause that let's Rails do substitutions, it will convert everything automatically. 如果您不使用find_by_sql ,而是使用带有:conditions子句的find ,让Rails进行替换,它将自动转换所有内容。

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

Worst case, if Rails is confused by the dates, you can convert them to times and it should play nicely: 最糟糕的情况是,如果Rails被日期混淆,你可以将它们转换为时间,它应该很好地运行:

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

I know that this is an old question, but in answer to Streamlines query about CONVERT_TZ: 我知道这是一个老问题,但在回答有关CONVERT_TZ的Streamlines查询时:

Unless you have the mySQL named timezone tables loaded (which is pretty unlikely on a vanilla install), you need to enter timezones as an offset from UTC. 除非您加载了mySQL命名的时区表(这在vanilla安装上很不可能),否则您需要输入时区作为UTC的偏移量。

CONVERT_TZ(status_changes.created_at, '+00:00', '+08:00') between '2009-01-24' and '2009-03-12')

MySQL has a CONVERT_TZ function that takes a datetime and converts it from one timezone to another. MySQL有一个CONVERT_TZ函数,它接受一个日期时间并将其从一个时区转换为另一个时区。 You could build your query to convert from the stored value (UTC) to your local timezone (PST). 您可以构建查询以将存储值(UTC)转换为本地时区(PST)。

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

I tried Ian's answer, but it did not quite work. 我尝试了伊恩的答案,但它并没有奏效。 Rails is correctly handling the timezone when records are saved and loaded, but doesn't seem to do the same for query parameters. 当保存和加载记录时,Rails正确处理时区,但对查询参数似乎不一样。 Note that the application I'm working on is in Rails 2.1.1, so things may have improved somewhat since then. 请注意,我正在使用的应用程序是在Rails 2.1.1中,所以从那以后事情可能会有所改善。

With one small tweak, I was able to make Ian's solution work though: Get the time value in the UTC timezone using the getutc method, and then pass that as the parameter. 通过一个小的调整,我能够使Ian的解决方案工作:使用getutc方法获取UTC时区中的时间值,然后将其作为参数传递。 This should also not cause any harm in any later versions of Rails that may handle the time parameter zone correctly, since UTC time is not altered by getutc, just the timezone. 这也不会对任何可能正确处理时间参数区域的Rails版本造成任何伤害,因为getutc不会改变UTC时间,只会改变时区。

Because Rails stores the dates in UTC in the database you should use the utc method on Time or DateTime 因为Rails在数据库中以UTC格式存储日期,所以您应该在TimeDateTime上使用utc方法

ie

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)

为我工作(:来自'日期'类型的数据库字段)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM