web-dev-qa-db-ja.com

Ruby on Railsで2つの日付間の月数を見つける

2つのRuby on Rails DateTimeオブジェクト。それらの間の月数を調べる方法は?(異なる年に属する可能性があることに注意してください)

88
phoenixwizard
(date2.year * 12 + date2.month) - (date1.year * 12 + date1.month)

詳細は http://www.Ruby-forum.com/topic/7212

161

より正確な答えは、距離のある日を考慮します。

たとえば、28/4/2000および1/5/20000 のではなく 1、次に使用できます:

(date2.year - date1.year) * 12 + date2.month - date1.month - (date2.day >= date1.day ? 0 : 1)
39
dgilperez

試してみる

((date2.to_time - date1.to_time)/1.month.second).to_i
14
knotito

質問を「日付の月の始まりの間に最初の日がいくつあるか」と言い換えてから、関数型のデータ変換を使用できます。

(date1.beginning_of_month...date2.beginning_of_month).select { |date| date.day == 1 }.size
8
shock_one

両方が日付であると仮定すると:((date2 - date1).to_f / 365 * 12).roundシンプル。

5
Andreykul

私が見つけたもう1つのソリューション(既にここに投稿されているソリューションから構築された)は、結果に1か月未満を含める場合に使用します。たとえば、距離は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...
2
Zack
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
2
Uğur Yılmaz
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
2
Ankit Varshney

総当たり攻撃のバリアントは次のとおりです。

date1 = '2016-01-05'.to_date
date2 = '2017-02-27'.to_date
months = 0

months += 1 while (date2 << (count+1)) >= date1
puts months # => 13

date2は常にdate1より大きくなければなりません

1
ole

別の方法があります。これは、2つの日付間の月全体の数を計算するのに役立ちます

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

2つの日付の間に正確な月数(小数を含む)が必要だったため、次のメソッドを作成しました。

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
0
mtrolle