11

Ruby 的日期/时间助手很有用,但我发现了一个差异。似乎 12.months 不等于 1.year。检查 1.month,您会发现它等于 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.year 等于 365.25 天的秒数,为什么您认为他们没有 1.month 返回一年中 1/12 的秒数而不是 30 天?

有没有人遇到过这个?有没有人有更好的解决方案?

4

4 回答 4

25

日历,一般来说,时间是这样一个随意的东西,充满了这样的不一致。“月”没有标准长度,因为变化在 28 到 31 天之间,就像“天”没有标准长度一样,可以是 23 到 25 小时,甚至分钟也可以是考虑到“闰秒”时为 59 到 62 秒。同样,一年可以是 365 天或 366 天,甚至是 351 天,就像 1582 年的情况一样。

除非您正在执行特定于特定间隔的计算,例如 2010 年 1 月 3 日和 2011 年 10 月 19 日之间的秒数,否则您将无法知道使用抽象月、日或年的间隔有多长。这些事情取决于大量的因素。

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

于 2010-11-12T21:28:08.130 回答
9

是和否:

12 months与将它们用作相对间隔时相同1 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 天”,这与其他任何近似值一样好,而您坚持使用它。

文档中指出了这一点:

虽然这些方法在如上述示例中使用时提供了精确的计算,但应注意,如果在使用前转换“月”、“年”等的结果,则情况并非如此

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

于 2010-11-12T21:39:16.837 回答
0

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

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

于 2010-11-12T21:29:57.677 回答
0
require 'date'

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

如果要减去月份,请使用 << 。

于 2010-11-12T21:34:36.507 回答