monotime 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/monotime.rb +92 -23
- data/lib/monotime/version.rb +1 -1
- data/monotime.gemspec +0 -2
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d77cca7907b76e8276296abc382f10612e7879605f7472ab46e4b26c9594426d
|
4
|
+
data.tar.gz: d4d1284f11de89438125a3e28e4686bdde6a78cf02a431d3eb57e861e7345613
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4975756b4d469b02437d7ad45216eef58d5e20b3675f6c725c64d1b8d1da3518c5eec89fc98cbc1d9d0e6238665232e837415783726132b757cf2e19ab2ef4fc
|
7
|
+
data.tar.gz: cfe8ffd03b80d308d512f5df277e5b9d82c6c88f47cb048390245dd8b34f598e03c41ad9286576add9f75dfdd1cbb2230101b60dc6bed844f85de9fab1247a76
|
data/README.md
CHANGED
@@ -61,7 +61,7 @@ And how to do basic maths on itself:
|
|
61
61
|
|
62
62
|
```ruby
|
63
63
|
(Duration.from_millis(42) + Duration.from_secs(1)).to_s # => "1.042s"
|
64
|
-
(Duration.from_millis(42) - Duration.from_secs(
|
64
|
+
(Duration.from_millis(42) - Duration.from_secs(1)).to_s # => "-958ms"
|
65
65
|
```
|
66
66
|
|
67
67
|
`Instant` does some simple maths too:
|
data/lib/monotime.rb
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'monotime/version'
|
4
4
|
|
5
|
-
require 'dry-equalizer'
|
6
|
-
|
7
5
|
module Monotime
|
8
6
|
# A measurement from the operating system's monotonic clock, with up to
|
9
7
|
# nanosecond precision.
|
@@ -12,136 +10,202 @@ module Monotime
|
|
12
10
|
# non-portable outside the process that created it.
|
13
11
|
protected def ns() @ns end
|
14
12
|
|
15
|
-
include Dry::Equalizer(:ns)
|
16
13
|
include Comparable
|
17
14
|
|
18
|
-
# Create a new +Instant+ from
|
19
|
-
# that given by +Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond))+.
|
15
|
+
# Create a new +Instant+ from an optional nanosecond measurement.
|
20
16
|
#
|
21
17
|
# Users should generally *not* pass anything to this function.
|
18
|
+
#
|
19
|
+
# @param nanos [Integer]
|
22
20
|
def initialize(nanos = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond))
|
23
21
|
@ns = Integer(nanos)
|
24
22
|
end
|
25
23
|
|
26
24
|
# An alias to +new+, and generally preferred over it.
|
25
|
+
#
|
26
|
+
# @return [Instant]
|
27
27
|
def self.now
|
28
28
|
new
|
29
29
|
end
|
30
30
|
|
31
31
|
# Return a +Duration+ between this +Instant+ and another.
|
32
|
+
#
|
33
|
+
# @param earlier [Instant]
|
34
|
+
# @return [Duration]
|
32
35
|
def duration_since(earlier)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
36
|
+
raise TypeError, 'Not an Instant' unless earlier.is_a?(Instant)
|
37
|
+
|
38
|
+
earlier - self
|
37
39
|
end
|
38
40
|
|
39
41
|
# Return a +Duration+ since this +Instant+ and now.
|
42
|
+
#
|
43
|
+
# @return [Duration]
|
40
44
|
def elapsed
|
41
45
|
duration_since(self.class.now)
|
42
46
|
end
|
43
47
|
|
44
48
|
# Sugar for +elapsed.to_s+.
|
49
|
+
#
|
50
|
+
# @see Duration#to_s
|
45
51
|
def to_s(*args)
|
46
52
|
elapsed.to_s(*args)
|
47
53
|
end
|
48
54
|
|
49
55
|
# Add a +Duration+ to this +Instant+, returning a new +Instant+.
|
56
|
+
#
|
57
|
+
# @param other [Duration, #to_nanos]
|
58
|
+
# @return [Instant]
|
50
59
|
def +(other)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
60
|
+
return TypeError, 'Not one of: [Duration, #to_nanos]' unless other.respond_to?(:to_nanos)
|
61
|
+
|
62
|
+
Instant.new(@ns + other.to_nanos)
|
55
63
|
end
|
56
64
|
|
57
65
|
# Subtract another +Instant+ to generate a +Duration+ between the two,
|
58
66
|
# or a +Duration+, to generate an +Instant+ offset by it.
|
67
|
+
#
|
68
|
+
# @param other [Instant, Duration, #to_nanos]
|
69
|
+
# @return [Duration, Instant]
|
59
70
|
def -(other)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
71
|
+
if other.is_a?(Instant)
|
72
|
+
Duration.new(@ns - other.ns)
|
73
|
+
elsif other.respond_to?(:to_nanos)
|
74
|
+
Instant.new(@ns - other.to_nanos)
|
75
|
+
else
|
76
|
+
raise TypeError, 'Not one of: [Instant, Duration, #to_nanos]'
|
64
77
|
end
|
65
78
|
end
|
66
79
|
|
67
80
|
# Compare this +Instant+ with another.
|
68
81
|
def <=>(other)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
82
|
+
@ns <=> other.ns if other.is_a?(Instant)
|
83
|
+
end
|
84
|
+
|
85
|
+
def ==(other)
|
86
|
+
other.is_a?(Instant) && @ns == other.ns
|
87
|
+
end
|
88
|
+
|
89
|
+
alias eql? ==
|
90
|
+
|
91
|
+
def hash
|
92
|
+
self.class.hash ^ @ns.hash
|
73
93
|
end
|
74
94
|
end
|
75
95
|
|
76
96
|
# A type representing a span of time in nanoseconds.
|
77
97
|
class Duration
|
78
|
-
include Dry::Equalizer(:to_nanos)
|
79
98
|
include Comparable
|
80
99
|
|
81
100
|
# Create a new +Duration+ of a specified number of nanoseconds, zero by
|
82
101
|
# default.
|
102
|
+
#
|
103
|
+
# @param nanos [Integer]
|
83
104
|
def initialize(nanos = 0)
|
84
105
|
@ns = Integer(nanos)
|
85
106
|
end
|
86
107
|
|
87
108
|
class << self
|
88
109
|
# Generate a new +Duration+ measuring the given number of seconds.
|
110
|
+
#
|
111
|
+
# @param secs [Numeric]
|
112
|
+
# @return [Duration]
|
89
113
|
def from_secs(secs)
|
90
114
|
new(Integer(Float(secs) * 1_000_000_000))
|
91
115
|
end
|
92
116
|
|
93
117
|
# Generate a new +Duration+ measuring the given number of milliseconds.
|
118
|
+
#
|
119
|
+
# @param millis [Numeric]
|
120
|
+
# @return [Duration]
|
94
121
|
def from_millis(millis)
|
95
122
|
new(Integer(Float(millis) * 1_000_000))
|
96
123
|
end
|
97
124
|
|
98
125
|
# Generate a new +Duration+ measuring the given number of microseconds.
|
126
|
+
#
|
127
|
+
# @param micros [Numeric]
|
128
|
+
# @return [Duration]
|
99
129
|
def from_micros(micros)
|
100
130
|
new(Integer(Float(micros) * 1_000))
|
101
131
|
end
|
102
132
|
|
103
133
|
# Generate a new +Duration+ measuring the given number of nanoseconds.
|
134
|
+
#
|
135
|
+
# @param nanos [Numeric]
|
136
|
+
# @return [Duration]
|
104
137
|
def from_nanos(nanos)
|
105
138
|
new(Integer(nanos))
|
106
139
|
end
|
107
140
|
|
108
141
|
# Return a +Duration+ measuring the elapsed time of the yielded block.
|
142
|
+
#
|
143
|
+
# @return [Duration]
|
109
144
|
def measure
|
110
145
|
Instant.now.tap { yield }.elapsed
|
111
146
|
end
|
112
147
|
end
|
113
148
|
|
114
149
|
# Add another +Duration+ to this one, returning a new +Duration+.
|
150
|
+
#
|
151
|
+
# @param [Duration, #to_nanos]
|
152
|
+
#
|
153
|
+
# @return [Duration]
|
115
154
|
def +(other)
|
155
|
+
raise TypeError, 'Not one of: [Duration, #to_nanos]' unless other.respond_to?(:to_nanos)
|
156
|
+
|
116
157
|
Duration.new(to_nanos + other.to_nanos)
|
117
158
|
end
|
118
159
|
|
119
160
|
# Subtract another +Duration+ from this one, returning a new +Duration+.
|
161
|
+
#
|
162
|
+
# @param [Duration, #to_nanos]
|
163
|
+
# @return [Duration]
|
120
164
|
def -(other)
|
165
|
+
raise TypeError, 'Not one of: [Duration, #to_nanos]' unless other.respond_to?(:to_nanos)
|
166
|
+
|
121
167
|
Duration.new(to_nanos - other.to_nanos)
|
122
168
|
end
|
123
169
|
|
124
170
|
# Compare this +Duration+ with another.
|
125
171
|
def <=>(other)
|
126
|
-
to_nanos <=> other.to_nanos
|
172
|
+
to_nanos <=> other.to_nanos if other.is_a? Duration
|
173
|
+
end
|
174
|
+
|
175
|
+
def ==(other)
|
176
|
+
other.is_a?(Duration) && to_nanos == other.to_nanos
|
177
|
+
end
|
178
|
+
|
179
|
+
alias eql? ==
|
180
|
+
|
181
|
+
def hash
|
182
|
+
self.class.hash ^ to_nanos.hash
|
127
183
|
end
|
128
184
|
|
129
185
|
# Return this +Duration+ in seconds.
|
186
|
+
#
|
187
|
+
# @return [Float]
|
130
188
|
def to_secs
|
131
189
|
to_nanos / 1_000_000_000.0
|
132
190
|
end
|
133
191
|
|
134
192
|
# Return this +Duration+ in milliseconds.
|
193
|
+
#
|
194
|
+
# @return [Float]
|
135
195
|
def to_millis
|
136
196
|
to_nanos / 1_000_000.0
|
137
197
|
end
|
138
198
|
|
139
199
|
# Return this +Duration+ in microseconds.
|
200
|
+
#
|
201
|
+
# @return [Float]
|
140
202
|
def to_micros
|
141
203
|
to_nanos / 1_000.0
|
142
204
|
end
|
143
205
|
|
144
206
|
# Return this +Duration+ in nanoseconds.
|
207
|
+
#
|
208
|
+
# @return [Integer]
|
145
209
|
def to_nanos
|
146
210
|
@ns
|
147
211
|
end
|
@@ -153,11 +217,16 @@ module Monotime
|
|
153
217
|
[0, 'ns']
|
154
218
|
].map(&:freeze).freeze
|
155
219
|
|
220
|
+
private_constant :DIVISORS
|
221
|
+
|
156
222
|
# Format this +Duration+ into a human-readable string, with a given number
|
157
223
|
# of decimal places.
|
158
224
|
#
|
159
225
|
# The exact format is subject to change, users with specific requirements
|
160
226
|
# are encouraged to use their own formatting methods.
|
227
|
+
#
|
228
|
+
# @param precision [Integer] the maximum number of decimal places
|
229
|
+
# @return [String]
|
161
230
|
def to_s(precision = 9)
|
162
231
|
precision = Integer(precision).abs
|
163
232
|
ns = to_nanos.abs
|
data/lib/monotime/version.rb
CHANGED
data/monotime.gemspec
CHANGED
@@ -31,8 +31,6 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
32
|
spec.require_paths = ["lib"]
|
33
33
|
|
34
|
-
spec.add_dependency "dry-equalizer", '~> 0'
|
35
|
-
|
36
34
|
spec.add_development_dependency "bundler", "~> 1.16"
|
37
35
|
spec.add_development_dependency "rake", "~> 10.0"
|
38
36
|
spec.add_development_dependency "minitest", "~> 5.0"
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: monotime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Hurst
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: dry-equalizer
|
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
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: bundler
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|