【问题标题】:Rails where() and timezonesRails where() 和时区
【发布时间】:2012-03-27 04:24:02
【问题描述】:

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

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

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

有什么想法可以找到今天在服务器时区创建的条目吗?

【问题讨论】:

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


    【解决方案1】:

    一旦您在 SQL 中调用 DATE() 函数,您就会忘记时区信息。有两点要记住:

    1. 数据库中的所有内容都将采用 UTC,所有内容都包含DATE() 的结果。
    2. 您当地时区的单个日期(即一天)可以轻松跨越 UTC 中的两个日期,因此您需要查看整个时间戳(双方)而不仅仅是 (UTC)日期组件。

    这样的事情应该可以工作:

    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
    )
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 这似乎和使用Time.now和Time.now.utc的效果一样。看起来查询是使用 UTC 时间构建的,但这给了我一天内英格兰的条目,而不是我在当地的地方。
      【解决方案3】:

      使用Time.now.utc?

      【讨论】:

      • 我想到了这一点,但它会根据 UTC 一天的 24 小时跨度返回条目,而不是本地。对吗?
      【解决方案4】:

      首先,您应该获取时区,然后是时区偏移量。 例如 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
      

      【讨论】:

        猜你喜欢
        • 2015-07-12
        • 2017-04-05
        • 2012-08-28
        • 2016-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-03
        相关资源
        最近更新 更多