代码之家  ›  专栏  ›  技术社区  ›  frankodwyer

为什么rails查询的行为会因时区而异?

  •  8
  • frankodwyer  · 技术社区  · 15 年前

    >> Model.find(:all,:conditions=>['created_at<=?',(Time.now-1.hours).gmtime]).length
    => 279
    >> Model.find(:all,:conditions=>['created_at<=?',(Time.now-1.hours)]).length
    => 280
    

    其中DB实际包含一个在过去一小时内创建的模型,模型总数为280。因此,只有第一个查询是正确的。

    但是,在environment.rb中,我有:

    config.time_zone = 'UTC'
    

    系统时区(如“日期”所报告的)是BST(即GMT+1),因此不知何故,它最终会被视为UTC并中断查询。

    这给我带来了各种各样的问题,因为我需要参数化在不同时间传递给某个操作的查询(然后使用Time.parse()转换),即使我发送UTC时间,这个“一小时关闭”DST问题也会出现很多问题。即使使用“.gmtime()”似乎也不能解决问题。

    那么,这里发生了什么?围绕它进行编程的安全方法是什么?

    >> Model.find(:last).created_at
    => Tue, 11 Aug 2009 20:31:07 UTC +00:00
    >> Time.now
    => Tue Aug 11 22:00:18 +0100 2009
    >> Time.now.gmtime
    => Tue Aug 11 21:00:22 UTC 2009
    
    3 回复  |  直到 15 年前
        1
  •  13
  •   atw    9 年前

    这个 Time 时间 仍将根据您的本地时区进行操作。这就是Time.now返回BST时间的原因。

    你可能想与之互动 Time.zone . 您可以像调用Time类本身一样对此调用方法,但它将在指定的时区中返回它。

    Time.zone.now # => Tue, 11 Aug 2009 21:31:45 UTC +00:00
    Time.zone.parse("2:30 PM Aug 23, 2009") # => Sun, 23 Aug 2009 14:30:00 UTC +00:00
    

    另一件您必须小心的事情是,如果您曾经在比较时间的数据库上进行查询,但一定要使用UTC时间(即使您指定了不同的时区),因为Rails总是在数据库中存储UTC。

    Item.all(:conditions => ["published_at <= ?", Time.now.utc])
    

    而且,代替 Time.now-1.hour 1.hour.ago . 它更容易阅读,Rails将自动使用配置的时区。

        2
  •  0
  •   MatthewFord    14 年前

    Time.zone = 'UK'
    Time.zone.now
     => Sun, 17 Oct 2010 02:09:54 BST +01:00
    
        3
  •  0
  •   Murat    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