【问题标题】:Compare a time to a range of times and return before, during, or after将时间与时间范围进行比较,并在之前、期间或之后返回
【发布时间】:2014-12-10 20:25:48
【问题描述】:

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

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)

是否有我遗漏的方法,或者另一种更简洁的方法来完成此任务?

【问题讨论】:

    标签: ruby-on-rails ruby time range


    【解决方案1】:

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

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

    【讨论】:

    • 一个小问题,我想。如果time = Time.now + 3600怎么办?
    • 好吧,如果设备报告它的最后一次更新是在未来,OP 可能想做一些不同的事情..
    • 对阅读问题不够谨慎的指控,我认罪了。
    • 感谢您的建议!我更喜欢@CarySwoveland 对哈希的使用,但我更喜欢你的编号,因为正如你所说,我不需要为未来的事件进行优化。
    【解决方案2】:

    怎么样:

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

    也许我遗漏了一些东西,但我不知道如何返回 :gray。我以这种方式组织它以处理未来的时间。

    【讨论】:

    • 我从没想过在我关心排序的地方使用哈希。太多年的习惯需要克服,我猜..
    • @MarkReed,我明白了。我们年轻人没有那种挂机。
    • 哎哟!摩擦它,现在! :)
    • 这是一个有趣的方法。我认为它比原始代码稍微迟钝,但似乎朝着更干净的方向发展。我会对此进行反思。谢谢!
    • 你是对的, :gray 不应该被关注,但我宁愿明确设置一个 else 也不要让它碰运气。
    【解决方案3】:

    您可以为Range 重载&lt;=&gt; 运算符:

    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。根据需要创建目录和文件。

    【讨论】:

    • 我不认为这是一种改进,因为您刚刚将我的案例语句翻译成 if/else。
    • @styger 请参阅第三种重载&lt;=&gt; 运算符的替代方案。
    • 为有趣的解决方案点赞!我一般不喜欢猴子补丁,所以我不会在生产代码中使用它,但它接近我想要的。谢谢!
    • @styger 没关系 - 一个女人的猴子补丁是另一个男人的延伸。但是,请考虑已添加到 String 类的所有“monkeypatches”导轨:api.rubyonrails.org/classes/String.html。在我看来,您已经选择了一个非常好的运算符来重载&lt;=&gt;,因为它内置了小于 () 的建议。 Range 类不使用此运算符,因此不可能发生冲突。如果它出现,我会在我的项目中使用它..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-14
    • 1970-01-01
    相关资源
    最近更新 更多