business_day 3.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e7eec67857ca22aefb1b20f5efe6a2d6c4b08e9fd4ab721cee016e2a038f819f
4
+ data.tar.gz: 1b210218ace3e18490d13a7467f33516adee9c2748419e1656873c66ddb6ff52
5
+ SHA512:
6
+ metadata.gz: 9199b19412df4d0c13def585e3b64559655a5de1f2a26fc1c2ba7d91ad350fa2a4a90cc84c76b75b2b2e3754bcacf4a793e6e51c266ac248358dac652de262c8
7
+ data.tar.gz: 31762c435189f1b5e6ea5252653cbee52e95235b223313c7913e8a4c9b81e2746820db848a807b88fbe234aa646a21de61e52d788a101ae0812d0e7f0802ea43
@@ -0,0 +1,37 @@
1
+ version: 2.1
2
+
3
+ jobs:
4
+ test:
5
+ docker:
6
+ - image: circleci/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.4.9", "2.5.8", "2.6.6", "2.7.1"]
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
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 ADDED
@@ -0,0 +1 @@
1
+ 2.7.1
data/CHANGELOG.md ADDED
@@ -0,0 +1,118 @@
1
+ ## 2.1.0 - June 8, 2020
2
+
3
+ - Add seperate `working_day?` and `holiday?` methods to the calendar
4
+
5
+ ## 2.0.0 - May 4, 2020
6
+
7
+ 🚨 **BREAKING CHANGES** 🚨
8
+
9
+ For more on the breaking changes that have been introduced in v2.0.0 please [see the readme](README.md#v200-breaking-changes).
10
+
11
+ - Remove bundled calendars see [this pr](https://github.com/gocardless/business/pull/54) for more context. If you need to use any of the previously bundled calendars, [see here](https://github.com/gocardless/business/tree/b12c186ca6fd4ffdac85175742ff7e4d0a705ef4/lib/business/data)
12
+ - `Business::Calendar.load_paths=` is now required
13
+
14
+ ## 1.18.0 - April 30, 2020
15
+
16
+ ### Note we have dropped support for Ruby < 2.4.x
17
+
18
+ - Correct Danish public holidays
19
+
20
+ ## 1.17.1 - November 19, 2019
21
+
22
+ - Change May Bank Holiday 2020 for UK (Bacs) - this was moved to the 8th.
23
+ - Add 2020 holidays for PAD.
24
+
25
+ ## 1.17.0 - October 30, 2019
26
+
27
+ - Add holiday calendar for France (Target(SEPA) + French bank holidays)
28
+
29
+ ## 1.16.1 - September 2, 2019
30
+
31
+ - Fix holiday calendar for ACH U.S.
32
+
33
+ ## 1.16.0 - January 17, 2019
34
+
35
+ - Add holiday calendar for ACH U.S.
36
+
37
+ ## 1.15.0 - October 24, 2018
38
+
39
+ - Add holiday calendar for PAD Canada
40
+
41
+ ## 1.14.0 - July 18, 2018
42
+
43
+ - Add holiday calendar for BECS New Zealand
44
+
45
+ ## 1.13.1 - June 22, 2018
46
+
47
+ - Fix June's 2018 bank holidays for Bankgirot
48
+
49
+ ## 1.13.0 - April 17, 2018
50
+
51
+ - Add support for specifying `extra_working_dates` (special dates that are "working days",
52
+ even though they are not one of the specified days, for example weekend dates
53
+ that are considered to be working days)
54
+
55
+ ## 1.12.0 - April 3, 2018
56
+
57
+ - Add Betalingservice & BECS calendars up until 2020
58
+
59
+ ## 1.11.1 - December 20, 2017
60
+
61
+ - Add 2017-2018 BECS holiday definitions
62
+
63
+ ## 1.11.0 - December 13, 2017
64
+
65
+ - Handle properly calendar initialization by Date objects (not strings),
66
+ coming from both YAML config and initialize().
67
+
68
+
69
+ ## 1.10.0 - September 20, 2017
70
+
71
+ - Add 2018-2019 Betalingsservice holiday definitions
72
+
73
+ ## 1.9.0 - August 23, 2017
74
+
75
+ - Add 2017 Betalingsservice holiday definitions
76
+
77
+ ## 1.8.0 - February 13, 2017
78
+
79
+ - Add 2018-2027 TARGET holiday defintions
80
+ - Add 2018-2027 Bankgirot holiday defintions
81
+
82
+ ## 1.7.0 - January 18, 2017
83
+
84
+ - Add 2018-2027 BACS holiday defintions
85
+
86
+ ## 1.6.0 - December 23, 2016
87
+
88
+ - Add 2017 BACS holiday definitions
89
+ - Add 2017 and 2018 TARGET holiday definitions
90
+
91
+ ## 1.5.0 - June 2, 2015
92
+
93
+ - Add 2016 holiday definitions
94
+
95
+ ## 1.4.0 - December 24, 2014
96
+
97
+ - Add support for custom calendar load paths
98
+ - Remove the 'sepa' calendar
99
+
100
+
101
+ ## 1.3.0 - December 2, 2014
102
+
103
+ - Add `Calendar#previous_business_day`
104
+
105
+
106
+ ## 1.2.0 - November 15, 2014
107
+
108
+ - Add TARGET calendar
109
+
110
+
111
+ ## 1.1.0 - September 30, 2014
112
+
113
+ - Add 2015 holiday definitions
114
+
115
+
116
+ ## 1.0.0 - June 11, 2014
117
+
118
+ - Initial public release
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 GoCardless
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,196 @@
1
+ # Business
2
+
3
+ [![Gem version](https://badge.fury.io/rb/business.svg)](http://badge.fury.io/rb/business)
4
+ [![CircleCI](https://circleci.com/gh/gocardless/business.svg?style=svg)](https://circleci.com/gh/gocardless/business)
5
+
6
+ Date calculations based on business calendars.
7
+
8
+ - [v2.0.0 breaking changes](#v200-breaking-changes)
9
+ - [Getting Started](#getting-started)
10
+ - [Creating a calendar](#creating-a-calendar)
11
+ - [Using a calendar file](#use-a-calendar-file)
12
+ - [Checking for business days](#checking-for-business-days)
13
+ - [Business day arithmetic](#business-day-arithmetic)
14
+ - [But other libraries already do this](#but-other-libraries-already-do-this)
15
+ - [License & Contributing](#license--contributing)
16
+
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 `BusinessDay::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
+ BusinessDay::Calendar.load_paths = ["lib/calendars"] # your_project/lib/calendars/ contains bacs.yml
27
+ BusinessDay::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
+ ## Getting started
38
+
39
+ To install business, simply:
40
+
41
+ ```bash
42
+ gem install business
43
+ ```
44
+
45
+ If you are using a Gemfile:
46
+
47
+ ```ruby
48
+ gem "business", "~> 2.0"
49
+ ```
50
+
51
+ ### Creating a calendar
52
+
53
+ Get started with business by creating an instance of the calendar class, that accepts a hash that specifies which days of the week are considered working days, which days are holidays and which are extra working dates.
54
+
55
+ ```ruby
56
+ calendar = BusinessDay::Calendar.new(
57
+ working_days: %w( mon tue wed thu fri ),
58
+ holidays: ["01/01/2014", "03/01/2014"] # array items are either parseable date strings, or real Date objects
59
+ extra_working_dates: [nil], # Makes the calendar to consider a weekend day as a working day.
60
+ )
61
+ ```
62
+
63
+ ### Use a calendar file
64
+
65
+ Defining a calendar as a Ruby object may not be convenient, so we provide a way of defining these calendars as YAML. Below we will walk through the necessary [steps](#example-calendar) to build your first calendar. All keys are optional and will default to the following:
66
+
67
+ Note: Elements of `holidays` and `extra_working_dates` may be either strings that `Date.parse()` [can understand](https://ruby-doc.org/stdlib-2.7.1/libdoc/date/rdoc/Date.html#method-c-parse), or `YYYY-MM-DD` (which is considered as a Date by Ruby YAML itself)[https://github.com/ruby/psych/blob/6ec6e475e8afcf7868b0407fc08014aed886ecf1/lib/psych/scalar_scanner.rb#L60].
68
+
69
+ #### YAML file Structure
70
+
71
+ ```yml
72
+ working_days: # Optional, default [Monday-Friday]
73
+ -
74
+ holidays: # Optional, default: [] ie: "no holidays" assumed
75
+ -
76
+ extra_working_dates: # Optional, default: [], ie: no changes in `working_days` will happen
77
+ -
78
+ ```
79
+
80
+ #### Example calendar
81
+
82
+ ```yaml
83
+ # lib/calendars/my_calendar.yml
84
+ working_days:
85
+ - Monday
86
+ - Wednesday
87
+ - Friday
88
+ holidays:
89
+ - 1st April 2020
90
+ - 2021-04-01
91
+ extra_working_dates:
92
+ - 9th March 2020 # A Saturday
93
+ ```
94
+
95
+ Ensure the calendar file is saved to a directory that will hold all your calendars, typically `lib/calendars`, then add this directory to your instance of `BusinessDay::Calendar` using the `load_paths` method before you call your calendar.
96
+
97
+ `load_paths` also accepts an array of plain Ruby hashes with the format:
98
+
99
+ ```ruby
100
+ { "calendar_name" => { "working_days" => [] }
101
+ ```
102
+
103
+ #### Example loading both a path and ruby hashes
104
+
105
+ ```ruby
106
+ BusinessDay::Calendar.load_paths = [
107
+ "lib/calendars",
108
+ { "foo_calendar" => { "working_days" => ["monday"] } },
109
+ { "bar_calendar" => { "working_days" => ["sunday"] } },
110
+ ]
111
+ ```
112
+
113
+ Now you can load the calendar by calling the `BusinessDay::Calendar.load(calendar_name)`. In order to avoid parsing the calendar file multiple times, there is a `BusinessDay::Calendar.load_cached(calendar_name)` method that caches the calendars by name after loading them.
114
+
115
+ ```ruby
116
+ calendar = BusinessDay::Calendar.load("my_calendar") # lib/calendars/my_calendar.yml
117
+ calendar = BusinessDay::Calendar.load("foo_calendar")
118
+ # or
119
+ calendar = BusinessDay::Calendar.load_cached("my_calendar")
120
+ calendar = BusinessDay::Calendar.load_cached("foo_calendar")
121
+ ```
122
+
123
+ ## Checking for business days
124
+
125
+ To check whether a given date is a business day (falls on one of the specified working days or working dates, and is not a holiday), use the `business_day?` method on `BusinessDay::Calendar`.
126
+
127
+ ```ruby
128
+ calendar.business_day?(Date.parse("Monday, 9 June 2014"))
129
+ # => true
130
+ calendar.business_day?(Date.parse("Sunday, 8 June 2014"))
131
+ # => false
132
+ ```
133
+
134
+ More specifically you can check if a given `business_day?` is either a `working_day?` or a `holiday?` using methods on `BusinessDay::Calendar`.
135
+
136
+ ```ruby
137
+ # Assuming "Monday, 9 June 2014" is a holiday
138
+ calendar.working_day?(Date.parse("Monday, 9 June 2014"))
139
+ # => true
140
+ calendar.holiday?(Date.parse("Monday, 9 June 2014"))
141
+ # => true
142
+ # Monday is a working day, but we have a holiday so it's not
143
+ # a business day
144
+ calendar.business_day?(Date.parse("Monday, 9 June 2014"))
145
+ # => false
146
+ ```
147
+
148
+ ## Business day arithmetic
149
+
150
+ The `add_business_days` and `subtract_business_days` are used to perform business day arithmetic on dates.
151
+
152
+ ```ruby
153
+ date = Date.parse("Thursday, 12 June 2014")
154
+ calendar.add_business_days(date, 4).strftime("%A, %d %B %Y")
155
+ # => "Wednesday, 18 June 2014"
156
+ calendar.subtract_business_days(date, 4).strftime("%A, %d %B %Y")
157
+ # => "Friday, 06 June 2014"
158
+ ```
159
+
160
+ The `roll_forward` and `roll_backward` methods snap a date to a nearby business day. If provided with a business day, they will return that date. Otherwise, they will advance (forward for `roll_forward` and backward for `roll_backward`) until a business day is found.
161
+
162
+ ```ruby
163
+ date = Date.parse("Saturday, 14 June 2014")
164
+ calendar.roll_forward(date).strftime("%A, %d %B %Y")
165
+ # => "Monday, 16 June 2014"
166
+ calendar.roll_backward(date).strftime("%A, %d %B %Y")
167
+ # => "Friday, 13 June 2014"
168
+ ```
169
+
170
+ To count the number of business days between two dates, pass the dates to `business_days_between`. This method counts from start of the first date to start of the second date. So, assuming no holidays, there would be two business days between a Monday and a Wednesday.
171
+
172
+ ```ruby
173
+ date = Date.parse("Saturday, 14 June 2014")
174
+ calendar.business_days_between(date, date + 7)
175
+ # => 5
176
+ ```
177
+
178
+ ## But other libraries already do this
179
+
180
+ Another gem, [business_time](https://github.com/bokmann/business_time), also exists for this purpose. We previously used business_time, but encountered several issues that prompted us to start business.
181
+
182
+ Firstly, business_time works by monkey-patching `Date`, `Time`, and `FixNum`. While this enables syntax like `Time.now + 1.business_day`, it means that all configuration has to be global. GoCardless handles payments across several geographies, so being able to work with multiple working-day calendars is
183
+ essential for us. Business provides a simple `Calendar` class, that is initialized with a configuration that specifies which days of the week are considered to be working days, and which dates are holidays.
184
+
185
+ Secondly, business_time supports calculations on times as well as dates. For our purposes, date-based calculations are sufficient. Supporting time-based calculations as well makes the code significantly more complex. We chose to avoid this extra complexity by sticking solely to date-based mathematics.
186
+
187
+ <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>
188
+
189
+ ## License & Contributing
190
+ - business is available as open source under the terms of the [MIT License](LICENSE).
191
+ - Bug reports and pull requests are welcome on GitHub at https://github.com/gocardless/business.
192
+
193
+ GoCardless ♥ open source. If you do too, come [join us](https://gocardless.com/about/jobs).
194
+
195
+ ## In this FORK
196
+ Renamed the Business module to BusinessDay
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ lib = File.expand_path("lib", __dir__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require "business_day/version"
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "business_day"
10
+ spec.version = BusinessDay::VERSION
11
+ spec.authors = ["Harry Marr"]
12
+ spec.email = ["developers@gocardless.com"]
13
+ spec.summary = "Date calculations based on business calendars"
14
+ spec.description = "Date calculations based on business calendars"
15
+ spec.homepage = "https://github.com/go-tandem/business_day"
16
+ spec.licenses = ["MIT"]
17
+
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
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "gc_ruboconfig", "~> 2.24.0"
24
+ spec.add_development_dependency "rspec", "~> 3.1"
25
+ spec.add_development_dependency "rspec_junit_formatter", "~> 0.4.1"
26
+ spec.add_development_dependency "rubocop", "~> 1.10.0"
27
+ end