diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d925b0..7adbf88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0 - June 8, 2020 + +- Add seperate `working_day?` and `holiday?` methods to the calendar + ## 2.0.0 - May 4, 2020 🚨 **BREAKING CHANGES** 🚨 diff --git a/README.md b/README.md index 36b75eb..3a69e95 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,20 @@ calendar.business_day?(Date.parse("Sunday, 8 June 2014")) # => false ``` +More specifically you can check if a given `business_day?` is either a `working_day?` or a `holiday?` using methods on `Business::Calendar`. + +```ruby +# Assuming "Monday, 9 June 2014" is a holiday +calendar.working_day?(Date.parse("Monday, 9 June 2014")) +# => true +calendar.holiday?(Date.parse("Monday, 9 June 2014")) +# => true +# Monday is a working day, but we have a holiday so it's not +# a business day +calendar.business_day?(Date.parse("Monday, 9 June 2014")) +# => false +``` + ## Business day arithmetic The `add_business_days` and `subtract_business_days` are used to perform business day arithmetic on dates. diff --git a/lib/business/calendar.rb b/lib/business/calendar.rb index 3231922..8946c05 100644 --- a/lib/business/calendar.rb +++ b/lib/business/calendar.rb @@ -57,16 +57,26 @@ def initialize(config) set_extra_working_dates(config[:extra_working_dates]) set_working_days(config[:working_days]) set_holidays(config[:holidays]) + + unless (@holidays & @extra_working_dates).none? + raise ArgumentError, 'Holidays cannot be extra working dates' + end end # Return true if the date given is a business day (typically that means a # non-weekend day) and not a holiday. def business_day?(date) date = date.to_date - return true if extra_working_dates.include?(date) - return false unless working_days.include?(date.strftime('%a').downcase) - return false if holidays.include?(date) - true + working_day?(date) && !holiday?(date) + end + + def working_day?(date) + date = date.to_date + extra_working_dates.include?(date) || working_days.include?(date.strftime('%a').downcase) + end + + def holiday?(date) + holidays.include?(date.to_date) end # Roll forward to the next business day. If the date given is a business @@ -191,8 +201,6 @@ def parse_dates(dates) # Internal method for assigning holidays from a calendar config. def set_holidays(holidays) @holidays = parse_dates(holidays) - return if (@holidays & @extra_working_dates).none? - raise ArgumentError, 'Holidays cannot be extra working dates' end def set_extra_working_dates(extra_working_dates) diff --git a/lib/business/version.rb b/lib/business/version.rb index 2f78dfc..19d5867 100644 --- a/lib/business/version.rb +++ b/lib/business/version.rb @@ -1,3 +1,3 @@ module Business - VERSION = "2.0.0" + VERSION = "2.1.0" end diff --git a/spec/calendar_spec.rb b/spec/calendar_spec.rb index 10509ed..75919c6 100644 --- a/spec/calendar_spec.rb +++ b/spec/calendar_spec.rb @@ -202,6 +202,62 @@ end end + describe "#working_day?" do + let(:calendar) do + Business::Calendar.new(holidays: ["9am, Tuesday 1st Jan, 2013"], + extra_working_dates: ["9am, Sunday 6th Jan, 2013"]) + end + subject { calendar.working_day?(day) } + + context "when given a working day" do + let(:day) { date_class.parse("9am, Wednesday 2nd Jan, 2013") } + it { is_expected.to be_truthy } + end + + context "when given a non-working day" do + let(:day) { date_class.parse("9am, Saturday 5th Jan, 2013") } + it { is_expected.to be_falsey } + end + + context "when given a working day that is a holiday" do + let(:day) { date_class.parse("9am, Tuesday 1st Jan, 2013") } + it { is_expected.to be_truthy } + end + + context "when given a non-business day that is a working date" do + let(:day) { date_class.parse("9am, Sunday 6th Jan, 2013") } + it { is_expected.to be_truthy } + end + end + + describe "#holiday?" do + let(:calendar) do + Business::Calendar.new(holidays: ["9am, Tuesday 1st Jan, 2013"], + extra_working_dates: ["9am, Sunday 6th Jan, 2013"]) + end + subject { calendar.holiday?(day) } + + context "when given a working day that is not a holiday" do + let(:day) { date_class.parse("9am, Wednesday 2nd Jan, 2013") } + it { is_expected.to be_falsey } + end + + context "when given a non-working day that is not a holiday day" do + let(:day) { date_class.parse("9am, Saturday 5th Jan, 2013") } + it { is_expected.to be_falsey } + end + + context "when given a day that is a holiday" do + let(:day) { date_class.parse("9am, Tuesday 1st Jan, 2013") } + it { is_expected.to be_truthy } + end + + context "when given a non-business day that is no a holiday" do + let(:day) { date_class.parse("9am, Sunday 6th Jan, 2013") } + it { is_expected.to be_falsey } + end + end + describe "#roll_forward" do let(:calendar) do Business::Calendar.new(holidays: ["Tuesday 1st Jan, 2013"])