Tengo dos objetos Ruby on Rails DateTime. ¿Cómo encontrar el número de meses entre ellos? (Teniendo en cuenta que pueden pertenecer a diferentes años)
Tengo dos objetos Ruby on Rails DateTime. ¿Cómo encontrar el número de meses entre ellos? (Teniendo en cuenta que pueden pertenecer a diferentes años)
Respuestas:
(date2.year * 12 + date2.month) - (date1.year * 12 + date1.month)
más información en http://www.ruby-forum.com/topic/72120
(12 * (date2.year - date1.year) + date2.month - date1.month).abs if date1 && date2
Una respuesta más precisa consideraría días en la distancia.
Por ejemplo, si considera que la distancia del mes desde 28/4/2000
y 1/5/2000
es en 0
lugar de 1
, puede usar:
(date2.year - date1.year) * 12 + date2.month - date1.month - (date2.day >= date1.day ? 0 : 1)
Dale una oportunidad a
((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
(Renuncio al formateo ... no puedo entenderlo)
Date.new(2014, 10, 31), Date.new(1997, 4, 30)
, recibí 213 en lugar de 210 meses. La razón de esto es que 1.month.seconds
es la cantidad de segundos en 30 días y no el promedio de segundos en un mes. Votar en contra para que otros se mantengan libres de errores.
Puede reformular la pregunta como "cuántos primeros días hay entre el comienzo de los meses de las fechas" y luego usar transformaciones de datos de estilo funcional:
(date1.beginning_of_month...date2.beginning_of_month).select { |date| date.day == 1 }.size
Suponiendo que ambos son fechas:
((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
Otra solución que encontré (construida a partir de una solución publicada aquí) es si desea que el resultado incluya fracciones de mes. Por ejemplo, la distancia es 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
Necesitaba el número exacto de meses (incluidos los decimales) entre dos fechas y escribí el siguiente método para ello.
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 comparamos, digamos el 26 de septiembre con el 26 de septiembre (el mismo día), lo calculo como 1 día. Si no lo necesita, puede eliminar la primera línea del método:period_end = period_end + 1.day
Pasa las siguientes especificaciones:
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
Aquí hay otro método. Esto ayudará a calcular el número de meses enteros entre dos fechas.
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