Mam dwa obiekty DateTime Ruby on Rails. Jak znaleźć liczbę miesięcy między nimi? (Pamiętając, że mogą należeć do różnych lat)
Mam dwa obiekty DateTime Ruby on Rails. Jak znaleźć liczbę miesięcy między nimi? (Pamiętając, że mogą należeć do różnych lat)
Odpowiedzi:
(date2.year * 12 + date2.month) - (date1.year * 12 + date1.month)
więcej informacji na http://www.ruby-forum.com/topic/72120
(12 * (date2.year - date1.year) + date2.month - date1.month).abs if date1 && date2
Dokładniejsza odpowiedź uwzględniłaby dni w oddali.
Na przykład, jeśli uważasz, że odległość miesięczna od 28/4/2000
i 1/5/2000
wynosi 0
raczej niż 1
, możesz użyć:
(date2.year - date1.year) * 12 + date2.month - date1.month - (date2.day >= date1.day ? 0 : 1)
Spróbuj
((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
(Rezygnuję z formatowania ... nie mogę tego rozgryźć)
Date.new(2014, 10, 31), Date.new(1997, 4, 30)
otrzymałem 213 zamiast 210 miesięcy. Powodem tego jest 1.month.seconds
liczba sekund w 30 dni, a nie średnia sekund w miesiącu. Głosowanie w dół, aby inni pozostali wolni od błędów.
Możesz przeformułować pytanie jako „ile pierwszych dni upływa między początkami miesięcy dat”, a następnie użyć transformacji danych w stylu funkcjonalnym:
(date1.beginning_of_month...date2.beginning_of_month).select { |date| date.day == 1 }.size
Zakładając, że obie daty są
((date2 - date1).to_f / 365 * 12).round
proste.
((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
Inne rozwiązanie, które znalazłem (zbudowane na podstawie rozwiązania zamieszczonego już tutaj) jest przeznaczone, jeśli chcesz, aby wynik obejmował ułamki miesiąca. Na przykład odległość to 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
Potrzebowałem dokładnej liczby miesięcy (w tym liczb dziesiętnych) między dwiema datami i napisałem dla niej następującą metodę.
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
Porównując powiedzmy 26 września do 26 września (tego samego dnia), obliczam to jako 1 dzień. Jeśli tego nie potrzebujesz, możesz usunąć pierwszą linię w metodzie:period_end = period_end + 1.day
Spełnia następujące specyfikacje:
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
Oto inna metoda. Pomoże to obliczyć liczbę pełnych miesięcy między dwiema datami
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
Rozwiązanie w każdym przypadku
(date1..date2).map { |date| date.strftime('%m.%Y') }.uniq.size