在Ruby中,12个月!= 1。1年

时间:2010-11-12 21:17:06

标签: ruby-on-rails ruby date-math

Ruby的日期/时间助手很有用,但我发现了一个差异。似乎12个月不等于1年。检查1.月,你会发现它等于30.days,当然,12 * 30.days = 360.days,比实际年份长5.25天。

当我根据客户指定的授权月数设置访问我们网站的某些组件时,我遇到了这种情况。我发现在运行我的测试时,一个36个月的术语提前几周到期了。解决方案是这样的:

def months_to_seconds(number_of_months)
  ( (number_of_months.to_f / 12) * 1.year).to_i.seconds
end

这将返回number_of_months表示的一年中任何一小部分的秒数。

由于1年是等于几天到365.25天,为什么你认为他们没有1.月份返回一年的1/12而不是30天的秒数?

以前有没有人碰过这个?有没有人有更好的解决方案?

4 个答案:

答案 0 :(得分:24)

日历和时间一般都是如此随意,并且充满了这样的不一致。没有标准长度的“月”,因为变化在28到31天之间,正如没有标准长度的“日”,可以是23到25小时,甚至分钟可以有任何地方考虑“闰秒”时59到62秒。同样,一年可以是365或366天,甚至是1582年的351。

除非您正在针对特定时间间隔进行计算,例如2010年1月3日到2011年10月19日之间的秒数,否则您将无法知道时间间隔使用抽象月份,天数或年份。这些因素取决于很多因素。

您的解决方案适用于您的应用程序,但在Rails术语中,为简单起见,“月份”仅为30天,就像“白天”为24小时一样。

答案 1 :(得分:9)

是和否:

当您将它们用作相对间隔时,

12 months1 year相同,因为它们不会转换为秒:

t = Time.now
#=> 2010-11-12 22:34:57 0100
t - 1.year == t - 12.months
#=> true

在内部,这些间隔保存为年,月和日数的数组,所以如果你说,例如:

1.year - 12.months
#=> 1 year and -12 months

这意味着减法导致的间隔为“一年零下12个月”。

但是如果你to_i他们,他们需要被转换为精确的秒数,并且有人认为“一个月”意味着“30天”,这与任何其他的一样好,而你坚持用它。

文档中指出了这一点:

  

虽然这些方法提供了精确的   计算时用作   上面的例子,应该小心   要注意的是,如果这不是真的   “月”,“年”等的结果是   使用前转换

我猜这些间隔可以在某种程度上被视为“懒惰评估”。

答案 2 :(得分:0)

1个月由12个月组成,但其中几个月的大小不同。鉴于一个月可能实际上是28个月,29个月,30个月或31个日历日,因此可以合理地预期任何给定的月份长度定义可能不是您想要的。

就个人而言,在大多数情况下,我使用4周作为一个月的定义。在这种情况下,如果您授予“一个月”访问权限,我倾向于存储授予访问权限的月份日期。然后,取月份数,并在一个月的同一天过期N个月数。

答案 3 :(得分:0)

require 'date'

expire_date = Date.today >> 36
puts expire_date #=> 2013-11-12

如果您想减去月数,请使用<<