biz 1.4.0 → 1.5.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/README.md +70 -1
- data/lib/biz.rb +0 -1
- data/lib/biz/configuration.rb +9 -2
- data/lib/biz/interval.rb +27 -6
- data/lib/biz/schedule.rb +17 -0
- data/lib/biz/time_segment.rb +4 -14
- data/lib/biz/version.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bfccc20f9a27336663959946a872593d35c53a3
|
4
|
+
data.tar.gz: 962e4f9927fb08f8f609e76d3f11b10949d81922
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63aeb93f5ce1299b4164ba9ec5d537032d6f8ff174ca5b08c0fd62d62a4afec902b4528ec4d1d606899764cf20aacddd08c8cf64f95dc81348f50bf6a1446968
|
7
|
+
data.tar.gz: d81c55c540298d454bab98a9d54243cb139f2aeed16ff4b1c817479e63798dab3909dfdb43c35339646d9139a508fa78bb9f9b84a43d09863d2c38b5b36c448c
|
data/README.md
CHANGED
@@ -17,6 +17,7 @@ Time calculations using business hours.
|
|
17
17
|
- Multiple schedule configurations.
|
18
18
|
* Second-level precision on all calculations.
|
19
19
|
* Accurate handling of Daylight Saving Time.
|
20
|
+
* Schedule intersection.
|
20
21
|
* Thread-safe.
|
21
22
|
|
22
23
|
## Anti-Features
|
@@ -50,7 +51,7 @@ Biz.configure do |config|
|
|
50
51
|
sat: {'10:00' => '14:00'}
|
51
52
|
}
|
52
53
|
|
53
|
-
config.holidays = [Date.new(
|
54
|
+
config.holidays = [Date.new(2016, 1, 1), Date.new(2016, 12, 25)]
|
54
55
|
|
55
56
|
config.time_zone = 'America/Los_Angeles'
|
56
57
|
end
|
@@ -120,6 +121,74 @@ Biz.periods
|
|
120
121
|
# #<Biz::TimeSegment start_time=2015-04-27 20:36:57 UTC end_time=2015-04-28 00:00:00 UTC>]
|
121
122
|
```
|
122
123
|
|
124
|
+
## Schedule Intersection
|
125
|
+
|
126
|
+
An intersection of two schedules can be found using `&`:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
schedule_1 = Biz::Schedule.new do |config|
|
130
|
+
config.hours = {
|
131
|
+
mon: {'09:00' => '17:00'},
|
132
|
+
tue: {'10:00' => '16:00'},
|
133
|
+
wed: {'09:00' => '17:00'},
|
134
|
+
thu: {'10:00' => '16:00'},
|
135
|
+
fri: {'09:00' => '17:00'},
|
136
|
+
sat: {'11:00' => '14:30'}
|
137
|
+
}
|
138
|
+
|
139
|
+
config.holidays = [Date.new(2016, 1, 1), Date.new(2016, 12, 25)]
|
140
|
+
|
141
|
+
config.time_zone = 'Etc/UTC'
|
142
|
+
end
|
143
|
+
|
144
|
+
schedule_2 = Biz::Schedule.new do |config|
|
145
|
+
config.hours = {
|
146
|
+
sun: {'10:00' => '12:00'},
|
147
|
+
mon: {'08:00' => '10:00'},
|
148
|
+
tue: {'11:00' => '15:00'},
|
149
|
+
wed: {'16:00' => '18:00'},
|
150
|
+
thu: {'11:00' => '12:00', '13:00' => '14:00'}
|
151
|
+
}
|
152
|
+
|
153
|
+
config.holidays = [
|
154
|
+
Date.new(2016, 1, 1),
|
155
|
+
Date.new(2016, 7, 4),
|
156
|
+
Date.new(2016, 11, 24)
|
157
|
+
]
|
158
|
+
|
159
|
+
config.time_zone = 'America/Los_Angeles'
|
160
|
+
end
|
161
|
+
|
162
|
+
schedule_1 & schedule_2
|
163
|
+
```
|
164
|
+
|
165
|
+
The resulting schedule will be a combination of the two schedules: an
|
166
|
+
intersection of the intervals, a union of the holidays, and the time zone of the
|
167
|
+
first schedule.
|
168
|
+
|
169
|
+
For the above example, the resulting schedule would be equivalent to one with
|
170
|
+
the following configuration:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
Biz::Schedule.new do |config|
|
174
|
+
config.hours = {
|
175
|
+
mon: {'09:00' => '10:00'},
|
176
|
+
tue: {'11:00' => '15:00'},
|
177
|
+
wed: {'16:00' => '17:00'},
|
178
|
+
thu: {'11:00' => '12:00', '13:00' => '14:00'}
|
179
|
+
}
|
180
|
+
|
181
|
+
config.holidays = [
|
182
|
+
Date.new(2016, 1, 1),
|
183
|
+
Date.new(2016, 7, 4),
|
184
|
+
Date.new(2016, 11, 24),
|
185
|
+
Date.new(2016, 12, 25)
|
186
|
+
]
|
187
|
+
|
188
|
+
config.time_zone = 'Etc/UTC'
|
189
|
+
end
|
190
|
+
```
|
191
|
+
|
123
192
|
## Core Extensions
|
124
193
|
|
125
194
|
Optional extensions to core classes (`Date`, `Fixnum`, and `Time`) are available
|
data/lib/biz.rb
CHANGED
data/lib/biz/configuration.rb
CHANGED
@@ -7,6 +7,8 @@ module Biz
|
|
7
7
|
yield raw if block_given?
|
8
8
|
|
9
9
|
Validation.perform(raw)
|
10
|
+
|
11
|
+
raw.freeze
|
10
12
|
end
|
11
13
|
|
12
14
|
def intervals
|
@@ -21,7 +23,12 @@ module Biz
|
|
21
23
|
|
22
24
|
def holidays
|
23
25
|
@holidays ||= begin
|
24
|
-
raw
|
26
|
+
raw
|
27
|
+
.holidays
|
28
|
+
.uniq
|
29
|
+
.map { |date| Holiday.new(date, time_zone) }
|
30
|
+
.sort
|
31
|
+
.freeze
|
25
32
|
end
|
26
33
|
end
|
27
34
|
|
@@ -30,7 +37,7 @@ module Biz
|
|
30
37
|
end
|
31
38
|
|
32
39
|
def weekdays
|
33
|
-
@weekdays ||= raw.hours.keys.
|
40
|
+
@weekdays ||= raw.hours.keys.uniq.freeze
|
34
41
|
end
|
35
42
|
|
36
43
|
protected
|
data/lib/biz/interval.rb
CHANGED
@@ -1,18 +1,38 @@
|
|
1
1
|
module Biz
|
2
2
|
class Interval
|
3
3
|
|
4
|
+
extend Forwardable
|
5
|
+
|
4
6
|
include Comparable
|
5
7
|
|
8
|
+
def self.to_hours(intervals)
|
9
|
+
intervals.each_with_object(
|
10
|
+
Hash.new do |hours, wday| hours.store(wday, {}) end
|
11
|
+
) do |interval, hours|
|
12
|
+
hours[interval.wday_symbol].store(*interval.endpoints.map(&:timestamp))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
6
16
|
def initialize(start_time, end_time, time_zone)
|
7
17
|
@start_time = start_time
|
8
18
|
@end_time = end_time
|
9
19
|
@time_zone = time_zone
|
10
20
|
end
|
11
21
|
|
22
|
+
attr_reader :start_time,
|
23
|
+
:end_time,
|
24
|
+
:time_zone
|
25
|
+
|
26
|
+
delegate wday_symbol: :start_time
|
27
|
+
|
12
28
|
def endpoints
|
13
29
|
[start_time, end_time]
|
14
30
|
end
|
15
31
|
|
32
|
+
def empty?
|
33
|
+
start_time >= end_time
|
34
|
+
end
|
35
|
+
|
16
36
|
def contains?(time)
|
17
37
|
(start_time...end_time).cover?(
|
18
38
|
WeekTime.from_time(Time.new(time_zone).local(time))
|
@@ -27,6 +47,13 @@ module Biz
|
|
27
47
|
)
|
28
48
|
end
|
29
49
|
|
50
|
+
def &(other)
|
51
|
+
lower_bound = [self, other].map(&:start_time).max
|
52
|
+
upper_bound = [self, other].map(&:end_time).min
|
53
|
+
|
54
|
+
self.class.new(lower_bound, [lower_bound, upper_bound].max, time_zone)
|
55
|
+
end
|
56
|
+
|
30
57
|
def <=>(other)
|
31
58
|
return unless other.is_a?(self.class)
|
32
59
|
|
@@ -34,11 +61,5 @@ module Biz
|
|
34
61
|
[other.start_time, other.end_time, other.time_zone]
|
35
62
|
end
|
36
63
|
|
37
|
-
protected
|
38
|
-
|
39
|
-
attr_reader :start_time,
|
40
|
-
:end_time,
|
41
|
-
:time_zone
|
42
|
-
|
43
64
|
end
|
44
65
|
end
|
data/lib/biz/schedule.rb
CHANGED
@@ -46,6 +46,23 @@ module Biz
|
|
46
46
|
Time.new(time_zone)
|
47
47
|
end
|
48
48
|
|
49
|
+
def &(other)
|
50
|
+
self.class.new do |config|
|
51
|
+
config.hours = Interval.to_hours(
|
52
|
+
intervals.flat_map { |interval|
|
53
|
+
other
|
54
|
+
.intervals
|
55
|
+
.map { |other_interval| interval & other_interval }
|
56
|
+
.reject(&:empty?)
|
57
|
+
}
|
58
|
+
)
|
59
|
+
|
60
|
+
config.holidays = [*holidays, *other.holidays].map(&:to_date)
|
61
|
+
|
62
|
+
config.time_zone = time_zone.name
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
49
66
|
protected
|
50
67
|
|
51
68
|
attr_reader :configuration
|
data/lib/biz/time_segment.rb
CHANGED
@@ -36,10 +36,10 @@ module Biz
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def &(other)
|
39
|
-
self.
|
40
|
-
|
41
|
-
|
42
|
-
)
|
39
|
+
lower_bound = [self, other].map(&:start_time).max
|
40
|
+
upper_bound = [self, other].map(&:end_time).min
|
41
|
+
|
42
|
+
self.class.new(lower_bound, [lower_bound, upper_bound].max)
|
43
43
|
end
|
44
44
|
|
45
45
|
def <=>(other)
|
@@ -48,15 +48,5 @@ module Biz
|
|
48
48
|
[start_time, end_time] <=> [other.start_time, other.end_time]
|
49
49
|
end
|
50
50
|
|
51
|
-
private
|
52
|
-
|
53
|
-
def lower_bound(other)
|
54
|
-
[self, other].map(&:start_time).max
|
55
|
-
end
|
56
|
-
|
57
|
-
def upper_bound(other)
|
58
|
-
[self, other].map(&:end_time).min
|
59
|
-
end
|
60
|
-
|
61
51
|
end
|
62
52
|
end
|
data/lib/biz/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: biz
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Craig Little
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-03-
|
12
|
+
date: 2016-03-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: clavius
|
@@ -45,14 +45,14 @@ dependencies:
|
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
48
|
+
version: '11.0'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '11.0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rspec
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
@@ -135,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
135
|
version: '0'
|
136
136
|
requirements: []
|
137
137
|
rubyforge_project:
|
138
|
-
rubygems_version: 2.
|
138
|
+
rubygems_version: 2.2.2
|
139
139
|
signing_key:
|
140
140
|
specification_version: 4
|
141
141
|
summary: Business hours calculations
|