如何以月为单位计算两个日期之差?此外,如果有区别的话,我正在使用Date对象,而不是DateTime。另外,一些四舍五入选项可能会很好,这样我就可以控制部分月份是向上还是向下。
谢谢!
从另一个Date或DateTime中减去一个Date或DateTime将产生作为分数的天数,但这可以根据需要计算为Float
或Fixnum
。
(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