day_time 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.
@@ -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: