为什么这个rails查询的行为有所不同,这取决于时区? [英] Why does this rails query behave differently depending on timezone?

查看:149
本文介绍了为什么这个rails查询的行为有所不同,这取决于时区?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a rails time-based query which has some odd timezone sensitive behaviour, even though as far as I know I'm using UTC. In a nutshell, these queries give different answers:

>> 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.所以只有第一个查询是正确的。

Where the DB actually does contain one model created in the last hour, and the total number of models is 280. So only the first query is correct.

然而,在environment.rb中我有:

However, in environment.rb I have:

config.time_zone = 'UTC'

系统时区(由'date'报告)是BST(这是GMT + 1) - 所以以某种方式这样做会被视为UTC和打破查询。

The system time zone (as reported by 'date') is BST (which is GMT+1) - so somehow this winds up getting treated as UTC and breaking queries.

这会导致我各种各样的问题,因为我需要将在不同时间传递的查询参数化为一个动作(然后使用Time.parse()转换)即使我在UTC时间发送,这个一个小时的DST问题也是很多。即使使用'.gmtime()'并不总是似乎修复它。

This is causing me all sorts of problems as I need to parameterise the query passing in different times to an action (which are then converted using Time.parse()), and even though I send in UTC times, this 'off by one hour' DST issue crops a lot. Even using '.gmtime()' doesn't always seem to fix it.

显然,这种差异是由某种隐含的转换引起的,导致BST被错误地视为UTC,但为什么? rails不会以UTC记录时间戳?时间班没有时区知道吗?我正在使用Rails 2.2.2

Obviously the difference is caused somehow by an implicit conversion somewhere resulting in BST being incorrectly treated as UTC, but why? Doesn't rails store the timestamps in UTC? Isn't the Time class timezone aware? I am using Rails 2.2.2

那么这里发生了什么 - 什么是安全的方式来编程?

So what is going on here - and what is the safe way to program around it?

编辑一些额外的信息,以显示DB和Time类的工作:

edit, some additional info to show what the DB and Time class are doing:

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


推荐答案

时间类不直接知道您配置的时区。 Rails 2.1添加了一大堆时区支持,但是 Time 仍然会对您的本地时区起作用。这就是为什么Time.now返回一个BST时间。

The Time class isn't directly aware of your configured timezone. Rails 2.1 added a bunch of timezone support, but Time will still act upon your local timezone. This is why Time.now returns a BST time.

你可能想要与 Time.zone 。您可以像Time Class本身一样调用方法,但它会在指定的时区返回。

What you likely want is to interact with Time.zone. You can call methods on this like you would the Time class itself but it will return it in the specified time zone.

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存储在数据库中。

Another thing you have to be careful with is if you ever do queries on the database where you are comparing times, but sure to use the UTC time (even if you have a different time zone specified) because Rails always stores UTC in the database.

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

另外,而不是 Time.now-1.hour do 1.hour.ago 。它更容易阅读,Rails会自动使用配置的时区。

Also, instead of Time.now-1.hour do 1.hour.ago. It is easier to read and Rails will automatically use the configured timezone.

这篇关于为什么这个rails查询的行为有所不同,这取决于时区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆