Rubyで2つのDateオブジェクト間の日数を見つけるにはどうすればよいですか?


141

2つのDateオブジェクト間の日数を見つけるにはどうすればよいですか?

回答:


170

終了日から開始日を引きます:

endDate - beginDate 

2
終了日から開始日を引くことを意味していると思います:)
Nader

99
一種のクライマクティックえっ?
Brig

18
注:irbでWirbleを使用している場合(出力を色分けするため)、有理数には最後に1が連結されます。うわぁ!to_iを使用して結果を整数に変換することができます
jwal

9
DateTimeオブジェクトがある場合は、必ずDate最初に変換してください。変換しないと、秒数が返されます(私は推測します)。
Joshua Muheim 2014

44
また、2つのDateオブジェクトを減算Rationalすると、次のように整数に型キャストする必要がある場合があります(endDate - beginDate).to_i
MusikAnimal

98
irb(main):005:0> a = Date.parse("12/1/2010")
=> #<Date: 4911063/2,0,2299161>

irb(main):007:0> b = Date.parse("12/21/2010")
=> #<Date: 4911103/2,0,2299161>

irb(main):016:0> c = b.mjd - a.mjd
=> 20

これは、修正ユリウス日番号を使用します。

ウィキペディアから:

ユリウス日(JD)は、紀元前4713年1月1日からの日数と1日の端数であり、紀元前グリニッジ正午、ユリウスの前向き暦です。


53

これはRuby 2.0で変更された可能性があります

これを行うと、私は分数を取得します。たとえばコンソール上(irbまたはrails c)

2.0.0-p195 :005 > require 'date'
 => true 
2.0.0-p195 :006 >  a_date = Date.parse("25/12/2013")
 => #<Date: 2013-12-25 ((2456652j,0s,0n),+0s,2299161j)> 
2.0.0-p195 :007 >  b_date = Date.parse("10/12/2013")
 => #<Date: 2013-12-10 ((2456637j,0s,0n),+0s,2299161j)> 
2.0.0-p195 :008 > a_date-b_date
 => (15/1) 

もちろん、intにキャストすると期待した結果が得られます

2.0.0-p195 :009 > (a_date-b_date).to_i
 => 15 

これはDateTimeオブジェクトでも機能しますが、この例のように秒数を考慮する必要があります

2.0.0-p195 :017 >   a_date_time = DateTime.now
 => #<DateTime: 2013-12-31T12:23:03-08:00 ((2456658j,73383s,725757000n),-28800s,2299161j)> 
2.0.0-p195 :018 > b_date_time = DateTime.now-20
 => #<DateTime: 2013-12-11T12:23:06-08:00 ((2456638j,73386s,69998000n),-28800s,2299161j)> 
2.0.0-p195 :019 > a_date_time - b_date_time
 => (1727997655759/86400000000) 
2.0.0-p195 :020 > (a_date_time - b_date_time).to_i
 => 19 
2.0.0-p195 :021 > c_date_time = a_date_time-20
 => #<DateTime: 2013-12-11T12:23:03-08:00 ((2456638j,73383s,725757000n),-28800s,2299161j)> 
2.0.0-p195 :022 > a_date_time - c_date_time
 => (20/1) 
2.0.0-p195 :023 > (a_date_time - c_date_time).to_i
 => 20 

29

Ruby 2.1.3では、次の点が変更されています。

> endDate = Date.new(2014, 1, 2)
 => #<Date: 2014-01-02 ((2456660j,0s,0n),+0s,2299161j)> 
> beginDate = Date.new(2014, 1, 1)
 => #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)> 
> days = endDate - beginDate
 => (1/1) 
> days.class
 => Rational 
> days.to_i
 => 1 

21

これはどう?

(beginDate...endDate).count

範囲は、一意のシリアルのセットです。そして...、排他的な範囲リテラルです。

だから、beginDate..(endDate - 1)同じです。例外ではありません。

beginDateendDateと等しい場合、一意であるため最初の要素が除外され...、最後の要素が除外されます。したがって、.count今日と今日の間の日付にしたい場合は、0を返します。


これは非常に良い答えです。beginDateがendDateよりも古い場合は、が返さ0れ、場合によっては完全に機能します。また、2つの日付が同じ場合は0を返します。また、通常の整数も返します。他の回答は整数に変換する必要があります。結果が負の場合は、0に変換する必要があります。
EmmanuelB



6

これらすべてが正しい結果に導いてくれましたが、

DateTime.now.mjd - DateTime.parse("01-01-1995").mjd

指摘すべき1つのヒント:RubyのDateTime.parseは、日付がDD / MM / YYYYまたはDD-MM-YYYYとして与えられることを期待しています。アメリカ人として、それはいつも私を捨てます!
rickumali 2014年

15
@rickumali世界の他のメンバーとして、Rubyのデフォルトの日付形式を使用してくれたことに感謝します。
Claudio Holanda 2015年

7
@rickumali Rubyは日付もYYYY-MM-DD形式で受け入れます。これは、とにかく誰もが使用する必要があるものです。
user513951

1

日=(endDate-beginDate)/(60 * 60 * 24)


5
日付は日数なので、これを行う必要はありません。私はあなたのソリューションがDateTimeの違いに関連するようになると思います。
suga_shane 2015

1

さて、「間」の意味にも注意してください...

days_apart = (to - from).to_i     # from + days_apart = to
total_days = (to - from).to_i + 1 # number of "selected" days
in_between_days = (to - from).to_i - 1 # how many days are in between from and to, i.e. excluding those two days
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.