business 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +3 -0
- data/.rubocop.yml +13 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +4 -0
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/business.gemspec +9 -5
- data/lib/business.rb +3 -1
- data/lib/business/calendar.rb +65 -47
- data/lib/business/version.rb +3 -1
- data/spec/{calendar_spec.rb → business/calendar_spec.rb} +215 -87
- metadata +33 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a053f4e9b8b8fa5ed407b58d1e81155dac75f1f0c305410403011c608c69c60
|
4
|
+
data.tar.gz: 90cd733d6991516ae8c438824e669850d554147fbb47172f1c4f0dd0bdd44e37
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f09af74f16a84326d8b193f219b1d4de9362c618d197977e4c887df49a34e73d9ad3db154cfe7606fa43b3017b4448175ac37e598ea497e8f508888cf3a2bdb2
|
7
|
+
data.tar.gz: 9dc9a98ae02f7cb056af0bd710ac754594931c796d934b18695fafec5caecf1d7e4f107966863bc46d11e71e576b214cb774fd1a19dbe1d8c024483e55e27503
|
data/.circleci/config.yml
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
inherit_gem:
|
2
|
+
gc_ruboconfig: rubocop.yml
|
3
|
+
|
4
|
+
RSpec/NestedGroups:
|
5
|
+
Exclude:
|
6
|
+
- spec/business/calendar_spec.rb
|
7
|
+
|
8
|
+
# Disabled as API uses set_holidays etc
|
9
|
+
Naming/AccessorMethodName:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Gemspec/RequiredRubyVersion:
|
13
|
+
Enabled: false
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.7.1
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -23,7 +23,7 @@ We have removed the bundled calendars as of version 2.0.0, if you need the calen
|
|
23
23
|
- Add this directory path to your instance of `Business::Calendar` using the `load_paths` method.dd the directory to where you placed the yml files before you load the calendar
|
24
24
|
|
25
25
|
```ruby
|
26
|
-
Business::Calendar.load_paths
|
26
|
+
Business::Calendar.load_paths = ["lib/calendars"] # your_project/lib/calendars/ contains bacs.yml
|
27
27
|
Business::Calendar.load("bacs")
|
28
28
|
```
|
29
29
|
|
data/business.gemspec
CHANGED
@@ -1,23 +1,27 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
lib = File.expand_path("lib", __dir__)
|
3
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
6
|
+
require "business/version"
|
5
7
|
|
6
8
|
Gem::Specification.new do |spec|
|
7
9
|
spec.name = "business"
|
8
10
|
spec.version = Business::VERSION
|
9
11
|
spec.authors = ["Harry Marr"]
|
10
12
|
spec.email = ["developers@gocardless.com"]
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
+
spec.summary = "Date calculations based on business calendars"
|
14
|
+
spec.description = "Date calculations based on business calendars"
|
13
15
|
spec.homepage = "https://github.com/gocardless/business"
|
14
16
|
spec.licenses = ["MIT"]
|
15
17
|
|
16
|
-
spec.files = `git ls-files`.split(
|
18
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
21
|
spec.require_paths = ["lib"]
|
20
22
|
|
23
|
+
spec.add_development_dependency "gc_ruboconfig", "~> 2.24.0"
|
21
24
|
spec.add_development_dependency "rspec", "~> 3.1"
|
22
25
|
spec.add_development_dependency "rspec_junit_formatter", "~> 0.4.1"
|
26
|
+
spec.add_development_dependency "rubocop", "~> 1.10.0"
|
23
27
|
end
|
data/lib/business.rb
CHANGED
data/lib/business/calendar.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require "date"
|
3
5
|
|
4
6
|
module Business
|
5
7
|
class Calendar
|
8
|
+
VALID_KEYS = %w[holidays working_days extra_working_dates].freeze
|
9
|
+
|
6
10
|
class << self
|
7
11
|
attr_accessor :load_paths
|
8
12
|
end
|
@@ -12,54 +16,57 @@ module Business
|
|
12
16
|
end
|
13
17
|
private_class_method :calendar_directories
|
14
18
|
|
19
|
+
# rubocop:disable Metrics/MethodLength
|
15
20
|
def self.load(calendar_name)
|
16
|
-
data =
|
21
|
+
data = find_calendar_data(calendar_name)
|
22
|
+
raise "No such calendar '#{calendar_name}'" unless data
|
23
|
+
|
24
|
+
unless (data.keys - VALID_KEYS).empty?
|
25
|
+
raise "Only valid keys are: #{VALID_KEYS.join(', ')}"
|
26
|
+
end
|
27
|
+
|
28
|
+
new(
|
29
|
+
name: calendar_name,
|
30
|
+
holidays: data["holidays"],
|
31
|
+
working_days: data["working_days"],
|
32
|
+
extra_working_dates: data["extra_working_dates"],
|
33
|
+
)
|
34
|
+
end
|
35
|
+
# rubocop:enable Metrics/MethodLength
|
36
|
+
|
37
|
+
def self.find_calendar_data(calendar_name)
|
38
|
+
calendar_directories.detect do |path|
|
17
39
|
if path.is_a?(Hash)
|
18
40
|
break path[calendar_name] if path[calendar_name]
|
19
41
|
else
|
20
|
-
next unless File.
|
42
|
+
next unless File.exist?(File.join(path, "#{calendar_name}.yml"))
|
21
43
|
|
22
44
|
break YAML.load_file(File.join(path, "#{calendar_name}.yml"))
|
23
45
|
end
|
24
46
|
end
|
25
|
-
|
26
|
-
raise "No such calendar '#{calendar_name}'" unless data
|
27
|
-
|
28
|
-
valid_keys = %w(holidays working_days extra_working_dates)
|
29
|
-
|
30
|
-
unless (data.keys - valid_keys).empty?
|
31
|
-
raise "Only valid keys are: #{valid_keys.join(', ')}"
|
32
|
-
end
|
33
|
-
|
34
|
-
self.new(
|
35
|
-
holidays: data['holidays'],
|
36
|
-
working_days: data['working_days'],
|
37
|
-
extra_working_dates: data['extra_working_dates'],
|
38
|
-
)
|
39
47
|
end
|
40
48
|
|
41
49
|
@lock = Mutex.new
|
42
50
|
def self.load_cached(calendar)
|
43
51
|
@lock.synchronize do
|
44
|
-
@cache ||= {
|
45
|
-
unless @cache.include?(calendar)
|
46
|
-
@cache[calendar] = self.load(calendar)
|
47
|
-
end
|
52
|
+
@cache ||= {}
|
53
|
+
@cache[calendar] = self.load(calendar) unless @cache.include?(calendar)
|
48
54
|
@cache[calendar]
|
49
55
|
end
|
50
56
|
end
|
51
57
|
|
52
58
|
DAY_NAMES = %( mon tue wed thu fri sat sun )
|
53
59
|
|
54
|
-
attr_reader :holidays, :working_days, :extra_working_dates
|
60
|
+
attr_reader :name, :holidays, :working_days, :extra_working_dates
|
55
61
|
|
56
|
-
def initialize(
|
57
|
-
|
58
|
-
|
59
|
-
|
62
|
+
def initialize(name:, extra_working_dates: nil, working_days: nil, holidays: nil)
|
63
|
+
@name = name
|
64
|
+
set_extra_working_dates(extra_working_dates)
|
65
|
+
set_working_days(working_days)
|
66
|
+
set_holidays(holidays)
|
60
67
|
|
61
68
|
unless (@holidays & @extra_working_dates).none?
|
62
|
-
raise ArgumentError,
|
69
|
+
raise ArgumentError, "Holidays cannot be extra working dates"
|
63
70
|
end
|
64
71
|
end
|
65
72
|
|
@@ -70,12 +77,13 @@ module Business
|
|
70
77
|
working_day?(date) && !holiday?(date)
|
71
78
|
end
|
72
79
|
|
73
|
-
def working_day?(date)
|
80
|
+
def working_day?(date)
|
74
81
|
date = date.to_date
|
75
|
-
extra_working_dates.include?(date) ||
|
82
|
+
extra_working_dates.include?(date) ||
|
83
|
+
working_days.include?(date.strftime("%a").downcase)
|
76
84
|
end
|
77
85
|
|
78
|
-
def holiday?(date)
|
86
|
+
def holiday?(date)
|
79
87
|
holidays.include?(date.to_date)
|
80
88
|
end
|
81
89
|
|
@@ -98,19 +106,19 @@ module Business
|
|
98
106
|
# Roll forward to the next business day regardless of whether the given
|
99
107
|
# date is a business day or not.
|
100
108
|
def next_business_day(date)
|
101
|
-
|
109
|
+
loop do
|
102
110
|
date += day_interval_for(date)
|
103
|
-
|
104
|
-
|
111
|
+
break date if business_day?(date)
|
112
|
+
end
|
105
113
|
end
|
106
114
|
|
107
115
|
# Roll backward to the previous business day regardless of whether the given
|
108
116
|
# date is a business day or not.
|
109
117
|
def previous_business_day(date)
|
110
|
-
|
118
|
+
loop do
|
111
119
|
date -= day_interval_for(date)
|
112
|
-
|
113
|
-
|
120
|
+
break date if business_day?(date)
|
121
|
+
end
|
114
122
|
end
|
115
123
|
|
116
124
|
# Add a number of business days to a date. If a non-business day is given,
|
@@ -121,9 +129,10 @@ module Business
|
|
121
129
|
def add_business_days(date, delta)
|
122
130
|
date = roll_forward(date)
|
123
131
|
delta.times do
|
124
|
-
|
132
|
+
loop do
|
125
133
|
date += day_interval_for(date)
|
126
|
-
|
134
|
+
break date if business_day?(date)
|
135
|
+
end
|
127
136
|
end
|
128
137
|
date
|
129
138
|
end
|
@@ -136,9 +145,10 @@ module Business
|
|
136
145
|
def subtract_business_days(date, delta)
|
137
146
|
date = roll_backward(date)
|
138
147
|
delta.times do
|
139
|
-
|
148
|
+
loop do
|
140
149
|
date -= day_interval_for(date)
|
141
|
-
|
150
|
+
break date if business_day?(date)
|
151
|
+
end
|
142
152
|
end
|
143
153
|
date
|
144
154
|
end
|
@@ -146,8 +156,11 @@ module Business
|
|
146
156
|
# Count the number of business days between two dates.
|
147
157
|
# This method counts from start of date1 to start of date2. So,
|
148
158
|
# business_days_between(mon, weds) = 2 (assuming no holidays)
|
159
|
+
# rubocop:disable Metrics/AbcSize
|
160
|
+
# rubocop:disable Metrics/MethodLength
|
149
161
|
def business_days_between(date1, date2)
|
150
|
-
date1
|
162
|
+
date1 = date1.to_date
|
163
|
+
date2 = date2.to_date
|
151
164
|
|
152
165
|
# To optimise this method we split the range into full weeks and a
|
153
166
|
# remaining period.
|
@@ -169,14 +182,16 @@ module Business
|
|
169
182
|
num_biz_days -= holidays.count do |holiday|
|
170
183
|
in_range = full_weeks_range.cover?(holiday)
|
171
184
|
# Only pick a holiday if its on a working day (e.g., not a weekend)
|
172
|
-
on_biz_day = working_days.include?(holiday.strftime(
|
185
|
+
on_biz_day = working_days.include?(holiday.strftime("%a").downcase)
|
173
186
|
in_range && on_biz_day
|
174
187
|
end
|
175
188
|
|
176
|
-
remaining_range = (date2-remaining_days...date2)
|
189
|
+
remaining_range = (date2 - remaining_days...date2)
|
177
190
|
# Loop through each day in remaining_range and count if a business day
|
178
191
|
num_biz_days + remaining_range.count { |a| business_day?(a) }
|
179
192
|
end
|
193
|
+
# rubocop:enable Metrics/AbcSize
|
194
|
+
# rubocop:enable Metrics/MethodLength
|
180
195
|
|
181
196
|
def day_interval_for(date)
|
182
197
|
date.is_a?(Date) ? 1 : 3600 * 24
|
@@ -189,9 +204,12 @@ module Business
|
|
189
204
|
raise "Invalid day #{day}" unless DAY_NAMES.include?(normalised_day)
|
190
205
|
end
|
191
206
|
end
|
192
|
-
extra_working_dates_names = @extra_working_dates.map
|
207
|
+
extra_working_dates_names = @extra_working_dates.map do |d|
|
208
|
+
d.strftime("%a").downcase
|
209
|
+
end
|
193
210
|
return if (extra_working_dates_names & @working_days).none?
|
194
|
-
|
211
|
+
|
212
|
+
raise ArgumentError, "Extra working dates cannot be on working days"
|
195
213
|
end
|
196
214
|
|
197
215
|
def parse_dates(dates)
|
@@ -209,7 +227,7 @@ module Business
|
|
209
227
|
|
210
228
|
# If no working days are provided in the calendar config, these are used.
|
211
229
|
def default_working_days
|
212
|
-
%w
|
230
|
+
%w[mon tue wed thu fri]
|
213
231
|
end
|
214
232
|
end
|
215
233
|
end
|
data/lib/business/version.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "business/calendar"
|
2
4
|
require "time"
|
3
5
|
|
@@ -6,61 +8,72 @@ RSpec.configure do |config|
|
|
6
8
|
config.raise_errors_for_deprecations!
|
7
9
|
end
|
8
10
|
|
9
|
-
describe Business::Calendar do
|
11
|
+
RSpec.describe Business::Calendar do
|
10
12
|
describe ".load" do
|
13
|
+
subject(:load_calendar) { described_class.load(calendar) }
|
14
|
+
|
11
15
|
let(:dummy_calendar) { { "working_days" => ["monday"] } }
|
12
16
|
|
13
17
|
before do
|
14
|
-
fixture_path = File.join(File.dirname(__FILE__),
|
18
|
+
fixture_path = File.join(File.dirname(__FILE__), "../fixtures", "calendars")
|
15
19
|
described_class.load_paths = [fixture_path, { "foobar" => dummy_calendar }]
|
16
20
|
end
|
17
21
|
|
18
22
|
context "when given a calendar from a custom directory" do
|
19
|
-
|
23
|
+
let(:calendar) { "ecb" }
|
20
24
|
|
21
25
|
after { described_class.load_paths = nil }
|
22
26
|
|
23
27
|
it "loads the yaml file" do
|
24
|
-
expect(YAML).to receive(:load_file)
|
25
|
-
|
26
|
-
|
27
|
-
subject
|
28
|
+
expect(YAML).to receive(:load_file).with(/ecb\.yml$/).and_return({})
|
29
|
+
|
30
|
+
load_calendar
|
28
31
|
end
|
29
32
|
|
30
|
-
it { is_expected.to be_a
|
33
|
+
it { is_expected.to be_a described_class }
|
31
34
|
|
32
35
|
context "that also exists as a default calendar" do
|
33
|
-
|
36
|
+
let(:calendar) { "bacs" }
|
34
37
|
|
35
38
|
it "uses the custom calendar" do
|
36
|
-
expect(
|
39
|
+
expect(load_calendar.business_day?(Date.parse("25th December 2014"))).
|
37
40
|
to eq(true)
|
38
41
|
end
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
42
45
|
context "when loading a calendar as a hash" do
|
43
|
-
|
46
|
+
let(:calendar) { "foobar" }
|
44
47
|
|
45
|
-
it { is_expected.to be_a
|
48
|
+
it { is_expected.to be_a described_class }
|
46
49
|
end
|
47
50
|
|
48
51
|
context "when given a calendar that does not exist" do
|
49
|
-
|
50
|
-
|
52
|
+
let(:calendar) { "invalid-calendar" }
|
53
|
+
|
54
|
+
specify { expect { load_calendar }.to raise_error(/No such calendar/) }
|
51
55
|
end
|
52
56
|
|
53
57
|
context "when given a calendar that has invalid keys" do
|
54
|
-
|
55
|
-
|
58
|
+
let(:calendar) { "invalid-keys" }
|
59
|
+
|
60
|
+
specify do
|
61
|
+
expect { load_calendar }.
|
62
|
+
to raise_error(
|
63
|
+
"Only valid keys are: holidays, working_days, extra_working_dates",
|
64
|
+
)
|
65
|
+
end
|
56
66
|
end
|
57
67
|
|
58
68
|
context "when given real business data" do
|
59
|
-
let(:data_path)
|
69
|
+
let(:data_path) do
|
70
|
+
File.join(File.dirname(__FILE__), "..", "lib", "business", "data")
|
71
|
+
end
|
72
|
+
|
60
73
|
it "validates they are all loadable by the calendar" do
|
61
74
|
Dir.glob("#{data_path}/*").each do |filename|
|
62
75
|
calendar_name = File.basename(filename, ".yml")
|
63
|
-
calendar =
|
76
|
+
calendar = described_class.load(calendar_name)
|
64
77
|
|
65
78
|
expect(calendar.working_days.length).to be >= 1
|
66
79
|
end
|
@@ -69,33 +82,38 @@ describe Business::Calendar do
|
|
69
82
|
end
|
70
83
|
|
71
84
|
describe "#set_working_days" do
|
72
|
-
|
85
|
+
subject(:set_working_days) { calendar.set_working_days(working_days) }
|
86
|
+
|
87
|
+
let(:calendar) { described_class.new(name: "test") }
|
73
88
|
let(:working_days) { [] }
|
74
|
-
subject { calendar.set_working_days(working_days) }
|
75
89
|
|
76
90
|
context "when given valid working days" do
|
77
|
-
let(:working_days) { %w
|
78
|
-
|
91
|
+
let(:working_days) { %w[mon fri] }
|
92
|
+
|
93
|
+
before { set_working_days }
|
79
94
|
|
80
95
|
it "assigns them" do
|
81
96
|
expect(calendar.working_days).to eq(working_days)
|
82
97
|
end
|
83
98
|
|
84
99
|
context "that are unnormalised" do
|
85
|
-
let(:working_days) { %w
|
100
|
+
let(:working_days) { %w[Monday Friday] }
|
101
|
+
|
86
102
|
it "normalises them" do
|
87
|
-
expect(calendar.working_days).to eq(%w
|
103
|
+
expect(calendar.working_days).to eq(%w[mon fri])
|
88
104
|
end
|
89
105
|
end
|
90
106
|
end
|
91
107
|
|
92
108
|
context "when given an invalid business day" do
|
93
|
-
let(:working_days) { %w
|
94
|
-
|
109
|
+
let(:working_days) { %w[Notaday] }
|
110
|
+
|
111
|
+
specify { expect { set_working_days }.to raise_error(/Invalid day/) }
|
95
112
|
end
|
96
113
|
|
97
114
|
context "when given nil" do
|
98
115
|
let(:working_days) { nil }
|
116
|
+
|
99
117
|
it "uses the default business days" do
|
100
118
|
expect(calendar.working_days).to eq(calendar.default_working_days)
|
101
119
|
end
|
@@ -103,70 +121,78 @@ describe Business::Calendar do
|
|
103
121
|
end
|
104
122
|
|
105
123
|
describe "#set_holidays" do
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
124
|
+
subject(:holidays) { calendar.holidays }
|
125
|
+
|
126
|
+
let(:calendar) { described_class.new(name: "test") }
|
127
|
+
let(:holiday_dates) { [] }
|
128
|
+
|
129
|
+
before { calendar.set_holidays(holiday_dates) }
|
110
130
|
|
111
131
|
context "when given valid business days" do
|
112
|
-
let(:
|
132
|
+
let(:holiday_dates) { ["1st Jan, 2013"] }
|
113
133
|
|
114
|
-
it { is_expected.
|
134
|
+
it { is_expected.to_not be_empty }
|
115
135
|
|
116
136
|
it "converts them to Date objects" do
|
117
|
-
|
137
|
+
expect(holidays).to all be_a Date
|
118
138
|
end
|
119
139
|
end
|
120
140
|
|
121
141
|
context "when given nil" do
|
122
|
-
let(:
|
142
|
+
let(:holiday_dates) { nil }
|
143
|
+
|
123
144
|
it { is_expected.to be_empty }
|
124
145
|
end
|
125
146
|
end
|
126
147
|
|
127
148
|
describe "#set_extra_working_dates" do
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
149
|
+
subject(:extra_working_dates) { calendar.extra_working_dates }
|
150
|
+
|
151
|
+
let(:calendar) { described_class.new(name: "test") }
|
152
|
+
let(:extra_dates) { [] }
|
153
|
+
|
154
|
+
before { calendar.set_extra_working_dates(extra_dates) }
|
132
155
|
|
133
156
|
context "when given valid business days" do
|
134
|
-
let(:
|
157
|
+
let(:extra_dates) { ["1st Jan, 2013"] }
|
135
158
|
|
136
|
-
it { is_expected.
|
159
|
+
it { is_expected.to_not be_empty }
|
137
160
|
|
138
161
|
it "converts them to Date objects" do
|
139
|
-
|
162
|
+
expect(extra_working_dates).to all be_a Date
|
140
163
|
end
|
141
164
|
end
|
142
165
|
|
143
166
|
context "when given nil" do
|
144
167
|
let(:holidays) { nil }
|
168
|
+
|
145
169
|
it { is_expected.to be_empty }
|
146
170
|
end
|
147
171
|
end
|
148
172
|
|
149
173
|
context "when holiday is also a working date" do
|
150
|
-
|
151
|
-
|
152
|
-
|
174
|
+
let(:instance) do
|
175
|
+
described_class.new(name: "test",
|
176
|
+
holidays: ["2018-01-06"],
|
177
|
+
extra_working_dates: ["2018-01-06"])
|
153
178
|
end
|
154
179
|
|
155
180
|
it do
|
156
|
-
expect {
|
157
|
-
|
181
|
+
expect { instance }.to raise_error(ArgumentError).
|
182
|
+
with_message("Holidays cannot be extra working dates")
|
158
183
|
end
|
159
184
|
end
|
160
185
|
|
161
186
|
context "when working date on working day" do
|
162
|
-
|
163
|
-
|
164
|
-
|
187
|
+
let(:instance) do
|
188
|
+
described_class.new(name: "test",
|
189
|
+
working_days: ["mon"],
|
190
|
+
extra_working_dates: ["Monday 26th Mar, 2018"])
|
165
191
|
end
|
166
192
|
|
167
193
|
it do
|
168
|
-
expect {
|
169
|
-
|
194
|
+
expect { instance }.to raise_error(ArgumentError).
|
195
|
+
with_message("Extra working dates cannot be on working days")
|
170
196
|
end
|
171
197
|
end
|
172
198
|
|
@@ -175,262 +201,315 @@ describe Business::Calendar do
|
|
175
201
|
# tests for both Date *and* Time.
|
176
202
|
shared_examples "common" do
|
177
203
|
describe "#business_day?" do
|
204
|
+
subject { calendar.business_day?(day) }
|
205
|
+
|
178
206
|
let(:calendar) do
|
179
|
-
|
180
|
-
|
207
|
+
described_class.new(name: "test",
|
208
|
+
holidays: ["9am, Tuesday 1st Jan, 2013"],
|
209
|
+
extra_working_dates: ["9am, Sunday 6th Jan, 2013"])
|
181
210
|
end
|
182
|
-
subject { calendar.business_day?(day) }
|
183
211
|
|
184
212
|
context "when given a business day" do
|
185
213
|
let(:day) { date_class.parse("9am, Wednesday 2nd Jan, 2013") }
|
214
|
+
|
186
215
|
it { is_expected.to be_truthy }
|
187
216
|
end
|
188
217
|
|
189
218
|
context "when given a non-business day" do
|
190
219
|
let(:day) { date_class.parse("9am, Saturday 5th Jan, 2013") }
|
220
|
+
|
191
221
|
it { is_expected.to be_falsey }
|
192
222
|
end
|
193
223
|
|
194
224
|
context "when given a business day that is a holiday" do
|
195
225
|
let(:day) { date_class.parse("9am, Tuesday 1st Jan, 2013") }
|
226
|
+
|
196
227
|
it { is_expected.to be_falsey }
|
197
228
|
end
|
198
229
|
|
199
230
|
context "when given a non-business day that is a working date" do
|
200
231
|
let(:day) { date_class.parse("9am, Sunday 6th Jan, 2013") }
|
232
|
+
|
201
233
|
it { is_expected.to be_truthy }
|
202
234
|
end
|
203
235
|
end
|
204
236
|
|
205
237
|
describe "#working_day?" do
|
238
|
+
subject { calendar.working_day?(day) }
|
239
|
+
|
206
240
|
let(:calendar) do
|
207
|
-
|
208
|
-
|
241
|
+
described_class.new(name: "test",
|
242
|
+
holidays: ["9am, Tuesday 1st Jan, 2013"],
|
243
|
+
extra_working_dates: ["9am, Sunday 6th Jan, 2013"])
|
209
244
|
end
|
210
|
-
subject { calendar.working_day?(day) }
|
211
245
|
|
212
246
|
context "when given a working day" do
|
213
247
|
let(:day) { date_class.parse("9am, Wednesday 2nd Jan, 2013") }
|
248
|
+
|
214
249
|
it { is_expected.to be_truthy }
|
215
250
|
end
|
216
251
|
|
217
252
|
context "when given a non-working day" do
|
218
253
|
let(:day) { date_class.parse("9am, Saturday 5th Jan, 2013") }
|
254
|
+
|
219
255
|
it { is_expected.to be_falsey }
|
220
256
|
end
|
221
257
|
|
222
258
|
context "when given a working day that is a holiday" do
|
223
259
|
let(:day) { date_class.parse("9am, Tuesday 1st Jan, 2013") }
|
260
|
+
|
224
261
|
it { is_expected.to be_truthy }
|
225
262
|
end
|
226
263
|
|
227
264
|
context "when given a non-business day that is a working date" do
|
228
265
|
let(:day) { date_class.parse("9am, Sunday 6th Jan, 2013") }
|
266
|
+
|
229
267
|
it { is_expected.to be_truthy }
|
230
268
|
end
|
231
269
|
end
|
232
270
|
|
233
271
|
describe "#holiday?" do
|
272
|
+
subject { calendar.holiday?(day) }
|
273
|
+
|
234
274
|
let(:calendar) do
|
235
|
-
|
236
|
-
|
275
|
+
described_class.new(name: "test",
|
276
|
+
holidays: ["9am, Tuesday 1st Jan, 2013"],
|
277
|
+
extra_working_dates: ["9am, Sunday 6th Jan, 2013"])
|
237
278
|
end
|
238
|
-
subject { calendar.holiday?(day) }
|
239
279
|
|
240
280
|
context "when given a working day that is not a holiday" do
|
241
281
|
let(:day) { date_class.parse("9am, Wednesday 2nd Jan, 2013") }
|
282
|
+
|
242
283
|
it { is_expected.to be_falsey }
|
243
284
|
end
|
244
285
|
|
245
286
|
context "when given a non-working day that is not a holiday day" do
|
246
287
|
let(:day) { date_class.parse("9am, Saturday 5th Jan, 2013") }
|
288
|
+
|
247
289
|
it { is_expected.to be_falsey }
|
248
290
|
end
|
249
291
|
|
250
292
|
context "when given a day that is a holiday" do
|
251
293
|
let(:day) { date_class.parse("9am, Tuesday 1st Jan, 2013") }
|
294
|
+
|
252
295
|
it { is_expected.to be_truthy }
|
253
296
|
end
|
254
297
|
|
255
298
|
context "when given a non-business day that is no a holiday" do
|
256
299
|
let(:day) { date_class.parse("9am, Sunday 6th Jan, 2013") }
|
300
|
+
|
257
301
|
it { is_expected.to be_falsey }
|
258
302
|
end
|
259
303
|
end
|
260
304
|
|
261
305
|
describe "#roll_forward" do
|
306
|
+
subject { calendar.roll_forward(date) }
|
307
|
+
|
262
308
|
let(:calendar) do
|
263
|
-
|
309
|
+
described_class.new(name: "test", holidays: ["Tuesday 1st Jan, 2013"])
|
264
310
|
end
|
265
|
-
subject { calendar.roll_forward(date) }
|
266
311
|
|
267
312
|
context "given a business day" do
|
268
313
|
let(:date) { date_class.parse("Wednesday 2nd Jan, 2013") }
|
314
|
+
|
269
315
|
it { is_expected.to eq(date) }
|
270
316
|
end
|
271
317
|
|
272
318
|
context "given a non-business day" do
|
273
319
|
context "with a business day following it" do
|
274
320
|
let(:date) { date_class.parse("Tuesday 1st Jan, 2013") }
|
321
|
+
|
275
322
|
it { is_expected.to eq(date + day_interval) }
|
276
323
|
end
|
277
324
|
|
278
325
|
context "followed by another non-business day" do
|
279
326
|
let(:date) { date_class.parse("Saturday 5th Jan, 2013") }
|
327
|
+
|
280
328
|
it { is_expected.to eq(date + 2 * day_interval) }
|
281
329
|
end
|
282
330
|
end
|
283
331
|
end
|
284
332
|
|
285
333
|
describe "#roll_backward" do
|
334
|
+
subject { calendar.roll_backward(date) }
|
335
|
+
|
286
336
|
let(:calendar) do
|
287
|
-
|
337
|
+
described_class.new(name: "test", holidays: ["Tuesday 1st Jan, 2013"])
|
288
338
|
end
|
289
|
-
subject { calendar.roll_backward(date) }
|
290
339
|
|
291
340
|
context "given a business day" do
|
292
341
|
let(:date) { date_class.parse("Wednesday 2nd Jan, 2013") }
|
342
|
+
|
293
343
|
it { is_expected.to eq(date) }
|
294
344
|
end
|
295
345
|
|
296
346
|
context "given a non-business day" do
|
297
347
|
context "with a business day preceeding it" do
|
298
348
|
let(:date) { date_class.parse("Tuesday 1st Jan, 2013") }
|
349
|
+
|
299
350
|
it { is_expected.to eq(date - day_interval) }
|
300
351
|
end
|
301
352
|
|
302
353
|
context "preceeded by another non-business day" do
|
303
354
|
let(:date) { date_class.parse("Sunday 6th Jan, 2013") }
|
355
|
+
|
304
356
|
it { is_expected.to eq(date - 2 * day_interval) }
|
305
357
|
end
|
306
358
|
end
|
307
359
|
end
|
308
360
|
|
309
361
|
describe "#next_business_day" do
|
362
|
+
subject { calendar.next_business_day(date) }
|
363
|
+
|
310
364
|
let(:calendar) do
|
311
|
-
|
365
|
+
described_class.new(name: "test", holidays: ["Tuesday 1st Jan, 2013"])
|
312
366
|
end
|
313
|
-
subject { calendar.next_business_day(date) }
|
314
367
|
|
315
368
|
context "given a business day" do
|
316
369
|
let(:date) { date_class.parse("Wednesday 2nd Jan, 2013") }
|
370
|
+
|
317
371
|
it { is_expected.to eq(date + day_interval) }
|
318
372
|
end
|
319
373
|
|
320
374
|
context "given a non-business day" do
|
321
375
|
context "with a business day following it" do
|
322
376
|
let(:date) { date_class.parse("Tuesday 1st Jan, 2013") }
|
377
|
+
|
323
378
|
it { is_expected.to eq(date + day_interval) }
|
324
379
|
end
|
325
380
|
|
326
381
|
context "followed by another non-business day" do
|
327
382
|
let(:date) { date_class.parse("Saturday 5th Jan, 2013") }
|
383
|
+
|
328
384
|
it { is_expected.to eq(date + 2 * day_interval) }
|
329
385
|
end
|
330
386
|
end
|
331
387
|
end
|
332
388
|
|
333
389
|
describe "#previous_business_day" do
|
390
|
+
subject { calendar.previous_business_day(date) }
|
391
|
+
|
334
392
|
let(:calendar) do
|
335
|
-
|
393
|
+
described_class.new(name: "test", holidays: ["Tuesday 1st Jan, 2013"])
|
336
394
|
end
|
337
|
-
subject { calendar.previous_business_day(date) }
|
338
395
|
|
339
396
|
context "given a business day" do
|
340
397
|
let(:date) { date_class.parse("Thursday 3nd Jan, 2013") }
|
398
|
+
|
341
399
|
it { is_expected.to eq(date - day_interval) }
|
342
400
|
end
|
343
401
|
|
344
402
|
context "given a non-business day" do
|
345
403
|
context "with a business day before it" do
|
346
404
|
let(:date) { date_class.parse("Tuesday 1st Jan, 2013") }
|
405
|
+
|
347
406
|
it { is_expected.to eq(date - day_interval) }
|
348
407
|
end
|
349
408
|
|
350
409
|
context "preceeded by another non-business day" do
|
351
410
|
let(:date) { date_class.parse("Sunday 6th Jan, 2013") }
|
411
|
+
|
352
412
|
it { is_expected.to eq(date - 2 * day_interval) }
|
353
413
|
end
|
354
414
|
end
|
355
415
|
end
|
356
416
|
|
357
417
|
describe "#add_business_days" do
|
418
|
+
subject { calendar.add_business_days(date, delta) }
|
419
|
+
|
358
420
|
let(:extra_working_dates) { [] }
|
359
421
|
let(:calendar) do
|
360
|
-
|
361
|
-
|
422
|
+
described_class.new(name: "test",
|
423
|
+
holidays: ["Tuesday 1st Jan, 2013"],
|
424
|
+
extra_working_dates: extra_working_dates)
|
362
425
|
end
|
363
426
|
let(:delta) { 2 }
|
364
|
-
subject { calendar.add_business_days(date, delta) }
|
365
427
|
|
366
428
|
context "given a business day" do
|
367
429
|
context "and a period that includes only business days" do
|
368
430
|
let(:date) { date_class.parse("Wednesday 2nd Jan, 2013") }
|
431
|
+
|
369
432
|
it { is_expected.to eq(date + delta * day_interval) }
|
370
433
|
end
|
371
434
|
|
372
435
|
context "and a period that includes a weekend" do
|
373
436
|
let(:date) { date_class.parse("Friday 4th Jan, 2013") }
|
437
|
+
|
374
438
|
it { is_expected.to eq(date + (delta + 2) * day_interval) }
|
375
439
|
end
|
376
440
|
|
377
441
|
context "and a period that includes a working date weekend" do
|
378
442
|
let(:extra_working_dates) { ["Sunday 6th Jan, 2013"] }
|
379
443
|
let(:date) { date_class.parse("Friday 4th Jan, 2013") }
|
444
|
+
|
380
445
|
it { is_expected.to eq(date + (delta + 1) * day_interval) }
|
381
446
|
end
|
382
447
|
|
383
448
|
context "and a period that includes a holiday day" do
|
384
449
|
let(:date) { date_class.parse("Monday 31st Dec, 2012") }
|
450
|
+
|
385
451
|
it { is_expected.to eq(date + (delta + 1) * day_interval) }
|
386
452
|
end
|
387
453
|
end
|
388
454
|
|
389
455
|
context "given a non-business day" do
|
390
456
|
let(:date) { date_class.parse("Tuesday 1st Jan, 2013") }
|
457
|
+
|
391
458
|
it { is_expected.to eq(date + (delta + 1) * day_interval) }
|
392
459
|
end
|
393
460
|
end
|
394
461
|
|
395
462
|
describe "#subtract_business_days" do
|
463
|
+
subject { calendar.subtract_business_days(date, delta) }
|
464
|
+
|
396
465
|
let(:extra_working_dates) { [] }
|
397
466
|
let(:calendar) do
|
398
|
-
|
399
|
-
|
467
|
+
described_class.new(name: "test",
|
468
|
+
holidays: ["Thursday 3rd Jan, 2013"],
|
469
|
+
extra_working_dates: extra_working_dates)
|
400
470
|
end
|
401
471
|
let(:delta) { 2 }
|
402
|
-
subject { calendar.subtract_business_days(date, delta) }
|
403
472
|
|
404
473
|
context "given a business day" do
|
405
474
|
context "and a period that includes only business days" do
|
406
475
|
let(:date) { date_class.parse("Wednesday 2nd Jan, 2013") }
|
476
|
+
|
407
477
|
it { is_expected.to eq(date - delta * day_interval) }
|
408
478
|
end
|
409
479
|
|
410
480
|
context "and a period that includes a weekend" do
|
411
481
|
let(:date) { date_class.parse("Monday 31st Dec, 2012") }
|
482
|
+
|
412
483
|
it { is_expected.to eq(date - (delta + 2) * day_interval) }
|
413
484
|
end
|
414
485
|
|
415
486
|
context "and a period that includes a working date weekend" do
|
416
487
|
let(:extra_working_dates) { ["Saturday 29th Dec, 2012"] }
|
417
488
|
let(:date) { date_class.parse("Monday 31st Dec, 2012") }
|
489
|
+
|
418
490
|
it { is_expected.to eq(date - (delta + 1) * day_interval) }
|
419
491
|
end
|
420
492
|
|
421
493
|
context "and a period that includes a holiday day" do
|
422
494
|
let(:date) { date_class.parse("Friday 4th Jan, 2013") }
|
495
|
+
|
423
496
|
it { is_expected.to eq(date - (delta + 1) * day_interval) }
|
424
497
|
end
|
425
498
|
end
|
426
499
|
|
427
500
|
context "given a non-business day" do
|
428
501
|
let(:date) { date_class.parse("Thursday 3rd Jan, 2013") }
|
502
|
+
|
429
503
|
it { is_expected.to eq(date - (delta + 1) * day_interval) }
|
430
504
|
end
|
431
505
|
end
|
432
506
|
|
433
507
|
describe "#business_days_between" do
|
508
|
+
subject do
|
509
|
+
calendar.business_days_between(date_class.parse(date_1),
|
510
|
+
date_class.parse(date_2))
|
511
|
+
end
|
512
|
+
|
434
513
|
let(:holidays) do
|
435
514
|
["Wed 27/5/2014", "Thu 12/6/2014", "Wed 18/6/2014", "Fri 20/6/2014",
|
436
515
|
"Sun 22/6/2014", "Fri 27/6/2014", "Thu 3/7/2014"]
|
@@ -439,11 +518,9 @@ describe Business::Calendar do
|
|
439
518
|
["Sun 1/6/2014", "Sat 28/6/2014", "Sat 5/7/2014"]
|
440
519
|
end
|
441
520
|
let(:calendar) do
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
calendar.business_days_between(date_class.parse(date_1),
|
446
|
-
date_class.parse(date_2))
|
521
|
+
described_class.new(name: "test",
|
522
|
+
holidays: holidays,
|
523
|
+
extra_working_dates: extra_working_dates)
|
447
524
|
end
|
448
525
|
|
449
526
|
context "starting on a business day" do
|
@@ -452,58 +529,68 @@ describe Business::Calendar do
|
|
452
529
|
context "ending on a business day" do
|
453
530
|
context "including only business days" do
|
454
531
|
let(:date_2) { "Thu 5/6/2014" }
|
532
|
+
|
455
533
|
it { is_expected.to eq(3) }
|
456
534
|
end
|
457
535
|
|
458
536
|
context "including only business days & weekend days" do
|
459
537
|
let(:date_2) { "Mon 9/6/2014" }
|
538
|
+
|
460
539
|
it { is_expected.to eq(5) }
|
461
540
|
end
|
462
541
|
|
463
542
|
context "including only business days, weekend days & working date" do
|
464
543
|
let(:date_1) { "Thu 29/5/2014" }
|
465
544
|
let(:date_2) { "The 3/6/2014" }
|
466
|
-
|
545
|
+
|
546
|
+
it { is_expected.to be(4) }
|
467
547
|
end
|
468
548
|
|
469
549
|
context "including only business days & holidays" do
|
470
550
|
let(:date_1) { "Mon 9/6/2014" }
|
471
551
|
let(:date_2) { "Fri 13/6/2014" }
|
552
|
+
|
472
553
|
it { is_expected.to eq(3) }
|
473
554
|
end
|
474
555
|
|
475
556
|
context "including business, weekend days, and holidays" do
|
476
557
|
let(:date_2) { "Fri 13/6/2014" }
|
558
|
+
|
477
559
|
it { is_expected.to eq(8) }
|
478
560
|
end
|
479
561
|
|
480
562
|
context "including business, weekend, hoilday days & working date" do
|
481
563
|
let(:date_1) { "Thu 26/6/2014" }
|
482
564
|
let(:date_2) { "The 1/7/2014" }
|
483
|
-
|
565
|
+
|
566
|
+
it { is_expected.to be(3) }
|
484
567
|
end
|
485
568
|
end
|
486
569
|
|
487
570
|
context "ending on a weekend day" do
|
488
571
|
context "including only business days & weekend days" do
|
489
572
|
let(:date_2) { "Sun 8/6/2014" }
|
573
|
+
|
490
574
|
it { is_expected.to eq(5) }
|
491
575
|
end
|
492
576
|
|
493
577
|
context "including business & weekend days & working date" do
|
494
578
|
let(:date_1) { "Thu 29/5/2014" }
|
495
579
|
let(:date_2) { "Sun 3/6/2014" }
|
580
|
+
|
496
581
|
it { is_expected.to eq(4) }
|
497
582
|
end
|
498
583
|
|
499
584
|
context "including business, weekend days, and holidays" do
|
500
585
|
let(:date_2) { "Sat 14/6/2014" }
|
586
|
+
|
501
587
|
it { is_expected.to eq(9) }
|
502
588
|
end
|
503
589
|
|
504
590
|
context "including business, weekend & holiday days & working date" do
|
505
591
|
let(:date_1) { "Thu 26/6/2014" }
|
506
592
|
let(:date_2) { "Tue 2/7/2014" }
|
593
|
+
|
507
594
|
it { is_expected.to eq(4) }
|
508
595
|
end
|
509
596
|
end
|
@@ -512,17 +599,20 @@ describe Business::Calendar do
|
|
512
599
|
context "including only business days & holidays" do
|
513
600
|
let(:date_1) { "Mon 9/6/2014" }
|
514
601
|
let(:date_2) { "Thu 12/6/2014" }
|
602
|
+
|
515
603
|
it { is_expected.to eq(3) }
|
516
604
|
end
|
517
605
|
|
518
606
|
context "including business, weekend days, and holidays" do
|
519
607
|
let(:date_2) { "Thu 12/6/2014" }
|
608
|
+
|
520
609
|
it { is_expected.to eq(8) }
|
521
610
|
end
|
522
611
|
|
523
|
-
context
|
612
|
+
context "including business, weekend, holiday days & business date" do
|
524
613
|
let(:date_1) { "Wed 28/5/2014" }
|
525
614
|
let(:date_2) { "Thu 12/6/2014" }
|
615
|
+
|
526
616
|
it { is_expected.to eq(11) }
|
527
617
|
end
|
528
618
|
end
|
@@ -532,17 +622,20 @@ describe Business::Calendar do
|
|
532
622
|
|
533
623
|
context "including only business days & working date" do
|
534
624
|
let(:date_2) { "Sat 5/7/2014" }
|
625
|
+
|
535
626
|
it { is_expected.to eq(1) }
|
536
627
|
end
|
537
628
|
|
538
629
|
context "including business, weekend days & working date" do
|
539
630
|
let(:date_2) { "Tue 8/7/2014" }
|
631
|
+
|
540
632
|
it { is_expected.to eq(3) }
|
541
633
|
end
|
542
634
|
|
543
635
|
context "including business, weekend days, holidays & working date" do
|
544
636
|
let(:date_1) { "Wed 25/6/2014" }
|
545
637
|
let(:date_2) { "Tue 8/7/2014" }
|
638
|
+
|
546
639
|
it { is_expected.to eq(8) }
|
547
640
|
end
|
548
641
|
end
|
@@ -552,26 +645,29 @@ describe Business::Calendar do
|
|
552
645
|
let(:date_1) { "Sat 7/6/2014" }
|
553
646
|
|
554
647
|
context "ending on a business day" do
|
555
|
-
|
556
648
|
context "including only business days & weekend days" do
|
557
649
|
let(:date_2) { "Mon 9/6/2014" }
|
650
|
+
|
558
651
|
it { is_expected.to eq(0) }
|
559
652
|
end
|
560
653
|
|
561
654
|
context "including business, weekend days & working date" do
|
562
655
|
let(:date_1) { "Sat 31/5/2014" }
|
563
656
|
let(:date_2) { "Tue 3/6/2014" }
|
657
|
+
|
564
658
|
it { is_expected.to eq(2) }
|
565
659
|
end
|
566
660
|
|
567
661
|
context "including business, weekend days, and holidays" do
|
568
662
|
let(:date_2) { "Fri 13/6/2014" }
|
663
|
+
|
569
664
|
it { is_expected.to eq(3) }
|
570
665
|
end
|
571
666
|
|
572
667
|
context "including business, weekend, holilday days & working date" do
|
573
668
|
let(:date_1) { "Sat 31/5/2014" }
|
574
669
|
let(:date_2) { "Fri 13/6/2014" }
|
670
|
+
|
575
671
|
it { is_expected.to eq(8) }
|
576
672
|
end
|
577
673
|
end
|
@@ -579,36 +675,42 @@ describe Business::Calendar do
|
|
579
675
|
context "ending on a weekend day" do
|
580
676
|
context "including only business days & weekend days" do
|
581
677
|
let(:date_2) { "Sun 8/6/2014" }
|
678
|
+
|
582
679
|
it { is_expected.to eq(0) }
|
583
680
|
end
|
584
681
|
|
585
682
|
context "including business, weekend days & working date" do
|
586
683
|
let(:date_1) { "Sat 31/5/2014" }
|
587
684
|
let(:date_2) { "Sun 8/6/2014" }
|
588
|
-
|
685
|
+
|
686
|
+
it { is_expected.to be(5) }
|
589
687
|
end
|
590
688
|
|
591
689
|
context "including business, weekend days, and holidays" do
|
592
690
|
let(:date_2) { "Sat 14/6/2014" }
|
691
|
+
|
593
692
|
it { is_expected.to eq(4) }
|
594
693
|
end
|
595
694
|
|
596
695
|
context "including business, weekend, holiday days & working date" do
|
597
696
|
let(:date_1) { "Sat 31/5/2014" }
|
598
697
|
let(:date_2) { "Sun 14/6/2014" }
|
599
|
-
|
698
|
+
|
699
|
+
it { is_expected.to be(9) }
|
600
700
|
end
|
601
701
|
end
|
602
702
|
|
603
703
|
context "ending on a holiday" do
|
604
704
|
context "including business, weekend days, and holidays" do
|
605
705
|
let(:date_2) { "Thu 12/6/2014" }
|
706
|
+
|
606
707
|
it { is_expected.to eq(3) }
|
607
708
|
end
|
608
709
|
|
609
710
|
context "including business, weekend days & working date" do
|
610
711
|
let(:date_1) { "Sat 31/5/2014" }
|
611
712
|
let(:date_2) { "Thu 12/6/2014" }
|
713
|
+
|
612
714
|
it { is_expected.to eq(8) }
|
613
715
|
end
|
614
716
|
end
|
@@ -618,16 +720,19 @@ describe Business::Calendar do
|
|
618
720
|
|
619
721
|
context "including only weekend days & working date" do
|
620
722
|
let(:date_2) { "Sat 2/6/2014" }
|
723
|
+
|
621
724
|
it { is_expected.to eq(1) }
|
622
725
|
end
|
623
726
|
|
624
727
|
context "including business, weekend days & working date" do
|
625
728
|
let(:date_2) { "Tue 4/6/2014" }
|
729
|
+
|
626
730
|
it { is_expected.to eq(3) }
|
627
731
|
end
|
628
732
|
|
629
733
|
context "including business, weekend days, holidays & working date" do
|
630
734
|
let(:date_2) { "Tue 13/6/2014" }
|
735
|
+
|
631
736
|
it { is_expected.to eq(8) }
|
632
737
|
end
|
633
738
|
end
|
@@ -637,20 +742,22 @@ describe Business::Calendar do
|
|
637
742
|
let(:date_1) { "Thu 12/6/2014" }
|
638
743
|
|
639
744
|
context "ending on a business day" do
|
640
|
-
|
641
745
|
context "including only business days & holidays" do
|
642
746
|
let(:date_2) { "Fri 13/6/2014" }
|
747
|
+
|
643
748
|
it { is_expected.to eq(0) }
|
644
749
|
end
|
645
750
|
|
646
751
|
context "including business, weekend days, and holidays" do
|
647
752
|
let(:date_2) { "Thu 19/6/2014" }
|
753
|
+
|
648
754
|
it { is_expected.to eq(3) }
|
649
755
|
end
|
650
756
|
|
651
757
|
context "including business, weekend days, holidays & working date" do
|
652
758
|
let(:date_1) { "Fri 27/6/2014" }
|
653
759
|
let(:date_2) { "Tue 1/7/2014" }
|
760
|
+
|
654
761
|
it { is_expected.to eq(2) }
|
655
762
|
end
|
656
763
|
end
|
@@ -658,12 +765,14 @@ describe Business::Calendar do
|
|
658
765
|
context "ending on a weekend day" do
|
659
766
|
context "including business, weekend days, and holidays" do
|
660
767
|
let(:date_2) { "Sun 15/6/2014" }
|
768
|
+
|
661
769
|
it { is_expected.to eq(1) }
|
662
770
|
end
|
663
771
|
|
664
772
|
context "including business, weekend days, holidays & working date" do
|
665
773
|
let(:date_1) { "Fri 27/6/2014" }
|
666
774
|
let(:date_2) { "Sun 29/6/2014" }
|
775
|
+
|
667
776
|
it { is_expected.to eq(1) }
|
668
777
|
end
|
669
778
|
end
|
@@ -672,17 +781,20 @@ describe Business::Calendar do
|
|
672
781
|
context "including only business days & holidays" do
|
673
782
|
let(:date_1) { "Wed 18/6/2014" }
|
674
783
|
let(:date_2) { "Fri 20/6/2014" }
|
784
|
+
|
675
785
|
it { is_expected.to eq(1) }
|
676
786
|
end
|
677
787
|
|
678
788
|
context "including business, weekend days, and holidays" do
|
679
789
|
let(:date_2) { "Wed 18/6/2014" }
|
790
|
+
|
680
791
|
it { is_expected.to eq(3) }
|
681
792
|
end
|
682
793
|
|
683
794
|
context "including business/weekend days, holidays & working date" do
|
684
795
|
let(:date_1) { "27/5/2014" }
|
685
796
|
let(:date_2) { "Thu 12/6/2014" }
|
797
|
+
|
686
798
|
it { is_expected.to eq(11) }
|
687
799
|
end
|
688
800
|
end
|
@@ -692,37 +804,43 @@ describe Business::Calendar do
|
|
692
804
|
|
693
805
|
context "including only holiday & working date" do
|
694
806
|
let(:date_2) { "Sat 29/6/2014" }
|
807
|
+
|
695
808
|
it { is_expected.to eq(1) }
|
696
809
|
end
|
697
810
|
|
698
811
|
context "including holiday, weekend days & working date" do
|
699
812
|
let(:date_2) { "Tue 30/6/2014" }
|
813
|
+
|
700
814
|
it { is_expected.to eq(1) }
|
701
815
|
end
|
702
816
|
|
703
817
|
context "including business, weekend days, holidays & working date" do
|
704
818
|
let(:date_2) { "Tue 2/7/2014" }
|
819
|
+
|
705
820
|
it { is_expected.to eq(3) }
|
706
821
|
end
|
707
822
|
end
|
708
823
|
end
|
709
824
|
|
710
|
-
context
|
825
|
+
context "starting on a working date" do
|
711
826
|
let(:date_1) { "Sun 1/6/2014" }
|
712
827
|
|
713
828
|
context "ending on a working day" do
|
714
829
|
context "including only working date & working day" do
|
715
830
|
let(:date_2) { "Wed 4/6/2014" }
|
831
|
+
|
716
832
|
it { is_expected.to eq(3) }
|
717
833
|
end
|
718
834
|
|
719
835
|
context "including working date, working & weekend days" do
|
720
836
|
let(:date_2) { "Tue 10/6/2014" }
|
837
|
+
|
721
838
|
it { is_expected.to eq(6) }
|
722
839
|
end
|
723
840
|
|
724
841
|
context "including working date, working & weekend days & holiday" do
|
725
842
|
let(:date_2) { "Tue 13/6/2014" }
|
843
|
+
|
726
844
|
it { is_expected.to eq(8) }
|
727
845
|
end
|
728
846
|
end
|
@@ -732,17 +850,20 @@ describe Business::Calendar do
|
|
732
850
|
|
733
851
|
context "including only working date & weekend day" do
|
734
852
|
let(:date_2) { "Sun 29/6/2014" }
|
853
|
+
|
735
854
|
it { is_expected.to eq(1) }
|
736
855
|
end
|
737
856
|
|
738
857
|
context "including working date, weekend & working days" do
|
739
858
|
let(:date_1) { "Sat 5/7/2014" }
|
740
859
|
let(:date_2) { "Wed 9/7/2014" }
|
860
|
+
|
741
861
|
it { is_expected.to eq(3) }
|
742
862
|
end
|
743
863
|
|
744
864
|
context "including working date, weekend & working days & holiday" do
|
745
865
|
let(:date_2) { "Fri 4/7/2014" }
|
866
|
+
|
746
867
|
it { is_expected.to eq(4) }
|
747
868
|
end
|
748
869
|
end
|
@@ -754,17 +875,20 @@ describe Business::Calendar do
|
|
754
875
|
let(:holidays) { ["Mon 2/6/2014"] }
|
755
876
|
let(:date_1) { "Sun 1/6/2014" }
|
756
877
|
let(:date_2) { "Mon 2/6/2014" }
|
878
|
+
|
757
879
|
it { is_expected.to eq(1) }
|
758
880
|
end
|
759
881
|
|
760
882
|
context "including working date, holiday & weekend day" do
|
761
883
|
let(:holidays) { ["Mon 30/6/2014"] }
|
762
884
|
let(:date_2) { "Mon 30/6/2014" }
|
885
|
+
|
763
886
|
it { is_expected.to eq(1) }
|
764
887
|
end
|
765
888
|
|
766
889
|
context "including working date, holiday, weekend & working days" do
|
767
890
|
let(:date_2) { "Thu 3/7/2014" }
|
891
|
+
|
768
892
|
it { is_expected.to eq(4) }
|
769
893
|
end
|
770
894
|
end
|
@@ -773,6 +897,7 @@ describe Business::Calendar do
|
|
773
897
|
context "including working dates, weekend & working days" do
|
774
898
|
let(:date_1) { "Sat 28/6/2014" }
|
775
899
|
let(:date_2) { "Sat 5/7/2014" }
|
900
|
+
|
776
901
|
it { is_expected.to eq(4) }
|
777
902
|
end
|
778
903
|
end
|
@@ -782,11 +907,14 @@ describe Business::Calendar do
|
|
782
907
|
context "for a range less than a week long" do
|
783
908
|
let(:date_1) { "Thu 19/6/2014" }
|
784
909
|
let(:date_2) { "Tue 24/6/2014" }
|
910
|
+
|
785
911
|
it { is_expected.to eq(2) }
|
786
912
|
end
|
913
|
+
|
787
914
|
context "for a range more than a week long" do
|
788
915
|
let(:date_1) { "Mon 16/6/2014" }
|
789
916
|
let(:date_2) { "Tue 24/6/2014" }
|
917
|
+
|
790
918
|
it { is_expected.to eq(4) }
|
791
919
|
end
|
792
920
|
end
|