2011-05-04 54 views
11

如何計算月份中兩個日期的差異?此外,如果它有所作爲,我正在使用Date對象,而不是DateTime。此外,一些舍入選項可能會很好,所以我可以控制是否要在部分月份上舍入或捨棄。Rails以月爲單位計算日期範圍

謝謝!

+0

我喜歡這個,但它聽起來有點繁瑣的代碼。 ._。 – omninonsense 2011-05-04 18:02:57

+0

DateTime和Date可以使用'DateTime#to_date'和'Date#to_datetime'方法進行互換。 – tadman 2011-05-04 18:07:10

+0

也許,[一個類似的問題關於年](http://stackoverflow.com/questions/1904097/how-to-calculate-how-many-years-passed-since-a-given-date-in-ruby)可能幫你? – 2011-05-04 19:09:48

回答

9

減去另一個日期或日期時間將產生的天數作爲一小部分,但可以作爲一個或FloatFixnum根據需要進行評估。

例如:

(Date.today - Date.today.advance(:months => -3)).to_f 
# => 89.0 

有今天和三個月前相同的日曆日期間89.0天。如果您使用30天的月份或30.4375的平均值進行工作,則最終結束時間爲2.92個月,或者四捨五入爲最接近的整數3.如果您要計算精確的日曆月數,這是棘手的,但可以完成。

+0

日曆月將成爲首選...但如果它太棘手,我將只使用除以30(或30.44)的方法。 – brettish 2011-05-04 18:31:10

+0

你知道些什麼後,再想一想,以及如何嘗試實施日曆月,我認爲它不值得。我會用你的方法。 – brettish 2011-05-04 18:49:36

5

這應該給一個O.K.近似:

Date1 - Date2 = difference_in_days 
(difference_in_days/30).round = difference_in_months 
+0

是的,如果日曆月方法太難以勝任,我可能必須這樣做。 – brettish 2011-05-04 18:36:31

+1

您可能希望將'round'更改爲'floor'以獲得更準確的結果 – yalestar 2011-09-07 17:44:02

5

像這樣的事情是不是搞清楚秒更具可讀性,並會給你的實際日曆區別:

# Calculate differnce between two dates in months 
# Produces b - a 
def month_difference(a, b) 
    difference = 0.0 
    if a.year != b.year 
     difference += 12 * (b.year - a.year) 
    end 
    difference + b.month - a.month 
end 

如果你需要制定出基於天也不同,你可以按照模式

+0

哇,謝謝!這是一個有用的小塊代碼!看起來你可以通過用'difference = 12 *(b.year - a.year).abs'(用.abs替換方法的前4行來縮短事情,所以日期的順序無關緊要指定在) – brettish 2011-05-04 20:49:50

+0

@brettish我會保持絕對的功能外,否則該功能將丟棄方向信息。我也認爲你最終必須做好這個決定,以確保當a。年> b.年但是a.month Glenjamin 2011-05-05 08:41:38

+1

這裏有一個更清晰的版本[這裏](http://stackoverflow.com/questions/9428605/find-number-of-months-between-two-dates-in-ruby-on-rails):(date2.year * 12 + date2.month) - (date1.year * 12 + date1.month) – 2013-02-01 17:55:35

5

我們需要沿着這些路線,但包括部分月份。所以1/31到2/1仍然會產生2個月。可能有幫助!

def self.month_count(range) 
    12 * (range.end.year - range.begin.year) + range.end.month - range.begin.month 
end 
0

這種做法如何?

current_date = start_date 

while current_date < end_date 
    # something 
    current_date = current_date.next_month 
end 
1

這個答案是遲到了,建立在以前的答案,也許可以更簡明地寫的,但是,它確實給兩個日期需要幾天考慮的日曆差異。

def difference_in_months(start_date, today) 
    date_to_months(today) - date_to_months(start_date) + adjustment_for_days(start_date, today) 
end 

def date_to_months(date) 
    date.year * 12 + date.month 
end 

def adjustment_for_days(earlier_date, later_date) 
    if later_date.day == earlier_date.day 
    0 
    elsif later_date.day > earlier_date.day 
    1 
    else 
    -1 
    end 
end 
0

我需要幾個月的兩個日期之間的確切數字(包括小數),並寫了下面的方法吧。

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 

如果比較一下,比如說9月26日到9月26日(當天),我計算它爲1天。如果你不需要,你可以刪除的第一行中的方法:period_end = period_end + 1.day

它通過以下規格:

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 

它依賴於Rails的的ActiveSupport。