business 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|