11 ответов:
(date2.year * 12 + date2.month) - (date1.year * 12 + date1.month)дополнительная информация на http://www.ruby-forum.com/topic/72120
более точный ответ будет считать дни на расстоянии.
например, если учесть, что месяц-расстояние от
28/4/2000и1/5/2000и0, а не1, вы можете использовать:(date2.year - date1.year) * 12 + date2.month - date1.month - (date2.day >= date1.day ? 0 : 1)
вы можете перефразировать вопрос как "сколько первых дней существует между началом месяцев дат", а затем использовать функциональные преобразования данных:
(date1.beginning_of_month...date2.beginning_of_month).select { |date| date.day == 1 }.size
другое решение, которое я нашел (построенное из решения, опубликованного здесь уже), предназначено для того, чтобы результат включал доли месяца. Например, расстояние -
1.2 months.((date2.to_time - date1.to_time)/1.month.second).round(1) #Tenth of a month Ex: 1.2 ((date2.to_time - date1.to_time)/1.month.second).round(2) #Hundreth, ex: 1.23 months etc...
start_date = Date.today end_date = Date.today+90 months = (end_date.month+end_date.year*12) - (start_date.month+start_date.year*12) //months = 3
def difference_in_months(date1, date2) month_count = (date2.year == date1.year) ? (date2.month - date1.month) : (12 - date1.month + date2.month) month_count = (date2.year == date1.year) ? (month_count + 1) : (((date2.year - date1.year - 1 ) * 12) + (month_count + 1)) month_count end
вот вариант грубой силы:
date1 = '2016-01-05'.to_date date2 = '2017-02-27'.to_date months = 0 months += 1 while (date2 << (count+1)) >= date1 puts months # => 13
date2всегда должно быть большеdate1
мне нужно точное количество месяцев (включая дроби) между двумя датами и написал следующий метод для этого.
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Если сравнивать, скажем, 26 сентября с 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
вот еще один способ. Это поможет рассчитать количество полных месяцев между двумя датами
def months_difference(date_time_start, date_time_end) curr_months = 0 while (date_time_start + curr_months.months) < date_time_end curr_months += 1 end curr_months -= 1 if (date_time_start + curr_months.months) > date_time_end curr_months.negative? ? 0 : curr_months end
Comments