Rails where()和timezones

时间:2012-03-09 18:01:51

标签: ruby-on-rails activerecord timezone rails-activerecord

我正在尝试使用以下内容创建今天(在我当前时区)创建的“条目”:

Entry.where("DATE(created_at) = DATE(?) AND email = ?", Time.now, email)

Time.now给了我当前区域的时间,但查询似乎是在搜索每个条目的created_at列的UTC时间。

如何在服务器的时区找到今天创建的条目?

4 个答案:

答案 0 :(得分:12)

只要在SQL中调用DATE()函数,就会忘记时区信息。要记住两件事:

  1. 数据库内的所有内容都是UTC格式,所有内容都包含DATE()的结果。
  2. 您当地时区的单个日期(即日期)可以轻松跨越UTC中的两个日期,因此您需要查看整个时间戳(在两个侧)而不仅仅是(UTC)日期组件。
  3. 这样的事情应该有效:

    now = Time.now
    Entry.where('created_at between :start and :end and email = :email',
        :start => now.beginning_of_day,
        :end   => now.end_of_day,
        :email => email
    )
    

    时间应自动转换为UTC。您可能希望以不同的方式处理上限;使用end_of_day会为您提供23:59:59,因此有一些空间可以让您想要捕获的内容。您可以使用显式的半开间隔(而不是SQL between使用的闭合间隔)来解决该问题,如下所示:

    now = Time.now
    Entry.where('created_at >= :start and created_at < :end and email = :email',
        :start => now.beginning_of_day,
        :end   => now.tomorrow.beginning_of_day,
        :email => email
    )
    

答案 1 :(得分:1)

使用Time.zone.now。这将使用ActiveSupport::TimeWithZone对象,当在数据库搜索中使用时,该对象将自动转换为UTC。

答案 2 :(得分:0)

使用Time.now.utc

答案 3 :(得分:0)

首先,您应该获得时区,然后是时区偏移量。 例如,current_time_zone是

  

美国/洛杉矶

时区偏移量发现:

 Time.now.in_time_zone(current_time_zone).utc_offset / 3600) * -1
  

7

在控制器中:

 start_date_format = DateTime.strptime(@start_date, date_format)
 start_date_format_with_hour = 
 DateTime.strptime((start_date_format.to_i + timezone_offset*60*60).to_s,'%s').strftime(date_format)

 end_date_format = DateTime.strptime(@end_date, date_format)
 end_date_format_with_hour = DateTime.strptime((end_date_format.to_i + timezone_offset*60*60).to_s,'%s').strftime(date_format)

 @filters_date = "invoices.created_at >= ? AND invoices.created_at < ?", start_date_format_with_hour, end_date_format_with_hour