将时间与一系列时间进行比较,并在之前,期间或之后返回

时间:2014-12-10 20:25:49

标签: ruby-on-rails ruby time range

我正在设备上创建一个状态,该状态将根据设备发回读数后的时间长度为该设备设置指示颜色。这是我目前的解决方案:

def indicator(device)
  # ...
  time = latest_event_time(device.id)

  case
  when time < 12.hours.ago
    :red
  when time.between?(12.hours.ago, 2.hours.ago)
    :yellow
  when 2.hours.ago < time
    :green
  else
    :gray
  end
end

private

def latest_event_time(dev_id)
  # Get latest event time from database
end

我希望能够简单地检查time是否在指定时间范围之前,期间或之后,可能是这样的:

time <=> (2.hours.ago...12.hours.ago)

我是否缺少一种方法,或其他更清洁的方法来实现这一目标?

3 个答案:

答案 0 :(得分:2)

不知道你是否认为这是一种改进,但是:

color = [ [12, :red], [2, :yellow], [0, :green] ].find do |n, c| 
  n.hours.ago >= time
end.last

答案 1 :(得分:1)

您可以重载Range<=>运算符:

class Range
  # return index into a 3-element array for before, in, and after
  def <=>(x)
    x < self.begin ? 0 : include?(x) ? 1 : 2
  end
end

def indicator(device)
  # ...
  time = latest_event_time(device.id) or return :gray

  [:red,:yellow,:green].at (2.hours.ago...12.hours.ago) <=> time
end

集成

关于如何将重载定义集成到rails 4项目中的一个建议是将Range代码存储在lib/ext/range.rb中并添加行

require 'ext/range'

config/initializers/extensions.rb。根据需要创建目录和文件。

答案 2 :(得分:1)

怎么样:

def time_to_color(time)  
  { green: 2, yellow: 12, red: Float::Infinity }.find { |_,t|
    time <= t.hours_ago }.first
end

也许我错过了一些东西,但我不知道如何归还:gray。我这样组织它来处理将来的时间。