Просто отсортируйте истории в соответствии с разницей между переданной отметкой времени и отметкой времени истории (абсолютное значение, чтобы она могла двигаться в любом направлении), и верните максимальный результат (это результат с наименьшей разницей).
sensor.histories.order("ABS(time_stamp - #{params[:time_stamp].to_i})").first
Обратите внимание, что для этого запроса я предполагаю, что вы используете MySQL (потому что я использую метод MySQL ABS), и я также предполагаю, что поле time_stamp
хранится как метка времени Unix, а также пользовательский ввод. Если хранилище базы данных или входные данные находятся в другом формате, вам придется использовать другие арифметические функции даты. Смотрите http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html для деталей. Или, если вы не используете MySQL, обратитесь к документации по используемой вами базе данных.
Также обратите внимание, что я использую .to_i
для очистки моих данных для запроса. Если ваши данные находятся в другом формате, возможно, вам нужно очистить их другим способом.
Чтобы сделать это более эффективным, ограничьте его time_spans в максимально возможном диапазоне. Если датчики берут данные каждые 10 минут или чаще (не реже чем через 10 минут между считываниями), тогда диапазон с 10 сторон с каждой стороны подойдет. Что-то вроде ниже. Здесь 600 = 10 (минут) * 60 (секунд):
sensor.histories.where("time_stamp >= ? AND time_stamp <= ?", params[:time_stamp].to_i - 600, params[:time_stamp].to_i + 600).order("ABS(time_stamp - #{params[:time_stamp].to_i})").first
Это просто преобразовать в метод модели:
class Sensor < ActiveRecord::Base
def history_at(time_stamp)
self.histories.where("time_stamp >= ? AND time_stamp <= ?", time_stamp.to_i - 600, time_stamp.to_i + 600).order("ABS(time_stamp - #{time_stamp.to_i})").first
end
end