Как определить с Руби день назад в 14:00? - PullRequest
1 голос
/ 07 марта 2012

Мне нужно сделать поиск событий со вчерашнего дня в 14:00 и до сих пор, я пытаюсь вот так

events.where("DATE(created_at) >= ? and DATE(created_at) <=", (1.day.ago + 14.hours).strftime('%Y-%m-%d %H:%M:'), Time.now.strftime('%Y-%m-%d %H:%M:') )

Но он показывает пустой ... но когда я удалил "% H":% M: "из текста форматирования я тоже их получаю.

Ответы [ 5 ]

6 голосов
/ 07 марта 2012

Прежде всего, вам нужно понять, что такое «вчера в 14:00», и я бы перевел:

DateTime.now.yesterday.beginning_of_day.change(:hour => 14)

Многие из опубликованных здесь решений предлагают добавить 14 часов к началувчера, но это неправильно. Помните, летнее время !Что безопаснее, так это просто изменить час на соответствующее значение.

Нет 24 часов в день.Есть 23, 24 и 25 в зависимости от того, какой сегодня день.Чтобы продемонстрировать это, рассмотрим переходные периоды летнего времени:

Time.zone = 'EST5EDT'
DateTime.parse('2012-03-12 12:34:56 -0500').to_time_in_current_zone.yesterday.beginning_of_day + 14.hours
# => Sun, 11 Mar 2012 15:00:00 EDT -04:00

Это 3 часа дня, потому что с 1 до 2 утра не произошло.Используя change, вы всегда должны получать правильные результаты:

DateTime.parse('2012-03-12 12:34:56 -0500').to_time_in_current_zone.yesterday.beginning_of_day.change(:hour => 14)
# => Sun, 11 Mar 2012 14:00:00 EDT -04:00 

Часто вы можете также использовать оператор BETWEEN, чтобы упростить вычисления даты, но в вашем случае, так как вы выбираете между этой точкойвовремя и прямо сейчас, предполагая, что у вас нет событий в будущем, вы можете опустить один предел.Кроме того, ActiveRecord должен правильно обрабатывать форматирование значений DateTime при выполнении запросов, поэтому вызов strftime часто бывает неэффективным, так как вы легко можете ошибиться.причина:

events.where("DATE(created_at) BETWEEN ? AND ?", DateTime.now.yesterday.beginning_of_day.change(:hour => 14), DateTime.now)

Имейте в виду, что обычно выгодно хранить время в вашей базе данных в формате UTC и выполнять преобразование из местного времени в UTC при выполнении запросов.Хранение испорченных значений часовых поясов в базе данных может создать много проблем, если вам нужно работать с несколькими часовыми поясами одновременно.

4 голосов
/ 07 марта 2012

Если вы используете Rails (и похоже, что вы это делаете), вы хотите

1.day.ago.beginning_of_day + 14.hours

потому что

1.day.ago

даст вам ровно 24 часа назад.

Редактировать: пост Тадмана является более точным, поскольку он охватывает переход к летнему времени и обратно. Используйте

DateTime.now.yesterday.beginning_of_day.change(:hour => 14)
3 голосов
/ 07 марта 2012

Прежде всего, вы конвертируете свои created_at временные метки в даты, когда ваши условия поиска должны знать время суток. Вы можете исправить это, отбросив вызовы DATE() в своем запросе, и вам, вероятно, следует переключиться на BETWEEN, пока вы на нем.

Во-вторых, ваша арифметика дат, 1.day.ago + 14.hours, не обязательно даст "вчера в 14:00", так как 1.day.ago включает время суток. Вы можете исправить это, используя Date.yesterday + 14.hours.

В-третьих, вам не нужно strftime что-то делать самостоятельно, ActiveRecord будет обрабатывать всю строку самостоятельно.

В-четвертых, у вас может возникнуть проблема с часовым поясом в качестве побочного эффекта, когда вы вручную используете strftime, но не включаете часовой пояс. Если вы позволите ActiveRecord преобразовать ваше время в то, что ожидает база данных, тогда он применит необходимые вам настройки часового пояса.

Я думаю, вы хотите что-то более похожее на это:

events.where(
    'created_at between :start and :end',
    :start => Date.yesteday + 14.hours,
    :end   => Time.now
)
1 голос
/ 07 марта 2012

Это то, что вы ищете

events.where ("созданный между? И?", Time.local (1.day.ago.year, 1.day.ago.month, 1.day.ago.day, 14, 0) .to_s (: дБ), Time.now.to_s (: дБ))

0 голосов
/ 07 марта 2012

Полагаю, это бы сработало:

a = 1.day.ago.strftime('%Y-%m-%d')
yyyy, mm, dd = $1, $2, $3 if a =~ /(\d+)-(\d+)-(\d+)/
t = Time.mktime(yyyy, mm, dd, 14)
events.where("DATE(created_at) >= ? and DATE(created_at) <=", t.strftime('%Y-%m-%d %H:%M:'), Time.now.strftime('%Y-%m-%d %H:%M:') )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...