business 2.3.0 → 3.0.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/.github/workflows/tests.yml +36 -0
- data/.rubocop.yml +5 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +5 -0
- data/COMPATIBILITY.md +21 -0
- data/Gemfile +6 -0
- data/README.md +8 -23
- data/business.gemspec +2 -7
- data/lib/business/calendar.rb +22 -12
- data/lib/business/version.rb +1 -1
- data/spec/business/calendar_spec.rb +80 -14
- metadata +10 -71
- data/.circleci/config.yml +0 -37
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c7aab6453e38130641098c102e0b05f1d5c40cd957710c80f3b53f4670175ce6
|
|
4
|
+
data.tar.gz: 2ae585a9a460e340db0821c755a787795e7504914af8febb247c451beb8f37f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ffe309242e862845535efb526d3f4ec95852bd685f026c97fdac4bcd4eec88051e47481f5d1354b98a9f34af47dd4858b417fe173b6f9498b52c226a6c491bac
|
|
7
|
+
data.tar.gz: 322e9a49e3fcec9078b6c5e1d78eb6ea0d4abc0bc47f95550cbb6069d72715c00d8c5868279bfdfc5e69776e7e85cea03fc3994441522ff7a84abb82411e867f
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- "master"
|
|
7
|
+
pull_request:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
rubocop:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v7
|
|
14
|
+
- name: Set up Ruby
|
|
15
|
+
uses: ruby/setup-ruby@v1
|
|
16
|
+
with:
|
|
17
|
+
bundler-cache: true
|
|
18
|
+
# Maintain consistency with the TargetRubyVersion in .rubocop.yml
|
|
19
|
+
ruby-version: "3.3"
|
|
20
|
+
- name: Run rubocop
|
|
21
|
+
run: bundle exec rubocop --parallel --extra-details --display-style-guide
|
|
22
|
+
|
|
23
|
+
tests:
|
|
24
|
+
strategy:
|
|
25
|
+
matrix:
|
|
26
|
+
ruby-version: ["3.3", "3.4", "4.0"]
|
|
27
|
+
runs-on: ubuntu-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v7
|
|
30
|
+
- name: Set up Ruby
|
|
31
|
+
uses: ruby/setup-ruby@v1
|
|
32
|
+
with:
|
|
33
|
+
bundler-cache: true
|
|
34
|
+
ruby-version: "${{ matrix.ruby-version }}"
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: bundle exec rspec
|
data/.rubocop.yml
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
inherit_gem:
|
|
2
2
|
gc_ruboconfig: rubocop.yml
|
|
3
3
|
|
|
4
|
+
AllCops:
|
|
5
|
+
TargetRubyVersion: 3.3
|
|
6
|
+
NewCops: enable
|
|
7
|
+
|
|
4
8
|
RSpec/NestedGroups:
|
|
5
9
|
Exclude:
|
|
6
10
|
- spec/business/calendar_spec.rb
|
|
@@ -12,5 +16,5 @@ Naming/AccessorMethodName:
|
|
|
12
16
|
Gemspec/RequiredRubyVersion:
|
|
13
17
|
Enabled: false
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
RSpec/IndexedLet:
|
|
16
20
|
Enabled: false
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4.0.6
|
data/CHANGELOG.md
CHANGED
data/COMPATIBILITY.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Compatibility
|
|
2
|
+
|
|
3
|
+
## v2.0.0 breaking changes
|
|
4
|
+
|
|
5
|
+
We have removed the bundled calendars as of version 2.0.0, if you need the calendars that were included:
|
|
6
|
+
|
|
7
|
+
- Download the calendars you wish to use from [v1.18.0](https://github.com/gocardless/business/tree/b12c186ca6fd4ffdac85175742ff7e4d0a705ef4/lib/business/data)
|
|
8
|
+
- Place them in a suitable directory in your project, typically `lib/calendars`
|
|
9
|
+
- 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
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
Business::Calendar.load_paths = ["lib/calendars"] # your_project/lib/calendars/ contains bacs.yml
|
|
13
|
+
Business::Calendar.load("bacs")
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
If you wish to stay on the last version that contained bundled calendars, pin `business` to `v1.18.0`
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
# Gemfile
|
|
20
|
+
gem "business", "v1.18.0"
|
|
21
|
+
```
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,39 +1,18 @@
|
|
|
1
1
|
# Business
|
|
2
2
|
|
|
3
3
|
[](http://badge.fury.io/rb/business)
|
|
4
|
-
[](https://circleci.com/gh/gocardless/business)
|
|
5
4
|
|
|
6
5
|
Date calculations based on business calendars.
|
|
7
6
|
|
|
8
|
-
- [v2.0.0 breaking changes](#v200-breaking-changes)
|
|
9
7
|
- [Getting Started](#getting-started)
|
|
10
8
|
- [Creating a calendar](#creating-a-calendar)
|
|
11
9
|
- [Using a calendar file](#use-a-calendar-file)
|
|
12
10
|
- [Checking for business days](#checking-for-business-days)
|
|
13
11
|
- [Business day arithmetic](#business-day-arithmetic)
|
|
14
12
|
- [But other libraries already do this](#but-other-libraries-already-do-this)
|
|
13
|
+
- [Compatibility](#compatibility)
|
|
15
14
|
- [License & Contributing](#license--contributing)
|
|
16
15
|
|
|
17
|
-
## v2.0.0 breaking changes
|
|
18
|
-
|
|
19
|
-
We have removed the bundled calendars as of version 2.0.0, if you need the calendars that were included:
|
|
20
|
-
|
|
21
|
-
- Download the calendars you wish to use from [v1.18.0](https://github.com/gocardless/business/tree/b12c186ca6fd4ffdac85175742ff7e4d0a705ef4/lib/business/data)
|
|
22
|
-
- Place them in a suitable directory in your project, typically `lib/calendars`
|
|
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
|
-
|
|
25
|
-
```ruby
|
|
26
|
-
Business::Calendar.load_paths = ["lib/calendars"] # your_project/lib/calendars/ contains bacs.yml
|
|
27
|
-
Business::Calendar.load("bacs")
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
If you wish to stay on the last version that contained bundled calendars, pin `business` to `v1.18.0`
|
|
31
|
-
|
|
32
|
-
```ruby
|
|
33
|
-
# Gemfile
|
|
34
|
-
gem "business", "v1.18.0"
|
|
35
|
-
```
|
|
36
|
-
|
|
37
16
|
## Getting started
|
|
38
17
|
|
|
39
18
|
To install business, simply:
|
|
@@ -45,7 +24,7 @@ gem install business
|
|
|
45
24
|
If you are using a Gemfile:
|
|
46
25
|
|
|
47
26
|
```ruby
|
|
48
|
-
gem "business", "~>
|
|
27
|
+
gem "business", "~> 3.0"
|
|
49
28
|
```
|
|
50
29
|
|
|
51
30
|
### Creating a calendar
|
|
@@ -189,6 +168,12 @@ Secondly, business_time supports calculations on times as well as dates. For our
|
|
|
189
168
|
|
|
190
169
|
<p align="center"><img src="http://3.bp.blogspot.com/-aq4iOz2OZzs/Ty8xaQwMhtI/AAAAAAAABrM/-vn4tcRA9-4/s1600/daily-morning-awesomeness-243.jpeg" alt="I'm late for business" width="250"/></p>
|
|
191
170
|
|
|
171
|
+
# Compatibility
|
|
172
|
+
|
|
173
|
+
## v2.0.0 Breaking Changes
|
|
174
|
+
|
|
175
|
+
- See [COMPATIBILITY.md](COMPATIBILITY.md#v200-breaking-changes)
|
|
176
|
+
|
|
192
177
|
## License & Contributing
|
|
193
178
|
- business is available as open source under the terms of the [MIT License](LICENSE).
|
|
194
179
|
- Bug reports and pull requests are welcome on GitHub at https://github.com/gocardless/business.
|
data/business.gemspec
CHANGED
|
@@ -8,7 +8,7 @@ require "business/version"
|
|
|
8
8
|
Gem::Specification.new do |spec|
|
|
9
9
|
spec.name = "business"
|
|
10
10
|
spec.version = Business::VERSION
|
|
11
|
-
spec.authors = ["
|
|
11
|
+
spec.authors = ["GoCcardless"]
|
|
12
12
|
spec.email = ["developers@gocardless.com"]
|
|
13
13
|
spec.summary = "Date calculations based on business calendars"
|
|
14
14
|
spec.description = "Date calculations based on business calendars"
|
|
@@ -16,12 +16,7 @@ Gem::Specification.new do |spec|
|
|
|
16
16
|
spec.licenses = ["MIT"]
|
|
17
17
|
|
|
18
18
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
|
19
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
20
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
21
19
|
spec.require_paths = ["lib"]
|
|
22
20
|
|
|
23
|
-
spec.
|
|
24
|
-
spec.add_development_dependency "rspec", "~> 3.1"
|
|
25
|
-
spec.add_development_dependency "rspec_junit_formatter", "~> 0.5.1"
|
|
26
|
-
spec.add_development_dependency "rubocop", "~> 1.25.0"
|
|
21
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
27
22
|
end
|
data/lib/business/calendar.rb
CHANGED
|
@@ -8,6 +8,11 @@ module Business
|
|
|
8
8
|
class Calendar
|
|
9
9
|
VALID_KEYS = %w[holidays working_days extra_working_dates].freeze
|
|
10
10
|
|
|
11
|
+
# Calendar names are interpolated into a filesystem path, so restrict them to
|
|
12
|
+
# plain identifiers: anything containing path separators, "..", or an absolute
|
|
13
|
+
# path would otherwise load a file from outside the configured load_paths.
|
|
14
|
+
CALENDAR_NAME_FORMAT = /\A[a-zA-Z0-9_-]+\z/
|
|
15
|
+
|
|
11
16
|
class << self
|
|
12
17
|
attr_accessor :load_paths
|
|
13
18
|
end
|
|
@@ -38,7 +43,7 @@ module Business
|
|
|
38
43
|
if path.is_a?(Hash)
|
|
39
44
|
break path[calendar_name] if path[calendar_name]
|
|
40
45
|
else
|
|
41
|
-
calendar_path =
|
|
46
|
+
calendar_path = calendar_path_for(path, calendar_name)
|
|
42
47
|
next unless calendar_path.exist?
|
|
43
48
|
|
|
44
49
|
break YAML.safe_load(calendar_path.read, permitted_classes: [Date])
|
|
@@ -46,6 +51,17 @@ module Business
|
|
|
46
51
|
end
|
|
47
52
|
end
|
|
48
53
|
|
|
54
|
+
# Only applied to directory load_paths; hash load_paths are a plain key
|
|
55
|
+
# lookup and cannot escape anywhere, so their keys stay unrestricted.
|
|
56
|
+
def self.calendar_path_for(directory, calendar_name)
|
|
57
|
+
unless calendar_name.to_s.match?(CALENDAR_NAME_FORMAT)
|
|
58
|
+
raise ArgumentError, "invalid calendar name: #{calendar_name.inspect}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
Pathname.new(directory).join("#{calendar_name}.yml")
|
|
62
|
+
end
|
|
63
|
+
private_class_method :calendar_path_for
|
|
64
|
+
|
|
49
65
|
@lock = Mutex.new
|
|
50
66
|
def self.load_cached(calendar)
|
|
51
67
|
@lock.synchronize do
|
|
@@ -65,7 +81,7 @@ module Business
|
|
|
65
81
|
set_working_days(working_days)
|
|
66
82
|
set_holidays(holidays)
|
|
67
83
|
|
|
68
|
-
|
|
84
|
+
if @holidays.intersect?(@extra_working_dates)
|
|
69
85
|
raise ArgumentError, "Holidays cannot be extra working dates"
|
|
70
86
|
end
|
|
71
87
|
end
|
|
@@ -129,10 +145,7 @@ module Business
|
|
|
129
145
|
def add_business_days(date, delta)
|
|
130
146
|
date = roll_forward(date)
|
|
131
147
|
delta.times do
|
|
132
|
-
|
|
133
|
-
date += day_interval_for(date)
|
|
134
|
-
break date if business_day?(date)
|
|
135
|
-
end
|
|
148
|
+
date = next_business_day(date)
|
|
136
149
|
end
|
|
137
150
|
date
|
|
138
151
|
end
|
|
@@ -145,10 +158,7 @@ module Business
|
|
|
145
158
|
def subtract_business_days(date, delta)
|
|
146
159
|
date = roll_backward(date)
|
|
147
160
|
delta.times do
|
|
148
|
-
|
|
149
|
-
date -= day_interval_for(date)
|
|
150
|
-
break date if business_day?(date)
|
|
151
|
-
end
|
|
161
|
+
date = previous_business_day(date)
|
|
152
162
|
end
|
|
153
163
|
date
|
|
154
164
|
end
|
|
@@ -184,7 +194,7 @@ module Business
|
|
|
184
194
|
in_range && on_biz_day
|
|
185
195
|
end
|
|
186
196
|
|
|
187
|
-
remaining_range = (date2 - remaining_days...date2)
|
|
197
|
+
remaining_range = ((date2 - remaining_days)...date2)
|
|
188
198
|
# Loop through each day in remaining_range and count if a business day
|
|
189
199
|
num_biz_days + remaining_range.count { |a| business_day?(a) }
|
|
190
200
|
end
|
|
@@ -203,7 +213,7 @@ module Business
|
|
|
203
213
|
extra_working_dates_names = @extra_working_dates.map do |d|
|
|
204
214
|
d.strftime("%a").downcase
|
|
205
215
|
end
|
|
206
|
-
return if (
|
|
216
|
+
return if !extra_working_dates_names.intersect?(@working_days)
|
|
207
217
|
|
|
208
218
|
raise ArgumentError, "Extra working dates cannot be on working days"
|
|
209
219
|
end
|
data/lib/business/version.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "business/calendar"
|
|
4
4
|
require "time"
|
|
5
|
+
require "fileutils"
|
|
5
6
|
|
|
6
7
|
RSpec.configure do |config|
|
|
7
8
|
config.mock_with(:rspec) { |mocks| mocks.verify_partial_doubles = true }
|
|
@@ -57,6 +58,71 @@ RSpec.describe Business::Calendar do
|
|
|
57
58
|
specify { expect { load_calendar }.to raise_error(/No such calendar/) }
|
|
58
59
|
end
|
|
59
60
|
|
|
61
|
+
context "when given a calendar name that escapes the load path" do
|
|
62
|
+
before do
|
|
63
|
+
outside = File.join(File.dirname(__FILE__), "../fixtures")
|
|
64
|
+
FileUtils.mkdir_p(File.join(outside, "outside"))
|
|
65
|
+
File.write(
|
|
66
|
+
File.join(outside, "outside", "escaped.yml"),
|
|
67
|
+
{ "working_days" => ["monday"] }.to_yaml,
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
after do
|
|
72
|
+
FileUtils.rm_rf(File.join(File.dirname(__FILE__), "../fixtures", "outside"))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context "with a relative traversal" do
|
|
76
|
+
let(:calendar) { "../outside/escaped" }
|
|
77
|
+
|
|
78
|
+
specify do
|
|
79
|
+
expect { load_calendar }.
|
|
80
|
+
to raise_error(ArgumentError, /invalid calendar name/)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context "with an absolute path" do
|
|
85
|
+
let(:calendar) do
|
|
86
|
+
File.join(File.dirname(__FILE__), "../fixtures", "outside", "escaped")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
specify do
|
|
90
|
+
expect { load_calendar }.
|
|
91
|
+
to raise_error(ArgumentError, /invalid calendar name/)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context "with a bare path separator" do
|
|
96
|
+
let(:calendar) { "outside/escaped" }
|
|
97
|
+
|
|
98
|
+
specify do
|
|
99
|
+
expect { load_calendar }.
|
|
100
|
+
to raise_error(ArgumentError, /invalid calendar name/)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
context "with a name that is only dots" do
|
|
105
|
+
let(:calendar) { ".." }
|
|
106
|
+
|
|
107
|
+
specify do
|
|
108
|
+
expect { load_calendar }.
|
|
109
|
+
to raise_error(ArgumentError, /invalid calendar name/)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context "when the escaping name is a key in a hash load path" do
|
|
114
|
+
before do
|
|
115
|
+
described_class.load_paths = [{ "../outside/escaped" => dummy_calendar }]
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
let(:calendar) { "../outside/escaped" }
|
|
119
|
+
|
|
120
|
+
it "still resolves, since hash lookups touch no filesystem" do
|
|
121
|
+
expect(load_calendar).to be_a described_class
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
60
126
|
context "when given a calendar that has invalid keys" do
|
|
61
127
|
let(:calendar) { "invalid-keys" }
|
|
62
128
|
|
|
@@ -340,7 +406,7 @@ RSpec.describe Business::Calendar do
|
|
|
340
406
|
context "followed by another non-business day" do
|
|
341
407
|
let(:date) { date_class.parse("Saturday 5th Jan, 2013") }
|
|
342
408
|
|
|
343
|
-
it { is_expected.to eq(date + 2 * day_interval) }
|
|
409
|
+
it { is_expected.to eq(date + (2 * day_interval)) }
|
|
344
410
|
end
|
|
345
411
|
end
|
|
346
412
|
end
|
|
@@ -368,7 +434,7 @@ RSpec.describe Business::Calendar do
|
|
|
368
434
|
context "preceeded by another non-business day" do
|
|
369
435
|
let(:date) { date_class.parse("Sunday 6th Jan, 2013") }
|
|
370
436
|
|
|
371
|
-
it { is_expected.to eq(date - 2 * day_interval) }
|
|
437
|
+
it { is_expected.to eq(date - (2 * day_interval)) }
|
|
372
438
|
end
|
|
373
439
|
end
|
|
374
440
|
end
|
|
@@ -396,7 +462,7 @@ RSpec.describe Business::Calendar do
|
|
|
396
462
|
context "followed by another non-business day" do
|
|
397
463
|
let(:date) { date_class.parse("Saturday 5th Jan, 2013") }
|
|
398
464
|
|
|
399
|
-
it { is_expected.to eq(date + 2 * day_interval) }
|
|
465
|
+
it { is_expected.to eq(date + (2 * day_interval)) }
|
|
400
466
|
end
|
|
401
467
|
end
|
|
402
468
|
end
|
|
@@ -424,7 +490,7 @@ RSpec.describe Business::Calendar do
|
|
|
424
490
|
context "preceeded by another non-business day" do
|
|
425
491
|
let(:date) { date_class.parse("Sunday 6th Jan, 2013") }
|
|
426
492
|
|
|
427
|
-
it { is_expected.to eq(date - 2 * day_interval) }
|
|
493
|
+
it { is_expected.to eq(date - (2 * day_interval)) }
|
|
428
494
|
end
|
|
429
495
|
end
|
|
430
496
|
end
|
|
@@ -444,33 +510,33 @@ RSpec.describe Business::Calendar do
|
|
|
444
510
|
context "and a period that includes only business days" do
|
|
445
511
|
let(:date) { date_class.parse("Wednesday 2nd Jan, 2013") }
|
|
446
512
|
|
|
447
|
-
it { is_expected.to eq(date + delta * day_interval) }
|
|
513
|
+
it { is_expected.to eq(date + (delta * day_interval)) }
|
|
448
514
|
end
|
|
449
515
|
|
|
450
516
|
context "and a period that includes a weekend" do
|
|
451
517
|
let(:date) { date_class.parse("Friday 4th Jan, 2013") }
|
|
452
518
|
|
|
453
|
-
it { is_expected.to eq(date + (delta + 2) * day_interval) }
|
|
519
|
+
it { is_expected.to eq(date + ((delta + 2) * day_interval)) }
|
|
454
520
|
end
|
|
455
521
|
|
|
456
522
|
context "and a period that includes a working date weekend" do
|
|
457
523
|
let(:extra_working_dates) { ["Sunday 6th Jan, 2013"] }
|
|
458
524
|
let(:date) { date_class.parse("Friday 4th Jan, 2013") }
|
|
459
525
|
|
|
460
|
-
it { is_expected.to eq(date + (delta + 1) * day_interval) }
|
|
526
|
+
it { is_expected.to eq(date + ((delta + 1) * day_interval)) }
|
|
461
527
|
end
|
|
462
528
|
|
|
463
529
|
context "and a period that includes a holiday day" do
|
|
464
530
|
let(:date) { date_class.parse("Monday 31st Dec, 2012") }
|
|
465
531
|
|
|
466
|
-
it { is_expected.to eq(date + (delta + 1) * day_interval) }
|
|
532
|
+
it { is_expected.to eq(date + ((delta + 1) * day_interval)) }
|
|
467
533
|
end
|
|
468
534
|
end
|
|
469
535
|
|
|
470
536
|
context "given a non-business day" do
|
|
471
537
|
let(:date) { date_class.parse("Tuesday 1st Jan, 2013") }
|
|
472
538
|
|
|
473
|
-
it { is_expected.to eq(date + (delta + 1) * day_interval) }
|
|
539
|
+
it { is_expected.to eq(date + ((delta + 1) * day_interval)) }
|
|
474
540
|
end
|
|
475
541
|
end
|
|
476
542
|
|
|
@@ -489,33 +555,33 @@ RSpec.describe Business::Calendar do
|
|
|
489
555
|
context "and a period that includes only business days" do
|
|
490
556
|
let(:date) { date_class.parse("Wednesday 2nd Jan, 2013") }
|
|
491
557
|
|
|
492
|
-
it { is_expected.to eq(date - delta * day_interval) }
|
|
558
|
+
it { is_expected.to eq(date - (delta * day_interval)) }
|
|
493
559
|
end
|
|
494
560
|
|
|
495
561
|
context "and a period that includes a weekend" do
|
|
496
562
|
let(:date) { date_class.parse("Monday 31st Dec, 2012") }
|
|
497
563
|
|
|
498
|
-
it { is_expected.to eq(date - (delta + 2) * day_interval) }
|
|
564
|
+
it { is_expected.to eq(date - ((delta + 2) * day_interval)) }
|
|
499
565
|
end
|
|
500
566
|
|
|
501
567
|
context "and a period that includes a working date weekend" do
|
|
502
568
|
let(:extra_working_dates) { ["Saturday 29th Dec, 2012"] }
|
|
503
569
|
let(:date) { date_class.parse("Monday 31st Dec, 2012") }
|
|
504
570
|
|
|
505
|
-
it { is_expected.to eq(date - (delta + 1) * day_interval) }
|
|
571
|
+
it { is_expected.to eq(date - ((delta + 1) * day_interval)) }
|
|
506
572
|
end
|
|
507
573
|
|
|
508
574
|
context "and a period that includes a holiday day" do
|
|
509
575
|
let(:date) { date_class.parse("Friday 4th Jan, 2013") }
|
|
510
576
|
|
|
511
|
-
it { is_expected.to eq(date - (delta + 1) * day_interval) }
|
|
577
|
+
it { is_expected.to eq(date - ((delta + 1) * day_interval)) }
|
|
512
578
|
end
|
|
513
579
|
end
|
|
514
580
|
|
|
515
581
|
context "given a non-business day" do
|
|
516
582
|
let(:date) { date_class.parse("Thursday 3rd Jan, 2013") }
|
|
517
583
|
|
|
518
|
-
it { is_expected.to eq(date - (delta + 1) * day_interval) }
|
|
584
|
+
it { is_expected.to eq(date - ((delta + 1) * day_interval)) }
|
|
519
585
|
end
|
|
520
586
|
end
|
|
521
587
|
|
metadata
CHANGED
|
@@ -1,71 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: business
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
8
|
-
autorequire:
|
|
7
|
+
- GoCcardless
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
-
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: gc_ruboconfig
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - "~>"
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: 2.31.0
|
|
20
|
-
type: :development
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - "~>"
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: 2.31.0
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: rspec
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - "~>"
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '3.1'
|
|
34
|
-
type: :development
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - "~>"
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '3.1'
|
|
41
|
-
- !ruby/object:Gem::Dependency
|
|
42
|
-
name: rspec_junit_formatter
|
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
|
44
|
-
requirements:
|
|
45
|
-
- - "~>"
|
|
46
|
-
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.5.1
|
|
48
|
-
type: :development
|
|
49
|
-
prerelease: false
|
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
-
requirements:
|
|
52
|
-
- - "~>"
|
|
53
|
-
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.5.1
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: rubocop
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - "~>"
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: 1.25.0
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: 1.25.0
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
69
12
|
description: Date calculations based on business calendars
|
|
70
13
|
email:
|
|
71
14
|
- developers@gocardless.com
|
|
@@ -73,12 +16,13 @@ executables: []
|
|
|
73
16
|
extensions: []
|
|
74
17
|
extra_rdoc_files: []
|
|
75
18
|
files:
|
|
76
|
-
- ".circleci/config.yml"
|
|
77
19
|
- ".github/dependabot.yml"
|
|
20
|
+
- ".github/workflows/tests.yml"
|
|
78
21
|
- ".gitignore"
|
|
79
22
|
- ".rubocop.yml"
|
|
80
23
|
- ".ruby-version"
|
|
81
24
|
- CHANGELOG.md
|
|
25
|
+
- COMPATIBILITY.md
|
|
82
26
|
- Gemfile
|
|
83
27
|
- LICENSE
|
|
84
28
|
- README.md
|
|
@@ -93,8 +37,8 @@ files:
|
|
|
93
37
|
homepage: https://github.com/gocardless/business
|
|
94
38
|
licenses:
|
|
95
39
|
- MIT
|
|
96
|
-
metadata:
|
|
97
|
-
|
|
40
|
+
metadata:
|
|
41
|
+
rubygems_mfa_required: 'true'
|
|
98
42
|
rdoc_options: []
|
|
99
43
|
require_paths:
|
|
100
44
|
- lib
|
|
@@ -109,12 +53,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
109
53
|
- !ruby/object:Gem::Version
|
|
110
54
|
version: '0'
|
|
111
55
|
requirements: []
|
|
112
|
-
rubygems_version:
|
|
113
|
-
signing_key:
|
|
56
|
+
rubygems_version: 4.0.16
|
|
114
57
|
specification_version: 4
|
|
115
58
|
summary: Date calculations based on business calendars
|
|
116
|
-
test_files:
|
|
117
|
-
- spec/business/calendar_spec.rb
|
|
118
|
-
- spec/fixtures/calendars/bacs.yml
|
|
119
|
-
- spec/fixtures/calendars/ecb.yml
|
|
120
|
-
- spec/fixtures/calendars/invalid-keys.yml
|
|
59
|
+
test_files: []
|
data/.circleci/config.yml
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
version: 2.1
|
|
2
|
-
|
|
3
|
-
jobs:
|
|
4
|
-
test:
|
|
5
|
-
docker:
|
|
6
|
-
- image: cimg/ruby:<< parameters.ruby-version >>
|
|
7
|
-
parameters:
|
|
8
|
-
ruby-version:
|
|
9
|
-
type: string
|
|
10
|
-
steps:
|
|
11
|
-
- checkout
|
|
12
|
-
- restore_cache:
|
|
13
|
-
keys:
|
|
14
|
-
- bundle-v1-<< parameters.ruby-version >>-{{ checksum "business.gemspec" }}
|
|
15
|
-
- bundle-v1-<< parameters.ruby-version >>-
|
|
16
|
-
- run:
|
|
17
|
-
name: Install dependencies
|
|
18
|
-
command: bundle install --clean --no-cache --path vendor/bundle --jobs=4 --retry=3
|
|
19
|
-
- save_cache:
|
|
20
|
-
key: bundle-v1-<< parameters.ruby-version >>-{{ checksum "business.gemspec" }}
|
|
21
|
-
paths:
|
|
22
|
-
- vendor/bundle
|
|
23
|
-
- run:
|
|
24
|
-
name: Run tests
|
|
25
|
-
command: bundle exec rspec
|
|
26
|
-
- run:
|
|
27
|
-
name: Run rubocop
|
|
28
|
-
command: bundle exec rubocop --parallel --extra-details --display-style-guide
|
|
29
|
-
|
|
30
|
-
workflows:
|
|
31
|
-
default:
|
|
32
|
-
jobs:
|
|
33
|
-
- test:
|
|
34
|
-
name: Ruby << matrix.ruby-version >>
|
|
35
|
-
matrix:
|
|
36
|
-
parameters:
|
|
37
|
-
ruby-version: ["2.6.7", "2.7.3", "3.0.1", "3.1.0"]
|