8

我有一个基于 Rails 时间的查询,它有一些奇怪的时区敏感行为,尽管据我所知我使用的是 UTC。简而言之,这些查询给出了不同的答案:

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

数据库实际上包含一个在最后一小时创建的模型,模型总数为 280。所以只有第一个查询是正确的。

但是,在 environment.rb 我有:

config.time_zone = 'UTC'

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

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

显然,差异是由某处的隐式转换导致 BST 被错误地视为 UTC 造成的,但为什么呢?Rails 不是以 UTC 格式存储时间戳吗?Time 类时区不知道吗?我正在使用 Rails 2.2.2

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

编辑,一些附加信息来显示 DB 和 Time 类在做什么:

>> 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
4

3 回答 3

13

该类Time不直接知道您配置的时区。Rails 2.1 添加了一堆时区支持,但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.hourdo 1.hour.ago。它更容易阅读,Rails 会自动使用配置的时区。

于 2009-08-11T21:36:04.153 回答
0

您需要设置的时区是英国,这将自动处理 BST

Time.zone = 'UK'
Time.zone.now
 => Sun, 17 Oct 2010 02:09:54 BST +01:00
于 2010-10-17T01:12:46.057 回答
0
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
于 2017-06-03T21:48:14.467 回答