Ho due oggetti DateTime di Ruby on Rails. Come trovare il numero di mesi tra di loro? (Tenendo presente che potrebbero appartenere ad anni diversi)
Ho due oggetti DateTime di Ruby on Rails. Come trovare il numero di mesi tra di loro? (Tenendo presente che potrebbero appartenere ad anni diversi)
Risposte:
(date2.year * 12 + date2.month) - (date1.year * 12 + date1.month)
maggiori informazioni su http://www.ruby-forum.com/topic/72120
(12 * (date2.year - date1.year) + date2.month - date1.month).abs if date1 && date2
Una risposta più accurata prenderebbe in considerazione i giorni in lontananza.
Ad esempio, se consideri che la distanza del mese da 28/4/2000
e 1/5/2000
è 0
piuttosto che 1
, puoi utilizzare:
(date2.year - date1.year) * 12 + date2.month - date1.month - (date2.day >= date1.day ? 0 : 1)
Provaci
((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
(Rinuncio alla formattazione ... non riesco a capirlo)
Date.new(2014, 10, 31), Date.new(1997, 4, 30)
ho ricevuto 213 invece di 210 mesi. Il motivo è che 1.month.seconds
è il numero di secondi in 30 giorni e non i secondi medi in un mese. Downvoting in modo che gli altri rimangano privi di bug.
Puoi riformulare la domanda come "quanti primi giorni ci sono tra l'inizio dei mesi delle date" e quindi utilizzare le trasformazioni dei dati in stile funzionale:
(date1.beginning_of_month...date2.beginning_of_month).select { |date| date.day == 1 }.size
Supponendo che entrambe siano date:
((date2 - date1).to_f / 365 * 12).round
semplice.
((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
Un'altra soluzione che ho trovato (costruita su una soluzione già pubblicata qui) è se vuoi che il risultato includa frazioni di un mese. Ad esempio la distanza è 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
Avevo bisogno del numero esatto di mesi (compresi i decimali) tra due date e ho scritto il seguente metodo per questo.
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
Se confrontiamo diciamo dal 26 settembre al 26 settembre (stesso giorno) lo calcolo come 1 giorno. Se non ti serve, puoi rimuovere la prima riga nel metodo:period_end = period_end + 1.day
Supera le seguenti specifiche:
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
Ecco un altro metodo. Ciò aiuterà a calcolare il numero di mesi interi tra due date
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