day_time 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 234dac2965a6a05a5d77af3cee675150d82d6d7d
4
+ data.tar.gz: 37adfab09cc9bead706eb5be4c6cb30864d4c0bb
5
+ SHA512:
6
+ metadata.gz: 638877ffbbdf94eb69378f67222ae6ff60f2db77f83456ce5fdec6f70e5fa1a896601b9995342286c4717dca8dc9c8dbd184b7ddb59986218799e64a26dd1780
7
+ data.tar.gz: 822d289367830714c8d5ab7e8b0e9475edb790b6d4fb1e6dbe66fc480248d8664b2364a2e04bc64273abea3528128975c6d4315a43690dc69fd941a810371849
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,32 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ day_time (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.5)
10
+ rspec (3.3.0)
11
+ rspec-core (~> 3.3.0)
12
+ rspec-expectations (~> 3.3.0)
13
+ rspec-mocks (~> 3.3.0)
14
+ rspec-core (3.3.2)
15
+ rspec-support (~> 3.3.0)
16
+ rspec-expectations (3.3.1)
17
+ diff-lcs (>= 1.2.0, < 2.0)
18
+ rspec-support (~> 3.3.0)
19
+ rspec-mocks (3.3.2)
20
+ diff-lcs (>= 1.2.0, < 2.0)
21
+ rspec-support (~> 3.3.0)
22
+ rspec-support (3.3.0)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ day_time!
29
+ rspec (~> 3.1)
30
+
31
+ BUNDLED WITH
32
+ 1.10.2
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Dominic Bauer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,45 @@
1
+ # day_time
2
+ 24-hour time representation with no dates attached
3
+
4
+ ## Installation
5
+ Install with Bundler by adding the following line to your `Gemfile`:
6
+
7
+ ```
8
+ gem "day_time"
9
+ ```
10
+ Or install via RubyGems:
11
+
12
+ ```
13
+ % gem install day_time
14
+ ```
15
+
16
+ ## Usage
17
+ ```ruby
18
+ require "day_time"
19
+
20
+ morning = DayTime.new("08:00")
21
+ breakfast = DayTime.new("08:45:00")
22
+ noon = DayTime.new(hours: 12, minutes: 15)
23
+ dinner = DayTime.new(hours: 12, minutes: 15, seconds: 30)
24
+ bedtime = DayTime.new(h: 22, m: 15, s: 30)
25
+ end_of_day = DayTime("23:59:59")
26
+
27
+ foo = DayTime.new(Time.new(...))
28
+ bar = DayTime.new(DateTime.new(...))
29
+
30
+ morning + DayTime.new("00:45") == breakfast
31
+ morning + 45 * 60 == breakfast
32
+ morning + "00:45" == breakfast
33
+
34
+ dinner < bedtime
35
+ end_of_day > bedtime
36
+
37
+ (noon..bedtime).include?(dinner) # => true
38
+
39
+ enum = end_of_day.to_enum
40
+ enum.next == DayTime.new("00:00")
41
+ enum.next == DayTime.new("00:00:01")
42
+
43
+ opens, closes = DayTime("10:00"), DayTime("17:00")
44
+ (opens..closes).step(60).map { |day_time| day_time.to_s }
45
+ ```
@@ -0,0 +1,8 @@
1
+ require "rspec/core/rake_task"
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ desc "Build the RubyGem"
6
+ task :build do
7
+ sh "gem build day_time.gemspec --verbose"
8
+ end
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "day_time"
3
+ s.version = "0.0.1"
4
+
5
+ s.summary = <<-summary
6
+ Day time calculations
7
+ summary
8
+
9
+ s.authors = ["Dominic Bauer"]
10
+ s.email = "bauerdominic@gmail.com"
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- spec/*`.split("\n")
14
+
15
+ s.homepage = "https://github.com/bauerd/day_time"
16
+ s.license = "MIT"
17
+
18
+ s.add_development_dependency "rspec", "~> 3.1"
19
+ end
@@ -0,0 +1,124 @@
1
+ require "date"
2
+
3
+ class DayTime
4
+ include Enumerable
5
+ include Comparable
6
+
7
+ SECONDS_PER_DAY = 86_399
8
+
9
+ HM_REGEXP = /^(2[0-3]|[01]?[0-9]):([0-5]?[0-9])$/i
10
+ HMS_REGEXP = /^(2[0-3]|[01]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])$/i
11
+
12
+ attr_reader :seconds_since_midnight
13
+
14
+ def initialize(arg)
15
+ @seconds_since_midnight = case arg
16
+ when self.class
17
+ arg.seconds_since_midnight
18
+ when Time
19
+ seconds_from_time(arg)
20
+ when DateTime
21
+ seconds_from_time(arg.to_time)
22
+ when Integer
23
+ seconds_from_integer(arg)
24
+ when String
25
+ seconds_from_time_string(arg)
26
+ when Hash
27
+ seconds_from_hash(arg)
28
+ else
29
+ raise ArgumentError
30
+ end
31
+ end
32
+
33
+ def hours
34
+ @seconds_since_midnight / (60 ** 2)
35
+ end
36
+
37
+ def minutes
38
+ (@seconds_since_midnight % 60 ** 2) / 60
39
+ end
40
+
41
+ def seconds
42
+ @seconds_since_midnight % 60
43
+ end
44
+
45
+ def <=>(other)
46
+ seconds_since_midnight <=> other.seconds_since_midnight
47
+ end
48
+
49
+ def succ
50
+ self + 1
51
+ end
52
+
53
+ def each
54
+ 1.upto(Float::INFINITY) { |i| yield self + i }
55
+ end
56
+
57
+ def +(obj)
58
+ other = DayTime.new(obj)
59
+ DayTime.new(@seconds_since_midnight + other.seconds_since_midnight)
60
+ end
61
+
62
+ def -(obj)
63
+ other = DayTime.new(obj)
64
+ DayTime.new((@seconds_since_midnight - other.seconds_since_midnight).abs)
65
+ end
66
+
67
+ def to_s
68
+ [hours, minutes, seconds].map { |int| int.to_s.rjust(2, "0") }.join(":")
69
+ end
70
+
71
+ def to_i
72
+ @seconds_since_midnight
73
+ end
74
+
75
+ private
76
+
77
+ def seconds_from_integer(seconds_since_midnight)
78
+ if seconds_since_midnight > SECONDS_PER_DAY
79
+ (seconds_since_midnight % SECONDS_PER_DAY) - 1
80
+ else
81
+ seconds_since_midnight
82
+ end
83
+ end
84
+
85
+ def seconds_from_time_string(str)
86
+ h, m, s = if match = str.match(HMS_REGEXP)
87
+ match.captures.map(&:to_i)
88
+ elsif match = str.match(HM_REGEXP)
89
+ match.captures.map(&:to_i) << 0
90
+ else
91
+ raise ArgumentError
92
+ end
93
+
94
+ seconds_from_hash(h: h, m: m, s: s)
95
+ end
96
+
97
+ def seconds_from_hash(hash)
98
+ [[:hours, :h], [:minutes, :m]].each do |keys|
99
+ unless keys.any? { |key| hash.key?(key) }
100
+ raise ArgumentError(
101
+ "Either a `#{keys[0]}` or `#{keys[2]} key is required"
102
+ )
103
+ end
104
+ end
105
+
106
+ h = hash[:hours] || hash[:h]
107
+ m = hash[:minutes] || hash[:m]
108
+ s = hash[:seconds] || hash[:s] || 0
109
+
110
+ seconds_from_integer(h * 60 ** 2 + m * 60 + s)
111
+ end
112
+
113
+ def seconds_from_time(time)
114
+ seconds_from_hash(
115
+ h: time.hour,
116
+ m: time.min,
117
+ s: time.sec
118
+ )
119
+ end
120
+ end
121
+
122
+ def DayTime(*argv)
123
+ DayTime.new(*argv)
124
+ end
@@ -0,0 +1,240 @@
1
+ require "day_time"
2
+
3
+ describe DayTime do
4
+ describe "Kernel#DayTime" do
5
+ it "proxies calls" do
6
+ expect(DayTime("08:00")).to eq DayTime.new("08:00")
7
+ end
8
+ end
9
+
10
+ describe "#initialize" do
11
+ context "with other DayTime" do
12
+ it "returns a new DayTime" do
13
+ day_time = DayTime.new("08:00")
14
+ expect(DayTime.new(day_time)).to eq day_time
15
+ end
16
+ end
17
+
18
+ context "with seconds since midnight" do
19
+ it "sets hours, minutes and seconds" do
20
+ day_time = DayTime.new(20_066) # 05:34:25
21
+
22
+ expect(day_time.hours).to eq 5
23
+ expect(day_time.minutes).to eq 34
24
+ expect(day_time.seconds).to eq 26
25
+
26
+ expect(day_time.seconds_since_midnight).to be 20_066
27
+ end
28
+
29
+ it "sets hours, minutes and seconds" do
30
+ day_time = DayTime.new(0) # 00:00:00
31
+
32
+ expect(day_time.hours).to eq 0
33
+ expect(day_time.minutes).to eq 0
34
+ expect(day_time.seconds).to eq 0
35
+
36
+ expect(day_time.seconds_since_midnight).to be 0
37
+ end
38
+
39
+ it "sets hours, minutes and seconds" do
40
+ day_time = DayTime.new(86_399) # 23:59:59
41
+
42
+ expect(day_time.hours).to eq 23
43
+ expect(day_time.minutes).to eq 59
44
+ expect(day_time.seconds).to eq 59
45
+
46
+ expect(day_time.seconds_since_midnight).to be 86_399
47
+ end
48
+
49
+ it "sets hours, minutes and seconds" do
50
+ day_time = DayTime.new(86_400) # 00:00:00
51
+
52
+ expect(day_time.hours).to eq 0
53
+ expect(day_time.minutes).to eq 0
54
+ expect(day_time.seconds).to eq 0
55
+
56
+ expect(day_time.seconds_since_midnight).to be 0
57
+ end
58
+
59
+ context "with overflowing seconds" do
60
+ it "starts over at midnight" do
61
+ day_time = DayTime.new(96_685) # 26:51:25 <-> 02:51:25
62
+
63
+ expect(day_time.hours).to eq 2
64
+ expect(day_time.minutes).to eq 51
65
+ expect(day_time.seconds).to eq 25
66
+
67
+ expect(day_time.seconds_since_midnight).to be 10_285
68
+ end
69
+ end
70
+ end
71
+
72
+ context "with hh:mm string" do
73
+ it "sets hours and minutes" do
74
+ day_time = DayTime.new("12:31")
75
+
76
+ expect(day_time.hours).to be 12
77
+ expect(day_time.minutes).to be 31
78
+ expect(day_time.seconds).to be 0
79
+ end
80
+ end
81
+
82
+ context "with hh:mm:ss string" do
83
+ it "sets hours, minutes and seconds" do
84
+ day_time = DayTime.new("12:31:22")
85
+
86
+ expect(day_time.hours).to be 12
87
+ expect(day_time.minutes).to be 31
88
+ expect(day_time.seconds).to be 22
89
+ end
90
+ end
91
+
92
+ context "with malformed string" do
93
+ it "raises an ArgumentError" do
94
+ expect {
95
+ DayTime.new("Y2:X1")
96
+ }.to raise_error(ArgumentError)
97
+ end
98
+ end
99
+
100
+ context "with hours-minutes-keyed Hash" do
101
+ it "sets hours and minutes" do
102
+ day_time = DayTime.new(hours: 13, minutes: 55)
103
+
104
+ expect(day_time.hours).to be 13
105
+ expect(day_time.minutes).to be 55
106
+ expect(day_time.seconds).to be 00
107
+ end
108
+ end
109
+
110
+ context "with hours-minutes-seconds-keyed Hash" do
111
+ it "sets hours, minutes and seconds" do
112
+ day_time = DayTime.new(hours: 13, minutes: 55, seconds: 45)
113
+
114
+ expect(day_time.hours).to be 13
115
+ expect(day_time.minutes).to be 55
116
+ expect(day_time.seconds).to be 45
117
+ end
118
+ end
119
+
120
+ context "with Time" do
121
+ it "sets hours, minutes and seconds" do
122
+ time = Time.new(2020, 10, 10, 18, 30, 45) # 18:30:45
123
+ day_time = DayTime.new(time)
124
+
125
+ expect(day_time.hours).to be 18
126
+ expect(day_time.minutes).to be 30
127
+ expect(day_time.seconds).to be 45
128
+ end
129
+ end
130
+
131
+ context "with DateTime" do
132
+ it "sets hours, minutes and seconds" do
133
+ date_time = DateTime.new(2020, 10, 10, 18, 30, 45, "+2") # 18:30:45
134
+ day_time = DayTime.new(date_time)
135
+
136
+ expect(day_time.hours).to be 18
137
+ expect(day_time.minutes).to be 30
138
+ expect(day_time.seconds).to be 45
139
+ end
140
+ end
141
+ end
142
+
143
+ describe "#==" do
144
+ it "compares by seconds since midnight" do
145
+ a = DayTime.new("08:00")
146
+ b = DayTime.new("08:00")
147
+
148
+ expect(a == b).to be true
149
+ end
150
+ end
151
+
152
+ describe "#seconds_since_midnight" do
153
+ it "returns the seconds since midnight" do
154
+ day_time = DayTime.new("04:22:44")
155
+ expect(day_time.seconds_since_midnight).to be 15_764
156
+ end
157
+ end
158
+
159
+ describe "#<=>" do
160
+ let(:morning) { DayTime.new("08:00") }
161
+ let(:noon) { DayTime.new("12:00") }
162
+ let(:evening) { DayTime.new("20:00") }
163
+
164
+ it "compares by seconds since midnight" do
165
+ expect(morning < evening).to be true
166
+ end
167
+
168
+ it "supports ranges" do
169
+ expect(morning..evening).to include noon
170
+ end
171
+ end
172
+
173
+ describe "#succ" do
174
+ it "returns a DayTime advanced by a second" do
175
+ expect(DayTime.new("08:00").succ).to eq DayTime.new("08:00:01")
176
+ end
177
+
178
+ context "with overflowing seconds" do
179
+ it "starts over at midnight" do
180
+ expect(DayTime.new("23:59:59").succ).to eq DayTime.new("00:00:00")
181
+ end
182
+ end
183
+ end
184
+
185
+ describe "#each" do
186
+ it "returns DayTimes advanced by a second" do
187
+ enum = DayTime.new("23:59:59").to_enum
188
+
189
+ expect(enum.next).to eq DayTime.new("00:00:00")
190
+ expect(enum.next).to eq DayTime.new("00:00:01")
191
+ end
192
+ end
193
+
194
+ describe "#+" do
195
+ let(:morning) { DayTime.new("08:00") }
196
+ let(:noon) { DayTime.new("12:00") }
197
+
198
+ context "with other DayTime" do
199
+ it "adds seconds since midnight" do
200
+ expect(morning + noon).to eq DayTime.new("20:00")
201
+ end
202
+ end
203
+
204
+ context "with other object" do
205
+ it "adds seconds since midnight" do
206
+ expect(morning + "00:00:15").to eq DayTime.new("08:00:15")
207
+ end
208
+ end
209
+ end
210
+
211
+ describe "#-" do
212
+ let(:noon) { DayTime.new("12:00") }
213
+ let(:morning) { DayTime.new("08:00") }
214
+
215
+ context "with other DayTime" do
216
+ it "subtracts seconds since midnight" do
217
+ expect(morning - noon).to eq DayTime.new("04:00")
218
+ end
219
+ end
220
+
221
+ context "with other object" do
222
+ it "adds seconds since midnight" do
223
+ expect(morning - 15).to eq DayTime.new("07:59:45")
224
+ end
225
+ end
226
+ end
227
+
228
+ describe "#to_s" do
229
+ it "returns a HH:MM:SS formatted string" do
230
+ expect(DayTime.new("04:22:44").to_s).to eq "04:22:44"
231
+ end
232
+ end
233
+
234
+ describe "#to_i" do
235
+ it "returns the seconds since midnight" do
236
+ day_time = DayTime.new("05:34:25")
237
+ expect(day_time.to_i).to eq day_time.seconds_since_midnight
238
+ end
239
+ end
240
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: day_time
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dominic Bauer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ description:
28
+ email: bauerdominic@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - ".gitignore"
34
+ - ".rspec"
35
+ - Gemfile
36
+ - Gemfile.lock
37
+ - LICENSE
38
+ - README.md
39
+ - Rakefile
40
+ - day_time.gemspec
41
+ - lib/day_time.rb
42
+ - spec/day_time_spec.rb
43
+ homepage: https://github.com/bauerd/day_time
44
+ licenses:
45
+ - MIT
46
+ metadata: {}
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 2.2.2
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Day time calculations
67
+ test_files:
68
+ - spec/day_time_spec.rb
69
+ has_rdoc: