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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5a97344679471a970a324027b84b560faf9dfc9597c0937094de1486cc0da602
4
- data.tar.gz: 35d55277a3181f0033939263122296b3a5328c5cc1605722644dd21aa9305ac1
3
+ metadata.gz: d77cca7907b76e8276296abc382f10612e7879605f7472ab46e4b26c9594426d
4
+ data.tar.gz: d4d1284f11de89438125a3e28e4686bdde6a78cf02a431d3eb57e861e7345613
5
5
  SHA512:
6
- metadata.gz: 29d7c0fb1aa092127f1a1a3036552466d9f6ea83d337fa3c9ffda0e88d3b5fb4ca996f81c828701a2a1bee4bf44d8c6392395298ac9f257034b3b71b8d0437b3
7
- data.tar.gz: bd3bef852b6d5b25810091e0ee7452e60e03a5cd25cc5577e25760452804d3d201cfc05efd2dcf19d91680ff6bdacbd93b9428473def942ac3c024aea4675c9d
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(-1)).to_s # => "-958ms"
64
+ (Duration.from_millis(42) - Duration.from_secs(1)).to_s # => "-958ms"
65
65
  ```
66
66
 
67
67
  `Instant` does some simple maths too:
@@ -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 a given nanosecond measurement, defaulting to
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
- case earlier
34
- when Instant then earlier - self
35
- else raise TypeError, 'Not an Instant'
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
- case other
52
- when Duration then Instant.new(@ns + other.to_nanos)
53
- else raise TypeError, 'Not a Duration'
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
- case other
61
- when Instant then Duration.new(@ns - other.ns)
62
- when Duration then Instant.new(@ns - other.to_nanos)
63
- else raise TypeError, 'Not an Instant or Duration'
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
- case other
70
- when Instant then @ns <=> other.ns
71
- else raise TypeError, 'Not an Instant'
72
- end
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Monotime
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
@@ -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.2.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-02 00:00:00.000000000 Z
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