Мое решение подчеркивает эффективность за счет простоты. Я предполагаю, что начальная дата - будний день.
require 'date'
def lookin_back(start_date, n)
days_after_monday = start_date.wday - 1
return start_date - n if n <= days_after_monday
weeks, days = (n - days_after_monday).divmod(5)
start_date - days_after_monday - 7*weeks - (days > 0 ? days + 2 : 0)
end
start_date = Date.today
#=> #<Date: 2018-04-30 ((2458239j,0s,0n),+0s,2299161j)>
start_date.wday
#=> 1 (Monday)
lookin_back(start_date, 0)
#=> #<Date: 2018-04-30 ((2458239j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 1)
#=> #<Date: 2018-04-27 ((2458236j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 5)
#=> #<Date: 2018-04-23 ((2458232j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 6)
#=> #<Date: 2018-04-20 ((2458229j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 7)
#=> #<Date: 2018-04-19 ((2458228j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 11)
#=> #<Date: 2018-04-13 ((2458222j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 16)
#=> #<Date: 2018-04-06 ((2458215j,0s,0n),+0s,2299161j)>
start_date += 2
#=> #<Date: 2018-05-02 ((2458241j,0s,0n),+0s,2299161j)>
start_date.wday
#=> 3 (Wednesday)
lookin_back(start_date, 0)
#=> #<Date: 2018-05-02 ((2458241j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 1)
#=> #<Date: 2018-05-01 ((2458240j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 2)
#=> #<Date: 2018-04-30 ((2458239j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 3)
#=> #<Date: 2018-04-27 ((2458236j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 5)
#=> #<Date: 2018-04-25 ((2458234j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 10)
#=> #<Date: 2018-04-18 ((2458227j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 15)
#=> #<Date: 2018-04-11 ((2458220j,0s,0n),+0s,2299161j)>
lookin_back(start_date, 12345)
#=> #<Date: 1971-01-06 ((2440958j,0s,0n),+0s,2299161j)>