J'ai deux objets Ruby on Rails DateTime. Comment trouver le nombre de mois entre eux? (En gardant à l'esprit qu'ils peuvent appartenir à des années différentes)
J'ai deux objets Ruby on Rails DateTime. Comment trouver le nombre de mois entre eux? (En gardant à l'esprit qu'ils peuvent appartenir à des années différentes)
Réponses:
(date2.year * 12 + date2.month) - (date1.year * 12 + date1.month)
plus d'informations sur http://www.ruby-forum.com/topic/72120
(12 * (date2.year - date1.year) + date2.month - date1.month).abs if date1 && date2
Une réponse plus précise prendrait en compte les jours au loin.
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 utiliser:
(date2.year - date1.year) * 12 + date2.month - date1.month - (date2.day >= date1.day ? 0 : 1)
Essayez de
((date2.to_time - date1.to_time)/1.month.second).to_i
irb>Time.at("2014-10-01".to_time - "2014-12-01".to_time).month => 10
(J'abandonne le formatage ... je ne peux pas le comprendre)
Date.new(2014, 10, 31), Date.new(1997, 4, 30)
j'ai reçu 213 mois au lieu de 210. La raison en est que 1.month.seconds
c'est le nombre de secondes dans 30 jours et non la moyenne des secondes dans un mois. Downvoter pour que les autres restent sans bug.
Vous pouvez reformuler la question comme "combien de premiers jours y a-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
En supposant que les deux sont des dates:
((date2 - date1).to_f / 365 * 12).round
simple.
((date2 - date1).to_f / 60 / 60 / 24 / 365 * 12).round
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
Une autre solution que j'ai trouvée (basée sur une solution déjà publiée ici) est si vous souhaitez que le résultat inclue 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...
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
J'avais besoin du nombre exact de mois (y compris les décimales) 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 vous comparez, 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
Voici une autre méthode. Cela 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