gb_work_day 0.0.1
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 +7 -0
- data/.gitignore +14 -0
- data/.idea/.name +1 -0
- data/.idea/encodings.xml +6 -0
- data/.idea/gb_working_day.iml +239 -0
- data/.idea/misc.xml +14 -0
- data/.idea/modules.xml +8 -0
- data/.idea/runConfigurations/specs.xml +33 -0
- data/.idea/workspace.xml +1333 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +119 -0
- data/Rakefile +2 -0
- data/gb_work_day.gemspec +26 -0
- data/lib/gb_work_day.rb +12 -0
- data/lib/gb_work_day/core_ext.rb +3 -0
- data/lib/gb_work_day/core_ext/date.rb +59 -0
- data/lib/gb_work_day/core_ext/integer.rb +8 -0
- data/lib/gb_work_day/core_ext/time.rb +60 -0
- data/lib/gb_work_day/duration.rb +107 -0
- data/lib/gb_work_day/helpers/date.rb +33 -0
- data/lib/gb_work_day/helpers/time.rb +33 -0
- data/lib/gb_work_day/interval.rb +55 -0
- data/lib/gb_work_day/version.rb +3 -0
- data/lib/gb_work_day/work_week.rb +58 -0
- data/spec/core_ext/date_spec.rb +66 -0
- data/spec/core_ext/integer_spec.rb +28 -0
- data/spec/core_ext/time_spec.rb +66 -0
- data/spec/duration_spec.rb +104 -0
- data/spec/helpers/date_spec.rb +56 -0
- data/spec/helpers/time_spec.rb +50 -0
- data/spec/interval_spec.rb +19 -0
- data/spec/spec_helper.rb +106 -0
- data/spec/work_week_spec.rb +122 -0
- metadata +157 -0
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 Kacper Kawecki
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
# GBWorkDay
|
2
|
+
|
3
|
+
Library to make calculation on work days.
|
4
|
+
Unlike others libraries like [`business_time`](https://github.com/bokmann/business_time),
|
5
|
+
[`working_hours`](https://github.com/Intrepidd/working_hours), [`biz`](https://github.com/zendesk/biz)
|
6
|
+
it operates on whole days, not hours.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'gb_work_day'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install gb_work_day
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
### Work week
|
27
|
+
|
28
|
+
Set default work week for current thread
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
beginning_of_week = 1 #Monday
|
32
|
+
work_days = 5 #wrokd days are Monday-Friday
|
33
|
+
GBWorkDay::WorkWeek.current = GBWorkWeek.new(work_days, beginning_of_week)
|
34
|
+
```
|
35
|
+
|
36
|
+
or if you want to setup per instance
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
beginning_of_week = 1 #Monday
|
40
|
+
work_days = 5 #wrokd days are Monday-Friday
|
41
|
+
week = GBWorkWeek.new(work_days, beginning_of_week)
|
42
|
+
my_date = Date.today.to_work_date(week)
|
43
|
+
```
|
44
|
+
|
45
|
+
or
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
beginning_of_week = 1 #Monday
|
49
|
+
work_days = 5 #wrokd days are Monday-Friday
|
50
|
+
week = GBWorkWeek.new(work_days, beginning_of_week)
|
51
|
+
my_date = my_date
|
52
|
+
#some code here
|
53
|
+
my_date.week = week
|
54
|
+
```
|
55
|
+
|
56
|
+
### Date and Time operation
|
57
|
+
|
58
|
+
Check if today is a work day
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
Date.today.work?
|
62
|
+
```
|
63
|
+
|
64
|
+
or
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
Time.now.work?
|
68
|
+
```
|
69
|
+
|
70
|
+
Check if today is holiday
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
Date.today.free?
|
74
|
+
```
|
75
|
+
|
76
|
+
or
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
Time.now.free?
|
80
|
+
```
|
81
|
+
|
82
|
+
Get next working day
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
Date.today.next_work_day
|
86
|
+
```
|
87
|
+
|
88
|
+
or
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
Time.now.next_work_day
|
92
|
+
```
|
93
|
+
|
94
|
+
|
95
|
+
You can also make more complicated calculations
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
delivery_date = Date.today + 10.work_days
|
99
|
+
```
|
100
|
+
|
101
|
+
or
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
amount_of_work = (start_date.to_work_date - end_date).work_days
|
105
|
+
```
|
106
|
+
|
107
|
+
## Contributing
|
108
|
+
|
109
|
+
1. Fork it ( https://github.com/GenieBelt/gb-works-day/fork )
|
110
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
111
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
112
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
113
|
+
5. Create a new Pull Request
|
114
|
+
|
115
|
+
## Alternatives
|
116
|
+
|
117
|
+
* [`business_time`](https://github.com/bokmann/business_time)
|
118
|
+
* [`working_hours`](https://github.com/Intrepidd/working_hours)
|
119
|
+
* [`biz`](https://github.com/zendesk/biz)
|
data/Rakefile
ADDED
data/gb_work_day.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gb_work_day/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'gb_work_day'
|
8
|
+
spec.version = GBWorkDay::VERSION
|
9
|
+
spec.authors = ['Kacper Kawecki']
|
10
|
+
spec.email = ['kacper@geniebelt.com']
|
11
|
+
spec.summary = %q{Library extending Time and Date to do calculations for work days}
|
12
|
+
spec.description = %q{Library extending Time and Date to do calculations for work days. Unlike others libraries it operates on whole days, not hours.}
|
13
|
+
spec.homepage = 'https://github.com/GenieBelt/gb-works-day'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
23
|
+
spec.add_development_dependency 'rspec'
|
24
|
+
spec.add_development_dependency 'simplecov'
|
25
|
+
spec.add_development_dependency 'activesupport'
|
26
|
+
end
|
data/lib/gb_work_day.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'gb_work_day/version'
|
2
|
+
require 'gb_work_day/core_ext'
|
3
|
+
require 'gb_work_day/duration'
|
4
|
+
require 'gb_work_day/interval'
|
5
|
+
require 'gb_work_day/work_week'
|
6
|
+
require 'gb_work_day/helpers/date'
|
7
|
+
require 'gb_work_day/helpers/time'
|
8
|
+
|
9
|
+
|
10
|
+
module GBWorkDay
|
11
|
+
# Your code goes here...
|
12
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'gb_work_day/duration'
|
2
|
+
require 'gb_work_day/helpers/date'
|
3
|
+
class Date
|
4
|
+
def plus_with_work_duration(other)
|
5
|
+
if GBWorkDay::Duration === other
|
6
|
+
other.since(self)
|
7
|
+
else
|
8
|
+
plus_without_work_duration(other)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
alias_method :plus_without_work_duration, :+
|
12
|
+
alias_method :+, :plus_with_work_duration
|
13
|
+
|
14
|
+
def minus_with_work_duration(other)
|
15
|
+
if GBWorkDay::Duration === other
|
16
|
+
plus_with_work_duration(- other)
|
17
|
+
elsif GBWorkDay::Date === other
|
18
|
+
other - self
|
19
|
+
else
|
20
|
+
minus_without_work_duration(other)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
alias_method :minus_without_work_duration, :-
|
24
|
+
alias_method :-, :minus_with_work_duration
|
25
|
+
|
26
|
+
# Check if it is a work day.
|
27
|
+
# @return [boolean]
|
28
|
+
def work?
|
29
|
+
default_week.work_day? self
|
30
|
+
end
|
31
|
+
|
32
|
+
# Check if it is a work day.
|
33
|
+
# @return [boolean]
|
34
|
+
def free?
|
35
|
+
default_week.free_day? self
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return next working day
|
39
|
+
# @return [Time]
|
40
|
+
def next_work_day
|
41
|
+
self + GBWorkDay::Duration.new(1, default_week)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Get date object for calculating working days
|
45
|
+
#
|
46
|
+
# @param week [GBWorkDay::WorkWeek] if not set, it will use week set globally. For more check {GBWorkingDay::WorkWeek#current}
|
47
|
+
def work_date(week=nil)
|
48
|
+
GBWorkDay::Date.from_date self, week
|
49
|
+
end
|
50
|
+
alias_method :to_work, :work_date
|
51
|
+
alias_method :to_work_date, :work_date
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# @return [GBWorkDay::WorkWeek]
|
56
|
+
def default_week
|
57
|
+
GBWorkDay::WorkWeek.current
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'gb_work_day/duration'
|
2
|
+
require 'gb_work_day/helpers/time'
|
3
|
+
class Time
|
4
|
+
def plus_with_work_duration(other)
|
5
|
+
if GBWorkDay::Duration === other
|
6
|
+
other.since(self)
|
7
|
+
else
|
8
|
+
plus_without_work_duration(other)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
alias_method :plus_without_work_duration, :+
|
12
|
+
alias_method :+, :plus_with_work_duration
|
13
|
+
|
14
|
+
def minus_with_work_duration(other)
|
15
|
+
if GBWorkDay::Duration === other
|
16
|
+
plus_with_work_duration(-other)
|
17
|
+
elsif GBWorkDay::Time === other
|
18
|
+
other - self
|
19
|
+
else
|
20
|
+
minus_without_work_duration(other)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
alias_method :minus_without_work_duration, :-
|
24
|
+
alias_method :-, :minus_with_work_duration
|
25
|
+
|
26
|
+
|
27
|
+
# Check if it is a work day.
|
28
|
+
# @return [boolean]
|
29
|
+
def work?
|
30
|
+
default_week.work_day? self
|
31
|
+
end
|
32
|
+
|
33
|
+
# Check if it is a work day.
|
34
|
+
# @return [boolean]
|
35
|
+
def free?
|
36
|
+
default_week.free_day? self
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return next working day
|
40
|
+
# @return [Time]
|
41
|
+
def next_work_day
|
42
|
+
self + GBWorkDay::Duration.new(1, default_week)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Get time object for calculating working days
|
46
|
+
#
|
47
|
+
# @param week [GBWorkDay::WorkWeek] if not set, it will use week set globally. For more check {GBWorkingDay::WorkWeek#current}
|
48
|
+
def work_time(week=nil)
|
49
|
+
GBWorkDay::Time.from_time self, week
|
50
|
+
end
|
51
|
+
alias_method :to_work, :work_time
|
52
|
+
alias_method :to_work_time, :work_time
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# @return [GBWorkDay::WorkWeek]
|
57
|
+
def default_week
|
58
|
+
GBWorkDay::WorkWeek.current
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'gb_work_day/work_week'
|
2
|
+
module GBWorkDay
|
3
|
+
class Duration
|
4
|
+
SEC_IN_DAY = 86400
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
attr_accessor :work_days, :week
|
8
|
+
def initialize(days, week=nil)
|
9
|
+
@work_days = days
|
10
|
+
@week = week || WorkWeek.current
|
11
|
+
end
|
12
|
+
|
13
|
+
def +(other) # :nodoc:
|
14
|
+
if Duration === other
|
15
|
+
Duration.new(work_days + other.work_days, week)
|
16
|
+
else
|
17
|
+
Duration.new(work_days + other, week)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def -(other) # :nodoc:
|
22
|
+
self + (-other)
|
23
|
+
end
|
24
|
+
|
25
|
+
def -@ # :nodoc:
|
26
|
+
Duration.new(-work_days, week)
|
27
|
+
end
|
28
|
+
|
29
|
+
def is_a?(klass) # :nodoc:
|
30
|
+
Duration == klass || work_days.is_a?(klass)
|
31
|
+
end
|
32
|
+
alias :kind_of? :is_a?
|
33
|
+
|
34
|
+
def instance_of?(klass) # :nodoc:
|
35
|
+
Duration == klass || work_days.instance_of?(klass)
|
36
|
+
end
|
37
|
+
|
38
|
+
def ==(other) # :nodoc:
|
39
|
+
if Duration === other
|
40
|
+
other.work_days == work_days && other.week == week
|
41
|
+
else
|
42
|
+
other == work_days
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the amount of seconds a duration covers as a string.
|
47
|
+
# For more information check to_i method.
|
48
|
+
#
|
49
|
+
# 1.work_day.to_s # => "86400"
|
50
|
+
def to_s
|
51
|
+
to_i.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns the number of seconds that this Duration represents.
|
55
|
+
def to_i(format = :seconds)
|
56
|
+
if format == :days
|
57
|
+
work_days
|
58
|
+
else
|
59
|
+
work_days * SEC_IN_DAY
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
# Returns +true+ if +other+ is also a Duration instance, which has the
|
65
|
+
# same parts as this one.
|
66
|
+
def eql?(other)
|
67
|
+
Duration === other && other.work_days.eql?(work_days) && other.week.eql?(week)
|
68
|
+
end
|
69
|
+
|
70
|
+
def inspect #:nodoc:
|
71
|
+
"#{self.work_days} working days in a working week: #{week}"
|
72
|
+
end
|
73
|
+
|
74
|
+
# Calculates a new Time or Date that is as far in the future
|
75
|
+
# as this Duration represents.
|
76
|
+
def since(time = ::Time.current)
|
77
|
+
sum(1, time)
|
78
|
+
end
|
79
|
+
alias :from_now :since
|
80
|
+
|
81
|
+
# Calculates a new Time or Date that is as far in the past
|
82
|
+
# as this Duration represents.
|
83
|
+
def ago(time = ::Time.current)
|
84
|
+
sum(-1, time)
|
85
|
+
end
|
86
|
+
alias :until :ago
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def sum(symbol, time)
|
91
|
+
work_days_left = self.work_days
|
92
|
+
if work_days_left < 0
|
93
|
+
symbol *= -1
|
94
|
+
work_days_left *= -1
|
95
|
+
end
|
96
|
+
while work_days_left > 0
|
97
|
+
if time.is_a? ::Date
|
98
|
+
time += symbol * 1
|
99
|
+
else
|
100
|
+
time += (symbol * SEC_IN_DAY)
|
101
|
+
end
|
102
|
+
work_days_left -= 1 if @week.work_day? time
|
103
|
+
end
|
104
|
+
time
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|