gb_work_day 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gb_work_day.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'rspec'
8
+ gem 'simplecov', :require => false
9
+ gem 'activesupport', :require => false
10
+ end
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
@@ -0,0 +1,2 @@
1
+ require 'bundler/gem_tasks'
2
+
@@ -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
@@ -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,3 @@
1
+ require 'gb_work_day/core_ext/integer'
2
+ require 'gb_work_day/core_ext/date'
3
+ require 'gb_work_day/core_ext/time'
@@ -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,8 @@
1
+ require 'gb_work_day/duration'
2
+ class Integer
3
+ def work_days(week=nil)
4
+ GBWorkDay::Duration.new(self, week)
5
+ end
6
+
7
+ alias work_day work_days
8
+ 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