business_time 0.7.4 → 0.7.5
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/LICENSE +1 -1
- data/README.rdoc +30 -19
- data/lib/business_time/business_days.rb +24 -2
- data/lib/business_time/business_hours.rb +10 -0
- data/lib/business_time/config.rb +18 -3
- data/lib/business_time/core_ext/date.rb +9 -5
- data/lib/business_time/time_extensions.rb +11 -1
- data/lib/business_time/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a751f4e1f9392f84ebca332f961e63434779054
|
4
|
+
data.tar.gz: aed6514ab58ee91cac9d45414459d12cdb7b9e7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e98626ba766dccef9d6f7826b456e17eada6258ad1e130d39a6fa423b4e99b9e301b8fb0748dfe6af5d172073b84c646ff96edaa4544fb1fa1ce60f4a49674d
|
7
|
+
data.tar.gz: 147619baf4a120328a78df160e4469874a040559b7acd4fb1fff5eacd0fb199ad904a3c239b25f376bdd63ffb6e1ecbeb722d8078163c69ea3a41adbf050e321
|
data/LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -15,11 +15,11 @@ as well as helpers to do that from any provided date or time.
|
|
15
15
|
I needed this, but taking into account business hours/days and holidays.
|
16
16
|
|
17
17
|
== Usage
|
18
|
-
|
18
|
+
=== install the gem
|
19
19
|
|
20
20
|
gem install business_time
|
21
21
|
|
22
|
-
|
22
|
+
=== open up your console
|
23
23
|
|
24
24
|
# if in irb, add these lines:
|
25
25
|
|
@@ -42,8 +42,12 @@ I needed this, but taking into account business hours/days and holidays.
|
|
42
42
|
1.business_day.ago
|
43
43
|
4.business_days.ago
|
44
44
|
8.business_days.ago
|
45
|
+
|
46
|
+
Date.today.workday?
|
47
|
+
Date.parse("2015-12-09").workday?
|
48
|
+
Date.parse("2015-12-12").workday?
|
45
49
|
|
46
|
-
|
50
|
+
And we can do it from any Date or Time object.
|
47
51
|
my_birthday = Date.parse("August 4th, 1969")
|
48
52
|
8.business_days.after(my_birthday)
|
49
53
|
8.business_days.before(my_birthday)
|
@@ -53,24 +57,24 @@ I needed this, but taking into account business hours/days and holidays.
|
|
53
57
|
8.business_days.before(my_birthday)
|
54
58
|
|
55
59
|
|
56
|
-
|
60
|
+
We can adjust the start and end time of our business hours
|
57
61
|
BusinessTime::Config.beginning_of_workday = "8:30 am"
|
58
62
|
BusinessTime::Config.end_of_workday = "5:30 pm"
|
59
63
|
|
60
|
-
|
61
|
-
|
64
|
+
and we can add holidays that don't count as business days
|
65
|
+
July 5 in 2010 is a monday that the U.S. takes off because our independence day falls on that Sunday.
|
62
66
|
three_day_weekend = Date.parse("July 5th, 2010")
|
63
67
|
BusinessTime::Config.holidays << three_day_weekend
|
64
68
|
friday_afternoon = Time.parse("July 2nd, 2010, 4:50 pm")
|
65
69
|
tuesday_morning = 1.business_hour.after(friday_afternoon)
|
66
70
|
|
67
|
-
|
71
|
+
plus, we can change the work week:
|
68
72
|
# July 9th in 2010 is a Friday.
|
69
73
|
BusinessTime::Config.work_week = [:sun, :mon, :tue, :wed, :thu]
|
70
74
|
thursday_afternoon = Time.parse("July 8th, 2010, 4:50 pm")
|
71
75
|
sunday_morning = 1.business_hour.after(thursday_afternoon)
|
72
76
|
|
73
|
-
|
77
|
+
As alternative we also can change the business hours for each work day:
|
74
78
|
BusinessTime::Config.work_hours = {
|
75
79
|
:mon=>["9:00","17:00"],
|
76
80
|
:fri=>["9:00","17:00"],
|
@@ -80,39 +84,46 @@ I needed this, but taking into account business hours/days and holidays.
|
|
80
84
|
monday = Time.parse("December 27, 2010 11:00")
|
81
85
|
working_hours = friday.business_time_until(monday) # 9.hours
|
82
86
|
|
83
|
-
|
87
|
+
You can also calculate business duration between two dates
|
84
88
|
friday = Date.parse("December 24, 2010")
|
85
89
|
monday = Date.parse("December 27, 2010")
|
86
90
|
friday.business_days_until(monday) #=> 1
|
87
91
|
|
88
|
-
|
92
|
+
Or you can calculate business duration between two Time objects
|
89
93
|
ticket_reported = Time.parse("February 3, 2012, 10:40 am")
|
90
94
|
ticket_resolved = Time.parse("February 4, 2012, 10:50 am")
|
91
95
|
ticket_reported.business_time_until(ticket_resolved) #=> 8.hours + 10.minutes
|
92
96
|
|
93
|
-
|
97
|
+
You can also determine if a given time is within business hours
|
94
98
|
Time.parse("February 3, 2012, 10:00 am").during_business_hours?
|
95
99
|
|
96
|
-
|
97
|
-
|
100
|
+
Note that counterintuitively, durations might not be quite what you expect when involving weekends.
|
101
|
+
Consider the following example:
|
98
102
|
ticket_reported = Time.parse("February 3, 2012, 10:40 am")
|
99
103
|
ticket_resolved = Time.parse("February 4, 2012, 10:40 am")
|
100
104
|
ticket_reported.business_time_until(ticket_resolved) # will equal 6 hours and 20 minutes!
|
101
105
|
|
102
|
-
|
103
|
-
|
104
|
-
|
106
|
+
Why does this happen? Feb 4 2012 is a Saturday. That time will roll over to
|
107
|
+
Monday, Feb 6th 2012, 9:00am. The business time between 10:40am friday and 9am monday is
|
108
|
+
6 hours and 20 minutes. From a quick inspection of the code, it looks like it should be 8 hours.
|
105
109
|
|
106
|
-
|
110
|
+
Or you can calculate business dates between two dates
|
107
111
|
monday = Date.parse("December 20, 2010")
|
108
112
|
wednesday = Date.parse("December 22, 2010")
|
109
113
|
monday.business_dates_until(wednesday) #=> [Mon, 20 Dec 2010, Tue, 21 Dec 2010]
|
110
114
|
|
111
|
-
|
115
|
+
You can get the first workday after a time or return itself if it is a workday
|
112
116
|
saturday = Time.parse("Sat Aug 9, 18:00:00, 2014")
|
113
117
|
monday = Time.parse("Mon Aug 11, 18:00:00, 2014")
|
114
118
|
Time.first_business_day(saturday) #=> "Mon Aug 11, 18:00:00, 2014"
|
115
119
|
Time.first_business_day(monday) #=> "Mon Aug 11, 18:00:00, 2014"
|
120
|
+
|
121
|
+
# similar to Time#first_business_day Time#previous_business_day only cares about
|
122
|
+
# workdays:
|
123
|
+
saturday = Time.parse("Sat Aug 9, 18:00:00, 2014")
|
124
|
+
monday = Time.parse("Mon Aug 11, 18:00:00, 2014")
|
125
|
+
Time.previous_business_day(saturday) #=> "Fri Aug 8, 18:00:00, 2014"
|
126
|
+
Time.previous_business_day(monday) #=> "Mon Aug 11, 18:00:00, 2014"
|
116
127
|
== Rails generator
|
117
128
|
|
118
129
|
rails generate business_time:config
|
@@ -205,4 +216,4 @@ I'm hoping Arild and I write some good blog entries on the subject at http://blo
|
|
205
216
|
|
206
217
|
== Copyright
|
207
218
|
|
208
|
-
Copyright (c) 2010
|
219
|
+
Copyright (c) 2010-2016 bokmann. See LICENSE for details.
|
@@ -2,15 +2,30 @@ require 'active_support/time'
|
|
2
2
|
|
3
3
|
module BusinessTime
|
4
4
|
class BusinessDays
|
5
|
+
include Comparable
|
6
|
+
attr_reader :days
|
7
|
+
|
5
8
|
def initialize(days)
|
6
9
|
@days = days
|
7
10
|
end
|
8
11
|
|
12
|
+
def <=>(other)
|
13
|
+
if other.class != self.class
|
14
|
+
raise ArgumentError.new("#{self.class} can't be compared with #{other.class}")
|
15
|
+
end
|
16
|
+
self.days <=> other.days
|
17
|
+
end
|
18
|
+
|
9
19
|
def after(time = Time.current)
|
10
20
|
days = @days
|
11
21
|
while days > 0 || !time.workday?
|
12
22
|
days -= 1 if time.workday?
|
13
|
-
time
|
23
|
+
time += 1.day
|
24
|
+
end
|
25
|
+
# If we have a Time or DateTime object, we can roll_forward to the
|
26
|
+
# beginning of the next business day
|
27
|
+
if time.is_a?(Time) || time.is_a?(DateTime)
|
28
|
+
time = Time.roll_forward(time) unless time.during_business_hours?
|
14
29
|
end
|
15
30
|
time
|
16
31
|
end
|
@@ -22,7 +37,14 @@ module BusinessTime
|
|
22
37
|
days = @days
|
23
38
|
while days > 0 || !time.workday?
|
24
39
|
days -= 1 if time.workday?
|
25
|
-
time
|
40
|
+
time -= 1.day
|
41
|
+
end
|
42
|
+
# If we have a Time or DateTime object, we can roll_backward to the
|
43
|
+
# beginning of the previous business day
|
44
|
+
if time.is_a?(Time) || time.is_a?(DateTime)
|
45
|
+
unless time.during_business_hours?
|
46
|
+
time = Time.beginning_of_workday(Time.roll_backward(time))
|
47
|
+
end
|
26
48
|
end
|
27
49
|
time
|
28
50
|
end
|
@@ -1,10 +1,20 @@
|
|
1
1
|
module BusinessTime
|
2
2
|
|
3
3
|
class BusinessHours
|
4
|
+
include Comparable
|
5
|
+
attr_reader :hours
|
6
|
+
|
4
7
|
def initialize(hours)
|
5
8
|
@hours = hours
|
6
9
|
end
|
7
10
|
|
11
|
+
def <=>(other)
|
12
|
+
if other.class != self.class
|
13
|
+
raise ArgumentError.new("#{self.class.to_s} can't be compared with #{other.class.to_s}")
|
14
|
+
end
|
15
|
+
self.hours <=> other.hours
|
16
|
+
end
|
17
|
+
|
8
18
|
def ago
|
9
19
|
Time.zone ? before(Time.zone.now) : before(Time.now)
|
10
20
|
end
|
data/lib/business_time/config.rb
CHANGED
@@ -20,13 +20,27 @@ module BusinessTime
|
|
20
20
|
private
|
21
21
|
|
22
22
|
def config
|
23
|
+
return local_config if local_config?
|
23
24
|
Thread.main[:business_time_config] ||= default_config
|
24
25
|
end
|
25
26
|
|
26
27
|
def config=(config)
|
28
|
+
return self.local_config = config if local_config?
|
27
29
|
Thread.main[:business_time_config] = config
|
28
30
|
end
|
29
31
|
|
32
|
+
def local_config
|
33
|
+
Thread.current[:business_time_local_config]
|
34
|
+
end
|
35
|
+
|
36
|
+
def local_config=(config)
|
37
|
+
Thread.current[:business_time_local_config] = config
|
38
|
+
end
|
39
|
+
|
40
|
+
def local_config?
|
41
|
+
!local_config.nil?
|
42
|
+
end
|
43
|
+
|
30
44
|
def threadsafe_cattr_accessor(name)
|
31
45
|
define_singleton_method name do
|
32
46
|
config[name]
|
@@ -131,11 +145,11 @@ module BusinessTime
|
|
131
145
|
end
|
132
146
|
|
133
147
|
def with(config)
|
134
|
-
|
148
|
+
self.local_config = config().dup
|
135
149
|
config.each { |k,v| send("#{k}=", v) } # calculations are done on setting
|
136
150
|
yield
|
137
151
|
ensure
|
138
|
-
self.
|
152
|
+
self.local_config = nil
|
139
153
|
end
|
140
154
|
|
141
155
|
def default_config
|
@@ -154,7 +168,8 @@ module BusinessTime
|
|
154
168
|
end
|
155
169
|
|
156
170
|
def reset
|
157
|
-
self.config
|
171
|
+
self.config = default_config
|
172
|
+
self.local_config = nil
|
158
173
|
end
|
159
174
|
|
160
175
|
def deep_dup(object)
|
@@ -2,11 +2,15 @@
|
|
2
2
|
class Date
|
3
3
|
include BusinessTime::TimeExtensions
|
4
4
|
|
5
|
-
def business_days_until(to_date)
|
6
|
-
business_dates_until(to_date).size
|
5
|
+
def business_days_until(to_date, inclusive = false)
|
6
|
+
business_dates_until(to_date, inclusive).size
|
7
7
|
end
|
8
8
|
|
9
|
-
def business_dates_until(to_date)
|
10
|
-
|
9
|
+
def business_dates_until(to_date, inclusive = false)
|
10
|
+
if inclusive
|
11
|
+
(self..to_date).select(&:workday?)
|
12
|
+
else
|
13
|
+
(self...to_date).select(&:workday?)
|
14
|
+
end
|
11
15
|
end
|
12
|
-
end
|
16
|
+
end
|
@@ -98,6 +98,16 @@ module BusinessTime
|
|
98
98
|
prev_business_time
|
99
99
|
end
|
100
100
|
|
101
|
+
# Returns the time parameter itself if it is a business day
|
102
|
+
# or else returns the previous business day
|
103
|
+
def previous_business_day(time)
|
104
|
+
while !time.workday?
|
105
|
+
time = time - 1.day
|
106
|
+
end
|
107
|
+
|
108
|
+
time
|
109
|
+
end
|
110
|
+
|
101
111
|
def work_hours_total(day)
|
102
112
|
return 0 unless day.workday?
|
103
113
|
|
@@ -159,7 +169,7 @@ module BusinessTime
|
|
159
169
|
first_day + days_in_between + last_day
|
160
170
|
end * direction
|
161
171
|
end
|
162
|
-
|
172
|
+
|
163
173
|
def during_business_hours?
|
164
174
|
self.workday? && self.to_i.between?(Time.beginning_of_workday(self).to_i, Time.end_of_workday(self).to_i)
|
165
175
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: business_time
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bokmann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -96,7 +96,7 @@ dependencies:
|
|
96
96
|
version: '0'
|
97
97
|
description: Have you ever wanted to do things like "6.business_days.from_now" and
|
98
98
|
have weekends and holidays taken into account? Now you can.
|
99
|
-
email: dbock@
|
99
|
+
email: dbock@javaguy.org
|
100
100
|
executables: []
|
101
101
|
extensions: []
|
102
102
|
extra_rdoc_files: []
|
@@ -137,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
137
|
version: '0'
|
138
138
|
requirements: []
|
139
139
|
rubyforge_project:
|
140
|
-
rubygems_version: 2.
|
140
|
+
rubygems_version: 2.4.5
|
141
141
|
signing_key:
|
142
142
|
specification_version: 4
|
143
143
|
summary: Support for doing time math in business hours and days
|