business_day 3.1.0

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