time_pieces 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8dff9eff972d3afdaf7b581ed5a1523d6322ca96
4
+ data.tar.gz: 04cd28f75eadad0881be6e136b6f1ce30ba58348
5
+ SHA512:
6
+ metadata.gz: 271412cccca93941de02b4de970b7ac9caddc49a9f2356fea5bec374ae81d2433f79f57336f3874bb50595f3e9c122ca4e03e3c929bcca42d10b4ca0784775e6
7
+ data.tar.gz: 33efeab9c9575ec061703f737ea51bfc814b6a7b42351c5cd81e7e89e71ab99bc9c804097a45718f0ed49fd4e0795f41f4d7f5e5923eb41790bfa49b1d088f9a
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
3
+ #group :test do
4
+ # gem "activesupport"
5
+ #
6
+ # gem "rake"
7
+ # gem "cucumber"
8
+ #end
9
+
10
+
11
+
data/Gemfile.lock ADDED
@@ -0,0 +1,50 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ time_pieces (0.2.0)
5
+ bundler
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ activesupport (4.2.5.1)
11
+ i18n (~> 0.7)
12
+ json (~> 1.7, >= 1.7.7)
13
+ minitest (~> 5.1)
14
+ thread_safe (~> 0.3, >= 0.3.4)
15
+ tzinfo (~> 1.1)
16
+ builder (3.2.2)
17
+ cucumber (2.3.2)
18
+ builder (>= 2.1.2)
19
+ cucumber-core (~> 1.4.0)
20
+ cucumber-wire (~> 0.0.1)
21
+ diff-lcs (>= 1.1.3)
22
+ gherkin (~> 3.2.0)
23
+ multi_json (>= 1.7.5, < 2.0)
24
+ multi_test (>= 0.1.2)
25
+ cucumber-core (1.4.0)
26
+ gherkin (~> 3.2.0)
27
+ cucumber-wire (0.0.1)
28
+ diff-lcs (1.2.5)
29
+ gherkin (3.2.0)
30
+ i18n (0.7.0)
31
+ json (1.8.3)
32
+ minitest (5.8.4)
33
+ multi_json (1.11.2)
34
+ multi_test (0.1.2)
35
+ rake (10.5.0)
36
+ thread_safe (0.3.5)
37
+ tzinfo (1.2.2)
38
+ thread_safe (~> 0.1)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ activesupport (~> 4.2)
45
+ cucumber (~> 2.3.2)
46
+ rake (~> 10.5)
47
+ time_pieces!
48
+
49
+ BUNDLED WITH
50
+ 1.10.6
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # TimePieces
2
+
3
+ This gem is for managing time pieces. It lets you add and subtract durations to help you with scheduling. For example if you have a duration (9:00am - 5:00pm) and you subtract the duration (1:00pm - 2:00pm) it will result in a time set with 2 time duration of (9:00am - 1:00pm) and (2:00pm - 5:00pm). You can also add durations. To make an object into a duration just use. You also have to include the method duration_copy which is used when creating new objects, for example when a duration is split.
4
+ ```ruby
5
+ include TimePieces::Duration
6
+
7
+ def duration_copy
8
+ return self.clone
9
+ end
10
+
11
+ ```
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'time_pieces'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install time_pieces
28
+
29
+ <!---
30
+ ## Usage
31
+
32
+ TODO: Write usage instructions here
33
+
34
+ ## Development
35
+
36
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
37
+
38
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
39
+ -->
40
+ ## Contributing
41
+
42
+ Bug reports and pull requests are welcome on GitHub at https://github.com/riggleg/time_pieces
43
+
44
+
45
+ ## License
46
+
47
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
48
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,4 @@
1
+ <%
2
+ std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
3
+ %>
4
+ default: <%= std_opts %> features
@@ -0,0 +1,131 @@
1
+ module TimePieces
2
+ module Duration
3
+ attr_accessor :start_at_seconds, :duration_seconds
4
+ def end_at_seconds
5
+ return start_at_seconds + duration_seconds
6
+ end
7
+ def end_at_seconds=(new_end_at_seconds)
8
+ self.duration_seconds = new_end_at_seconds - start_at_seconds
9
+ end
10
+ def update_start_seconds_and_end_seconds(new_start_seconds, new_end_seconds)
11
+ self.start_at_seconds = new_start_seconds
12
+ self.end_at_seconds = new_end_seconds
13
+ return self
14
+ end
15
+ def left_duration_copy
16
+ duration_copy
17
+ end
18
+ def right_duration_copy
19
+ duration_copy
20
+ end
21
+
22
+
23
+ def overlaps_start?(other_td)
24
+ return true if (start_at_seconds >= other_td.start_at_seconds) && (start_at_seconds < other_td.end_at_seconds)
25
+ return false
26
+ end
27
+ def overlaps_end?(other_td)
28
+ return true if (end_at_seconds <= other_td.end_at_seconds) && (end_at_seconds > other_td.start_at_seconds)
29
+ return false
30
+ end
31
+ def overlaps_inside?(other_td)
32
+ return true if (other_td.end_at_seconds > start_at_seconds) && (other_td.end_at_seconds <= end_at_seconds) && (other_td.start_at_seconds >= start_at_seconds) && (other_td.start_at_seconds < end_at_seconds)
33
+ return false
34
+ end
35
+ def overlaps_outside?(other_td)
36
+ return other_td.overlaps_inside?(self)
37
+ end
38
+ def overlaps?(other_td)
39
+ return true if overlaps_outside?(other_td)
40
+ return true if overlaps_start?(other_td)
41
+ return true if overlaps_end?(other_td)
42
+ return true if overlaps_inside?(other_td)
43
+ return false
44
+ end
45
+ def touches_at_start?(other_td)
46
+ return true if other_td.end_at_seconds == start_at_seconds
47
+ return false
48
+ end
49
+ def touches_at_end?(other_td)
50
+ return true if other_td.start_at_seconds == end_at_seconds
51
+ return false
52
+ end
53
+ def touches?(other_td)
54
+ return (touches_at_start?(other_td) || touches_at_end?(other_td))
55
+ return false
56
+ end
57
+ def <=>(other)
58
+ start_at_seconds <=> other.start_at_seconds
59
+ end
60
+ def +(other_td)
61
+ ts_ret = TimeSet.new
62
+ if overlaps?(other_td)
63
+ if overlaps_start?(other_td) && !overlaps_outside?(other_td)
64
+ update_start_seconds_and_end_seconds(other_td.start_at_seconds, end_at_seconds)
65
+ ts_ret << self
66
+ return ts_ret
67
+ end
68
+ if overlaps_end?(other_td) && !overlaps_outside?(other_td)
69
+
70
+ update_start_seconds_and_end_seconds(start_at_seconds, other_td.end_at_seconds)
71
+ ts_ret << self
72
+ return ts_ret
73
+ end
74
+ if overlaps_inside?(other_td)
75
+ ts_ret << self
76
+ return ts_ret
77
+ end
78
+ if overlaps_outside?(other_td)
79
+ ts_ret << other_td
80
+ end
81
+ return ts_ret
82
+ end
83
+ if touches?(other_td)
84
+ if touches_at_end?(other_td) && other_td.end_at_seconds > end_at_seconds
85
+ update_start_seconds_and_end_seconds(start_at_seconds, other_td.end_at_seconds)
86
+ ts_ret << self
87
+ return ts_ret
88
+ end
89
+ if touches_at_start?(other_td) && other_td.start_at_seconds < start_at_seconds
90
+ update_start_seconds_and_end_seconds(other_td.start_at_seconds, end_at_seconds)
91
+ ts_ret << self
92
+ return ts_ret
93
+ end
94
+ return false
95
+ end
96
+ ts_ret << self
97
+ ts_ret << other_td
98
+ return ts_ret
99
+ end
100
+ def -(other_td)
101
+ ts_ret = TimeSet.new
102
+ unless overlaps?(other_td)
103
+ ts_ret << self
104
+ return ts_ret
105
+ end
106
+ if overlaps?(other_td)
107
+ if overlaps_start?(other_td)
108
+ update_start_seconds_and_end_seconds(other_td.end_at_seconds, end_at_seconds)
109
+ ts_ret << self
110
+ return ts_ret
111
+ end
112
+ if overlaps_end?(other_td)
113
+ puts inspect
114
+ update_start_seconds_and_end_seconds(start_at_seconds, other_td.start_at_seconds)
115
+ puts "RUNNING OVERLAPPING END"
116
+ puts inspect
117
+ ts_ret << self
118
+ return ts_ret
119
+ end
120
+ if overlaps_inside?(other_td)
121
+ left_of_break = left_duration_copy.update_start_seconds_and_end_seconds(start_at_seconds, other_td.start_at_seconds)
122
+ right_of_break = right_duration_copy.update_start_seconds_and_end_seconds(other_td.end_at_seconds, end_at_seconds)
123
+ ts_ret << left_of_break
124
+ ts_ret << right_of_break
125
+ end
126
+ return ts_ret
127
+ end
128
+ end
129
+
130
+ end
131
+ end
@@ -0,0 +1,30 @@
1
+ module TimePieces
2
+ class SimpleDuration
3
+ include TimePieces::Duration
4
+ #Time is measured as seconds since midnight
5
+ def start_at=(s_at)
6
+ self.start_at_seconds = s_at.seconds_since_midnight
7
+ end
8
+ def initialize(start_at_seconds, duration_seconds)
9
+ self.start_at_seconds = start_at_seconds
10
+ self.duration_seconds = duration_seconds
11
+ end
12
+ def self.parse_from_time_string(start_at_str, end_at_str)
13
+ start_at_seconds = Time.parse(start_at_str).seconds_since_midnight
14
+ end_at_seconds = Time.parse(end_at_str).seconds_since_midnight
15
+ return self.new(start_at_seconds, end_at_seconds - start_at_seconds)
16
+ end
17
+ def self.new_using_seconds_and_end_at(start_at_seconds, end_at_seconds)
18
+ return self.new(start_at_seconds, end_at_seconds - start_at_seconds)
19
+ end
20
+ def inspect
21
+ hours_start = start_at_seconds / 60 / 60
22
+ hours_end = end_at_seconds / 60 / 60
23
+ duration = duration_seconds / 60 / 60
24
+ return "TD: #{hours_start} - #{hours_end} time in seconds: #{duration_seconds}"
25
+ end
26
+ def bookable_copy
27
+ return SimpleDuration.new(1,10)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,64 @@
1
+ module TimePieces
2
+ class TimeSet
3
+ attr_accessor :time_durations
4
+ def initialize
5
+ @time_durations = []
6
+ end
7
+ #Adds a new time duration. Removes invalid time durations.
8
+ def <<(new_td)
9
+ if new_td.duration_seconds == 0
10
+
11
+ else
12
+ new_tds = []
13
+ has_combined = false
14
+ time_durations.each do |td|
15
+ if new_td.overlaps?(td) || new_td.touches?(td)
16
+ combined_td = td + new_td
17
+ combined_td.time_durations.each do |td3|
18
+ new_tds << td3
19
+ end
20
+ has_combined = true
21
+ else
22
+ new_tds << td
23
+ end
24
+ end
25
+ new_tds << new_td unless has_combined
26
+ self.time_durations = new_tds
27
+ end
28
+ return self
29
+ end
30
+ def >>(subtracting_td)
31
+ new_tds = []
32
+ time_durations.each do |td|
33
+ if subtracting_td.overlaps?(td)
34
+ combined_td = td - subtracting_td
35
+ combined_td.time_durations.each do |td3|
36
+ new_tds << td3
37
+ end
38
+ else
39
+ new_tds << td
40
+ end
41
+
42
+ end
43
+ self.time_durations = new_tds
44
+ return self
45
+ end
46
+ def +(other_ts)
47
+ ret_ts = TimeSet.new
48
+ ret_ts.time_durations = time_durations.map{|td| td}
49
+ other_ts.time_durations.each do |td|
50
+ ret_ts << td
51
+ end
52
+ return ret_ts
53
+ end
54
+ def -(other_ts)
55
+ ret_ts = TimeSet.new
56
+ ret_ts.time_durations = Array.new(time_durations)
57
+ other_ts.time_durations.each do |td|
58
+ ret_ts >> td
59
+ end
60
+ return ret_ts
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ module TimePieces
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,9 @@
1
+ require 'active_support/all'
2
+ #lib = File.expand_path('../lib/', __FILE__)
3
+ lib = File.expand_path('.', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'time_pieces/version'
6
+ require 'time_pieces/duration'
7
+
8
+ require 'time_pieces/simple_duration'
9
+ require 'time_pieces/time_set'
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib/', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'time_pieces/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+
8
+ spec.name = "time_pieces"
9
+ spec.version = TimePieces::VERSION
10
+ spec.license = "MIT"
11
+ spec.authors = ["Grant R."]
12
+ spec.email = "grant@arsemporium.com"
13
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
14
+ spec.bindir = "exe"
15
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
16
+ spec.require_paths = ["lib"]
17
+ spec.homepage = "http://github.com/riggleg/time_pieces"
18
+ spec.summary = "Time based operations."
19
+ spec.description = "time_pieces is a library to make it easy to add/subtract time from a schedule"
20
+
21
+ # s.files = `git ls-files -- lib/*`.split("\n")
22
+ # s.files += %w[README.md LICENSE.md Changelog.md Capybara.md .yardopts .document]
23
+ # s.test_files = []
24
+ # s.require_path = "lib"
25
+
26
+ # private_key = File.expand_path('~/.gem/rspec-gem-private_key.pem')
27
+ # if File.exist?(private_key)
28
+ # s.signing_key = private_key
29
+ # s.cert_chain = [File.expand_path('~/.gem/rspec-gem-public_cert.pem')]
30
+ # end
31
+
32
+
33
+ # if RUBY_VERSION <= '1.8.7' && ENV['RAILS_VERSION'] != '3-2-stable'
34
+ # version_string << '!= 3.2.22.1'
35
+ # end
36
+ spec.add_dependency 'bundler'
37
+ spec.add_development_dependency %q<activesupport>, '~> 4.2'
38
+
39
+ spec.add_development_dependency 'rake', '~> 10.5'
40
+ spec.add_development_dependency 'cucumber', '~> 2.3.2'
41
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: time_pieces
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Grant R.
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-02-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: cucumber
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.3.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.3.2
69
+ description: time_pieces is a library to make it easy to add/subtract time from a
70
+ schedule
71
+ email: grant@arsemporium.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - Gemfile
77
+ - Gemfile.lock
78
+ - README.md
79
+ - Rakefile
80
+ - config/cucumber.yml
81
+ - lib/time_pieces.rb
82
+ - lib/time_pieces/duration.rb
83
+ - lib/time_pieces/simple_duration.rb
84
+ - lib/time_pieces/time_set.rb
85
+ - lib/time_pieces/version.rb
86
+ - time_pieces.gemspec
87
+ homepage: http://github.com/riggleg/time_pieces
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.4.6
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Time based operations.
111
+ test_files: []