web-dev-qa-db-fra.com

Trouver le nombre de mois entre deux dates dans Ruby on Rails

J'ai deux Ruby on Rails DateTime objets. Comment trouver le nombre de mois entre eux? (Gardant à l'esprit qu'ils peuvent appartenir à des années différentes))

88
phoenixwizard
(date2.year * 12 + date2.month) - (date1.year * 12 + date1.month)

plus d'informations sur http://www.Ruby-forum.com/topic/7212

161
Massimiliano Peluso

Une réponse plus précise prendrait en compte les jours de distance.

Par exemple, si vous considérez que la distance mensuelle de 28/4/2000 et 1/5/2000 est 0 plutôt que 1, vous pouvez alors utiliser:

(date2.year - date1.year) * 12 + date2.month - date1.month - (date2.day >= date1.day ? 0 : 1)
39
dgilperez

Essayez

((date2.to_time - date1.to_time)/1.month.second).to_i
14
knotito

Vous pouvez reformuler la question comme "combien de 1er jours existe-t-il entre le début des mois des dates", puis utiliser des transformations de données de style fonctionnel:

(date1.beginning_of_month...date2.beginning_of_month).select { |date| date.day == 1 }.size
8
shock_one

En supposant que les deux sont des dates: ((date2 - date1).to_f / 365 * 12).round simple.

5
Andreykul

Une autre solution que j'ai trouvée (basée sur une solution déjà publiée ici) est pour si vous voulez que le résultat comprenne des fractions de mois. Par exemple, la distance est 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...
2
Zack
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
2
Uğur Yılmaz
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
2
Ankit Varshney

Voici une variante de forçage brutal:

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 doit toujours être supérieur à date1

1
ole

Voici une autre méthode. Cela vous aidera à calculer le nombre de mois entiers entre deux dates

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
0

J'avais besoin du nombre exact de mois (décimales comprises) entre deux dates et j'ai écrit la méthode suivante pour cela.

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

Si l'on compare, disons du 26 septembre au 26 septembre (même jour), je le calcule comme 1 jour. Si vous n'en avez pas besoin, vous pouvez supprimer la première ligne de la méthode: period_end = period_end + 1.day

Il passe les spécifications suivantes:

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
0
mtrolle