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.
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