С holiday-gem вы также можете проверить, есть ли выходной. Если вы это сделаете, вы должны определить регион, который вам нужен.
Праздничная жемчужина позволяет также использовать субрегионы (например, us-va ...)
Пример кода с немецкими (де) и американскими (сша) праздниками.
require 'holidays'
require 'holidays/us'
require 'holidays/de'
require 'holidays/core_extensions/date'
class Date
include Holidays::CoreExtensions::Date #provide Date#holiday?
def next_business_day(region=:any)
skip_weekends_and_holidays(1,region)
end
def previous_business_day(region=:any)
skip_weekends_and_holidays(-1,region)
end
def skip_weekends_and_holidays(inc, region = :any)
date = self + inc
while (date.wday == 6 or date.holiday?(region) ) do
date += inc
end
date
end
end
Обратите внимание: skip_weekends_and_holidays
не увеличивает рабочие дни. Если вы увеличиваете 5 дней с понедельника, вы заканчиваете понедельник (если этот понедельник не является выходным). Если в течение 5 дней был праздничный день, возможен дополнительный прирост.
Тестовый код:
[
Date.new(2012,6,8), #Friday
Date.new(2012,6,10), #Monday
Date.new(2012,6,9), #Sunday
Date.new(2012,12,24), #Christmas eve
Date.new(2012,12,26), #After Christmas
].each{|t|
%w{us de}.each{|region|
puts "====#{region}======"
puts "Today: #{Date::DAYNAMES[t.wday]} #{Date::MONTHNAMES[t.mon]} #{t.day}"
nextday = t.next_business_day(region)
puts "Next B-day: #{Date::MONTHNAMES[nextday.mon]} #{nextday.day} - #{Date::DAYNAMES[nextday.wday]}"
previousday = t.previous_business_day(region)
puts "Previous B-day: #{Date::MONTHNAMES[previousday.mon]} #{previousday.day} - #{Date::DAYNAMES[previousday.wday]}"
}
Выписка из результата (канун Рождества):
====us======
Today: Monday December 24
Next B-day: December 26 - Wednesday
Previous B-day: December 23 - Sunday
В Германии два свободных дня (25 + 26,12):
====de======
Today: Monday December 24
Next B-day: December 27 - Thursday
Previous B-day: December 23 - Sunday
Обновление: я создал другую версию для определения нескольких рабочих дней:
require 'holidays'
require 'holidays/us'
require 'holidays/core_extensions/date'
#~ require 'holidays/de'
class Date
include Holidays::CoreExtensions::Date #provide Date#holiday?
def next_business_day(region=:any)
next_business_days(1,region)
end
def next_business_days(inc, region=:any)
date = self
inc.times{
date = date.next
while (date.wday == 6 or date.holiday?(region) ) do
date = date.next
end
}
date
end
def previous_business_day(region=:any)
previous_business_days(1,region)
end
def previous_business_days(inc, region=:any)
date = self
inc.times{
date = date.prev_day
while (date.wday == 6 or date.holiday?(region) ) do
date = date.prev_day
end
}
date
end
end
Мой тестовый код:
require 'test/unit'
class BDay_Test < Test::Unit::TestCase
def test_2012_06_08_us()
date = Date.new(2012, 6, 8)
assert_equal( Date.new(2012, 06, 10), date.next_business_day('us'))
assert_equal( Date.new(2012, 06, 7), date.previous_business_day('us'))
assert_equal( Date.new(2012, 06, 17), date.next_business_days(7, 'us'))
assert_equal( Date.new(2012, 05, 31), date.previous_business_day(7, 'us'))
end
def test_2012_06_08_de()
date = Date.new(2012, 6, 8)
assert_equal( Date.new(2012, 06, 10), date.next_business_day('de'))
assert_equal( Date.new(2012, 06, 7), date.previous_business_day('de'))
assert_equal( Date.new(2012, 06, 17), date.next_business_days(7, 'de'))
assert_equal( Date.new(2012, 05, 31), date.previous_business_day(7, 'de'))
end
def test_2012_06_10_us()
date = Date.new(2012, 6, 10)
assert_equal( Date.new(2012, 06, 11), date.next_business_day('us'))
assert_equal( Date.new(2012, 06, 8), date.previous_business_day('us'))
assert_equal( Date.new(2012, 06, 18), date.next_business_days(7, 'us'))
assert_equal( Date.new(2012, 06, 1), date.previous_business_day(7, 'us'))
end
def test_2012_06_10_de()
date = Date.new(2012, 6, 10)
assert_equal( Date.new(2012, 06, 11), date.next_business_day('de'))
assert_equal( Date.new(2012, 06, 8), date.previous_business_day('de'))
assert_equal( Date.new(2012, 06, 18), date.next_business_days(7, 'de'))
assert_equal( Date.new(2012, 06, 1), date.previous_business_day(7, 'de'))
end
def test_2012_06_09_us()
date = Date.new(2012, 6, 9)
assert_equal( Date.new(2012, 06, 10), date.next_business_day('us'))
assert_equal( Date.new(2012, 06, 8), date.previous_business_day('us'))
assert_equal( Date.new(2012, 06, 17), date.next_business_days(7, 'us'))
assert_equal( Date.new(2012, 06, 1), date.previous_business_day(7, 'us'))
end
def test_2012_06_09_de()
date = Date.new(2012, 6, 9)
assert_equal( Date.new(2012, 06, 10), date.next_business_day('de'))
assert_equal( Date.new(2012, 06, 8), date.previous_business_day('de'))
assert_equal( Date.new(2012, 06, 17), date.next_business_days(7, 'de'))
assert_equal( Date.new(2012, 06, 1), date.previous_business_day(7, 'de'))
end
def test_2012_12_24_us()
date = Date.new(2012, 12, 24)
assert_equal( Date.new(2012, 12, 26), date.next_business_day('us'))
assert_equal( Date.new(2012, 12, 23), date.previous_business_day('us'))
assert_equal( Date.new(2013, 01, 3), date.next_business_days(7, 'us'))
assert_equal( Date.new(2012, 12, 16), date.previous_business_day(7, 'us'))
end
def test_2012_12_24_de()
date = Date.new(2012, 12, 24)
assert_equal( Date.new(2012, 12, 27), date.next_business_day('de'))
assert_equal( Date.new(2012, 12, 23), date.previous_business_day('de'))
assert_equal( Date.new(2013, 01, 4), date.next_business_days(7, 'de'))
assert_equal( Date.new(2012, 12, 16), date.previous_business_day(7, 'de'))
end
def test_2012_12_26_us()
date = Date.new(2012, 12, 26)
assert_equal( Date.new(2012, 12, 27), date.next_business_day('us'))
assert_equal( Date.new(2012, 12, 24), date.previous_business_day('us'))
assert_equal( Date.new(2013, 01, 4), date.next_business_days(7, 'us'))
assert_equal( Date.new(2012, 12, 17), date.previous_business_day(7, 'us'))
end
def test_2012_12_26_de()
date = Date.new(2012, 12, 26)
assert_equal( Date.new(2012, 12, 27), date.next_business_day('de'))
assert_equal( Date.new(2012, 12, 24), date.previous_business_day('de'))
assert_equal( Date.new(2013, 01, 4), date.next_business_days(7, 'de'))
assert_equal( Date.new(2012, 12, 17), date.previous_business_day(7, 'de'))
end
end
См. test_2012_12_24_us()
и date.next_business_days(7,...
Вы заканчиваете в 2013 году, каждый праздник в период уважается.