Rails以月为单位计算日期范围

时间:2011-05-04 17:56:01

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

如何计算两个月的差异?此外,它有所作为,我正在使用Date对象,而不是DateTime。此外,一些舍入选项可能会很好,所以我可以控制是否要在部分月份进行向上或向下舍入。

谢谢!

8 个答案:

答案 0 :(得分:10)

从另一个日期或日期时间中减去一个会产生天数作为分数,但可以根据需要将其评估为FloatFixnum

例如:

(Date.today - Date.today.advance(:months => -3)).to_f
# => 89.0

从今天到三个月前的同一日历日期之间有89.0天。如果你使用平均30天或30.4375这样做,你最终会在当时和现在之间经过2.92个月,或者向上舍入到最接近的整数3。

如果您想计算精确的日历月数,那就更难了,但可以完成。

答案 1 :(得分:5)

这应该给出一个o.k.近似:

Date1 - Date2 = difference_in_days
(difference_in_days/30).round = difference_in_months

答案 2 :(得分:5)

这样的东西比计算秒数更具可读性,并且会给你实际的日历差异:

# Calculate differnce between two dates in months
# Produces b - a
def month_difference(a, b)
    difference = 0.0
    if a.year != b.year
        difference += 12 * (b.year - a.year)
    end
    difference + b.month - a.month
end

如果你需要根据天数来计算差异,你可以按照模式

答案 3 :(得分:5)

我们需要这些方面的东西,但包括部分月份。所以1/31到2/1仍然会产生2个月。可能会有帮助!

def self.month_count(range)
  12 * (range.end.year - range.begin.year) + range.end.month - range.begin.month
end

答案 4 :(得分:1)

这个答案迟到了,以前面的答案为基础,并且可能写得更简洁,但它确实给出了考虑几天的两个日期之间的日历差异。

def difference_in_months(start_date, today)
  date_to_months(today) - date_to_months(start_date) + adjustment_for_days(start_date, today)
end

def date_to_months(date)
  date.year * 12 + date.month
end

def adjustment_for_days(earlier_date, later_date)
  if later_date.day == earlier_date.day
    0
  elsif later_date.day > earlier_date.day
    1
  else
   -1
  end
end

答案 5 :(得分:0)

答案 6 :(得分:0)

这种做法怎么样?

current_date = start_date

while current_date < end_date
  # something  
  current_date = current_date.next_month
end

答案 7 :(得分:0)

我需要两个日期之间的确切月数(包括小数),并为其编写了以下方法。

def months_difference(period_start, period_end)
  period_end = period_end + 1.day
  months = (period_end.year - period_start.year) * 12 + period_end.month - period_start.month - (period_end.day >= period_start.day ? 0 : 1)
  remains = period_end - (period_start + months.month)

  (months + remains/period_end.end_of_month.day).to_f.round(2)
end

如果比较让我们说9月26日到9月26日(同一天)我将其计算为1天。如果您不需要,可以删除方法中的第一行:period_end = period_end + 1.day

它通过了以下规范:

expect(months_difference(Date.new(2017, 8, 1), Date.new(2017, 8, 31))).to eq 1.0
expect(months_difference(Date.new(2017, 8, 1), Date.new(2017, 8, 30))).to eq 0.97
expect(months_difference(Date.new(2017, 8, 1), Date.new(2017, 10, 31))).to eq 3.0
# Overlapping february (28 days) still counts Feb as a full month
expect(months_difference(Date.new(2017, 1, 1), Date.new(2017, 3, 31))).to eq 3.0
expect(months_difference(Date.new(2017, 2, 10), Date.new(2017, 3, 9))).to eq 1.0
# Leap year
expect(months_difference(Date.new(2016, 2, 1), Date.new(2016, 2, 29))).to eq 1.0

它依赖于Rails&#39;的ActiveSupport。