Rails рассчитывает диапазон дат в месяцах - PullRequest
11 голосов
/ 04 мая 2011

Как рассчитать разницу двух дат в месяцах?Кроме того, если это имеет значение, я работаю с объектами Date, а не DateTime.Кроме того, некоторые варианты округления могут быть хорошими, поэтому я могу контролировать, хочу ли я округлять вверх или вниз в отдельные месяцы.

Спасибо!

Ответы [ 8 ]

10 голосов
/ 04 мая 2011

Вычитание одного Date или DateTime из другого даст количество дней в виде дроби, но это может быть оценено как Float или Fixnum, как требуется.

Например:

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

Между сегодняшним днем ​​и той же календарной датой три месяца назад было 89,0 дней. Если вы работаете с этим, используя 30-дневные месяцы, или 30,4375, как они в среднем, у вас останется 2,92 месяца, прошедшие между тогда и сейчас, или округленные до ближайшего целого числа, 3 *.

Если вы хотите вычислить точное количество календарных месяцев, это сложнее, но может быть сделано.

5 голосов
/ 04 января 2012

Нам нужно было что-то в этом роде, но включая неполные месяцы.Таким образом, с 1/31 до 2/1 все равно будет 2 месяца.Могу помочь!

def self.month_count(range)
  12 * (range.end.year - range.begin.year) + range.end.month - range.begin.month
end
5 голосов
/ 05 мая 2011

Что-то вроде этого более читабельно, чем вычисление секунд, и даст вам реальную календарную разницу:

# 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

Если вам нужно рассчитать разницу также по дням, вы можете просто следовать схеме

5 голосов
/ 04 мая 2011

Это должно дать правильное приближение:

Date1 - Date2 = difference_in_days
(difference_in_days/30).round = difference_in_months
1 голос
/ 27 марта 2015

Этот ответ опаздывает на вечеринку, основывается на предыдущих ответах и, вероятно, может быть написан более кратко, однако он дает календарную разницу между двумя датами с учетом дней.

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
0 голосов
/ 26 сентября 2017

Мне нужно было точное количество месяцев (включая десятичные) между двумя датами, и я написал для него следующий метод:

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

Он опирается на ActiveSupport Rails.

0 голосов
/ 08 августа 2014

как насчет этой практики?

current_date = start_date

while current_date < end_date
  # something  
  current_date = current_date.next_month
end
0 голосов
/ 04 мая 2011

Для этой функции есть помощник рельсов:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...