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



如何以月为单位计算两个日期之差?此外,如果有区别的话,我正在使用Date对象,而不是DateTime。另外,一些四舍五入选项可能会很好,这样我就可以控制部分月份是向上还是向下。

谢谢!

从另一个Date或DateTime中减去一个Date或DateTime将产生作为分数的天数,但这可以根据需要计算为FloatFixnum

例如:

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

今天与三个月前的同一日历日期之间有89.0天。如果您使用30天的月来计算,或者平均为30.4375,那么从那时到现在已经经过了2.92个月,或者四舍五入到最接近的整数3。

如果您想要计算日历月的精确数目,这是比较棘手的,但可以做到。

这样的东西比计算秒更容易读,并且会给出实际的日历差异:

# 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

如果您也需要计算基于天数的差异,您可以按照模式

我们需要这样的内容,但要包括部分月份。所以1/31到2/1的收益率仍然是2个月。可能的帮助!

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

这应该是一个不错的近似:

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

这个答案来得太晚了,建立在之前的答案之上,可能可以写得更简洁,但是,考虑到天数,它确实给出了两个日期之间的日历差异。

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

这个功能有一个rails帮助器:

http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html method-i-distance_of_time_in_words

这种做法如何?

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

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

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

相关内容

  • 没有找到相关文章

最新更新