Почему этот запрос рельсов ведет себя по-разному в зависимости от часового пояса? - PullRequest
8 голосов
/ 12 августа 2009

У меня есть запрос на основе времени по рельсам, который имеет нечетное поведение, чувствительное к часовому поясу, хотя, насколько я знаю, я использую 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, но почему? Разве рельсы не хранят метки времени в UTC? Разве часовой пояс класса Time не знает? Я использую Rails 2.2.2

Итак, что здесь происходит - и какой безопасный способ программирования вокруг него?

edit, некоторая дополнительная информация, чтобы показать, что делают 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

Ответы [ 3 ]

13 голосов
/ 12 августа 2009

Класс 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.hour сделайте 1.hour.ago. Его легче читать, и Rails автоматически использует настроенный часовой пояс.

0 голосов
/ 04 июня 2017
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
0 голосов
/ 17 октября 2010

Часовой пояс, который вам нужно установить, это Великобритания, он автоматически обрабатывает BST

Time.zone = 'UK'
Time.zone.now
 => Sun, 17 Oct 2010 02:09:54 BST +01:00
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...