【问题标题】:Get the count of elements in a ruby range made of Time objects获取由 Time 对象组成的 ruby​​ 范围内的元素计数
【发布时间】:2012-06-20 22:34:55
【问题描述】:

如何获得由Time 对象组成的范围的大小或计数?

可以实现与我的伪 Ruby 代码相同的结果,但它不起作用:

((Time.now.end_of_day - 31.days)..(Time.now.end_of_day - 1.day)).size == 30

当前执行上述操作会出错:

NoMethodError: 2012-05-18 23:59:59 -0400..2012-06-17 23:59:59 -0400:Range 的未定义方法“大小”

并试图把它变成数组(range).to_a

无法从时间迭代

更新

有趣,刚刚尝试做

((Date.today.end_of_day - 31.days)..(Date.today.end_of_day - 1.day)).count

Users/.../gems/ruby/1.9.1/gems/activesupport-3.0.15/lib/active_support/time_with_zone.rb:322:警告:Time#succ 已过时;使用时间+1

然而

((Date.today - 31.days)..(Date.today - 1.day)).count == 31

我愿意接受吗?

还有((Date.today - 31.days)..(Date.yesterday)).count == 31

更新 2

另一方面,根据 Mu 的提示,我们可以这样做:

(((Time.now.end_of_day - 31.days)..(Time.now.end_of_day - 1.day)).first.to_date..((Time.now.end_of_day - 31.days)..(Time.now.end_of_day - 1.day)).last.to_date).count == 31

【问题讨论】:

  • 您打算实现什么?您的代码点中的 .size 表示您想要该范围将提供的元素数量,但您建议进行迭代。
  • 我不建议迭代,红宝石错误建议如此,我想得到我提到的大小/计数。好像有人改了我帖子的标题...
  • 另外,你是对的,上面的代码会在 2012-05-18 23:59:59 -0400..2012-06-17 23:59 给出错误NoMethodError: undefined method size': 59 -0400:Range`,我之前做的是(range).to_a,它给出了前面提到的错误,我会更新问题。
  • 可能最简单的方法是减去它们,正如 Andrew Marshall 所指出的那样。

标签: ruby time range


【解决方案1】:

没有像Range#size 这样的方法,尝试Range#count(如Andrew Marshall 所建议的那样),尽管它仍然不适用于一系列Time 对象。

如果要执行天数计算,最好使用Date 对象,或者直接实例化它们(例如Date.today - 31),或者在@987654327 上调用#to_date @对象。

Date 对象也可以用于迭代:

((Date.today - 2)..(Date.today)).to_a
=> [#<Date: 2012-06-17 ((2456096j,0s,0n),+0s,2299161j)>,
 #<Date: 2012-06-18 ((2456097j,0s,0n),+0s,2299161j)>,
 #<Date: 2012-06-19 ((2456098j,0s,0n),+0s,2299161j)>]

((Date.today - 2)..(Date.today)).map(&:to_s)
=> ["2012-06-17", "2012-06-18", "2012-06-19"]

【讨论】:

  • 不过有Range#count。它失败并出现与问题中的to_a 相同的错误。 (我想一个范围没有“大小”,因为它没有以有意义的方式包含实际对象,但它确实对它所代表的范围内的对象数量进行了“计数”。)
【解决方案2】:

这是因为日期范围的大小没有意义——它不知道您是否希望将其视为天、分、秒、月或其他形式。错误提到迭代的原因是,为了确定范围的大小,它必须知道如何对它们进行迭代,以便计算元素的数量。

既然你想要的是天的差异,那就这样做吧:

date_one = Time.now.end_of_day - 31.days
date_two = Time.now.end_of_day - 1.day

((date_one - date_two) / 1.day).abs
#=> 30.0

您必须除以 1.day,因为 Times 的差异返回秒数。

【讨论】:

  • irb(main):016:0&gt; Time.now - Time.now+50 =&gt; 49.999998633 irb(main):017:0&gt; Time.now - Time.now+40 =&gt; 39.999998196 irb(main):018:0&gt; 对我来说很好,没有 /(1.day) 的事件。
  • 谢谢,但如果可能的话,我想从范围中获取数字,而不是重写代码。想象一下,您只需要使用范围即可。
  • @VictorS 由于我概述的原因,这是不可能的。您必须重写代码或将范围的端点更改为 Times 以外的其他值。
【解决方案3】:

为了让您的代码能够正常工作,您应该将 .size 之前的所有内容都用括号括起来。

也许您可以从另一个对象中减去一个时间对象,而不是使用范围?

我知道您使用 Date 对象制作范围,因此您可以转换为该范围。

【讨论】:

  • 谢谢,我将它分配给我的代码中的一个变量,但是对于这个例子你是对的,我已经重新格式化了它。但是,我认为它实际上并没有什么不同......
猜你喜欢
  • 2019-12-14
  • 2021-05-26
  • 2019-01-23
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-13
相关资源
最近更新 更多