monotime 0.2.0 → 0.3.0
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.
- 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
|