2012-05-03 27 views
15

私は、ユーザが日付範囲を入力し、日、月曜日、火曜日、水曜日、木曜日、金曜日、土曜日などの曜日/曜日のチェックボックスのリストから選択するフォームに取り組んでいます。Rubyで日曜日の間に日曜日を取得するにはどうすればいいですか?

フォームが提出されたら、選択した日に基づいて入力された2つの日付間の日付のリスト、つまり、与えられた2つの日付の間のすべての月曜日と木曜日を取得する方法が必要です。私はドキュメントを見てきましたが、これを効率的に行う方法、つまりルビーの方法を指摘することはできません。

答えて

46

楽しい1つ! :D

start_date = Date.today # your start 
end_date = Date.today + 1.year # your end 
my_days = [1,2,3] # day of the week in 0-6. Sunday is day-of-week 0; Saturday is day-of-week 6. 
result = (start_date..end_date).to_a.select {|k| my_days.include?(k.wday)} 

上記のデータを使用すると、今年と来年の間にすべての月曜日/火曜日/水曜日の配列が取得されます。

+1

素晴らしい:Dのおかげで!さて、それはどうやってルビーで行われるべきかのように見えます! – Ali

+1

私は 'to_a'の代わりに' to_enum'を使うことを提案します。 –

+0

制限が無制限になる可能性は低くなります。私はまだサイズ(日数)がよく質問されるかもしれないので配列を選ぶだろう。 – TomDunning

0

上記の回答は論理的には正しいものの、時間がかかります。ベンチマークを行いましたが、ここでは違いがあります。

第2のアプローチの実行時間は非常に短くなります。上記のプログラムの

クローン:

def check_fridays(d1, d2) 
my_days = [5] 
(Date.parse(d1)..Date.parse(d2)).to_a.select { |k| my_days.include?(k.wday) } 
end 

start_time = Time.now(); 
fridays = check_fridays("2015/10/03", "4037/11/30") 
endtime = Time.now(); 

p "Time Taken #{(endtime - start_time) * 1000.0}" 

p "There are #{fridays.length} Fridays " 

出力

"Time Taken 486.922" 
"There are 105511 Fridays " 

第二のアプローチ:

require 'date' 

def check_fridays(d1, d2) 

    # Compare the input values and swap accordingly 
    d1p = d1 <= d2 ? Date.parse(d1) : Date.parse(d2) 
    d2p = d2 >= d1 ? Date.parse(d2) : Date.parse(d1) 

    # Total Number Days 
    number_of_days = (d2p-d1p).to_i 

    # Total Number Of Weeks 
    total_weeks = number_of_days/7 

    # Get The Reminder For Friday Check 
    remaining_days = number_of_days%7 

    # Check if any friday lies in remaining days 
    if is_there_any_friday(remaining_days, d1p, d2p) 
    total_weeks += 1 
    end 

    #Return The Total No Of Fridays 
    total_weeks 
end 

def is_there_any_friday(remaining_days, start_date, end_date) 
    got_friday = false #First set variable as false 

    #First check from start date 
    (0..remaining_days).each do |i| 
    got_friday = (start_date+i).friday? 
    end 

    # If There Is No Friday Found In Start Date 
    unless got_friday 
    (0..remaining_days).each do |i| 
     got_friday = (end_date-i).friday? 
    end 
    end 

    #Return True OR False 
    got_friday 
end 

start_time = Time.now() 
fridays = check_fridays("2015/10/03", "4037/11/30") 
end_time = Time.now() 

p "Time Taken #{(end_time - start_time) * 1000.0}" 

p "There are #{fridays} Fridays " 

出力

"Time Taken 0.754" 
"There are 105511 Fridays " 
+0

よくできた@A H K、その素晴らしい。 –

+2

「2015/10/03」と「4037/11/30」の間に5金曜日はありません。 5週間のデータセットに対して自分のコードを実行すると、あなたのものと同じ速さで実行されます。それはまた、質問で求められたものであるカウントではなく、日付を返します。入力と一致する出力であなたの答えを更新できますか?私はいつもより良い解決策を見つけるために船に乗っています! – TomDunning

+0

is_there_any_fridayメソッド内で反復処理を行い、金曜日を見つけたら壊す必要があります。 – brianfalah

4

別のアプローチは、wdayによってグループにあなたの日付範囲で、週の一日を狙い撃ち:

datesByWeekday = (start_date..end_date).group_by(&:wday) 
datesByWeekday[6] # All Sundays 

例えば、2016年3月中のすべての日曜日を得るために:

> (Date.new(2016,03,01)..Date.new(2016,04,01)).group_by(&:wday)[6] 
=> [Sat, 05 Mar 2016, Sat, 12 Mar 2016, Sat, 19 Mar 2016, Sat, 26 Mar 2016] 
関連する問題