如何在Ruby中从另一个中减去一次?

时间:2014-09-22 08:14:55

标签: ruby timespan

我需要从另一个时间减去一次。

示例:timespan1是2014年1月1日到2014年1月15日.timespan2是1月5日到1月10日。我想得到类似的内容:

timespan1 - timespan2 = 01/01 to 01/04 AND 01/11 to 01/15

我可以使用这样的宝石吗?如果我想手动执行此操作,我必须考虑很多情况(时间跨度重叠/不重叠,部分/完全重叠等)如果不是宝石,可能是一个比考虑所有这些更简单的算法的想法案件分开?

2 个答案:

答案 0 :(得分:1)

您可以使用常规的Date对象数组来解决您的示例。假设你只使用几天,我相信在你感兴趣的情况下这会很好用。那就是:

require 'date'

a = [* Date.new(2014,1,1) .. Date.new(2014,1,15)]
b = [* Date.new(2014,1,5) .. Date.new(2014,1,10)]

diff = a - b

diff.each { |date| puts date.strftime('%d %B %Y') }

# Output:
# 01 January 2014
# 02 January 2014
# 03 January 2014
# 04 January 2014
# 11 January 2014
# 12 January 2014
# 13 January 2014
# 14 January 2014
# 15 January 2014

答案 1 :(得分:0)

假设

r1 = (f1..l1)
r2 = (f2..l2)

其中f1l1f2l2是日期对象(可能是从字符串转换而来的)或任何其他可以形成范围的对象。我假设您要构建一个数组,其中包含r1涵盖的r2未涵盖的所有元素。请注意,结果不一定表示为范围,因为在某些情况下,r1涵盖但r2覆盖的元素不是连续的,如r1 = (1..6)r2 = (3..4)时,结果为[1,2,5,6]

<强>代码

我们可以直接从两个给定范围的端点计算出所需的数组。有六种情况需要考虑,这些案例由case声明涵盖。

def range_difference(r1, r2)
  f1, l1 = r1.first, r1.last
  f2, l2 = r2.first, r2.last
  case
  when l2 < f1
    (f1..l1).to_a
  when f2 <= f1 && f1 <= l2 && l2 < l1
    (l2+1..l1).to_a
  when f2 <= f1 && l1 <= l2
    []
  when f1 < f2 && f2 < l1 && l2 < l1
    (f1..f2-1).to_a + (l2+1..l1).to_a
  when f1 < f2 && f2 <= l1 && l2 >= l1
    (f1..f2-1).to_a
  else # f2 > l1
    (f1..l1).to_a
  end
end

<强>实施例

range_difference((5..10),(2..7))
  #=> [8, 9, 10]
range_difference((5..10),(2..10))
  #=> []
range_difference((5..10),(6..8))
  #=> [5, 9, 10]
range_difference((5..10),(6..10))
  #=> [5]
range_difference((5..10),(7..12))
  #=> [5, 6]
range_difference((5..10),(10..12))
  #=> [5, 6, 7, 8, 9]
range_difference((5..10),(11..12))
  #=> [5, 6, 7, 8, 9, 10]