Class: Monotime::Duration

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/monotime/duration.rb

Overview

A type representing a span of time in nanoseconds.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(nanos = 0) ⇒ Duration

Create a new Duration of a specified number of nanoseconds, zero by default.

Users are strongly advised to use #from_nanos instead.

See Also:

  • #from_nanos


15
16
17
# File 'lib/monotime/duration.rb', line 15

def initialize(nanos = 0)
  @ns = Integer(nanos)
end

Class Method Details

.from_micros(micros) ⇒ Duration Also known as: micros

Generate a new Duration measuring the given number of microseconds.



44
45
46
# File 'lib/monotime/duration.rb', line 44

def from_micros(micros)
  new(Integer(micros * 1_000))
end

.from_millis(millis) ⇒ Duration Also known as: millis

Generate a new Duration measuring the given number of milliseconds.



34
35
36
# File 'lib/monotime/duration.rb', line 34

def from_millis(millis)
  new(Integer(millis * 1_000_000))
end

.from_nanos(nanos) ⇒ Duration Also known as: nanos

Generate a new Duration measuring the given number of nanoseconds.



54
55
56
# File 'lib/monotime/duration.rb', line 54

def from_nanos(nanos)
  new(Integer(nanos))
end

.from_secs(secs) ⇒ Duration Also known as: secs

Generate a new Duration measuring the given number of seconds.



24
25
26
# File 'lib/monotime/duration.rb', line 24

def from_secs(secs)
  new(Integer(secs * 1_000_000_000))
end

.measureDuration

Return a Duration measuring the elapsed time of the yielded block.

Examples:

Duration.measure { sleep(0.5) }.to_s # => "512.226109ms"


66
67
68
# File 'lib/monotime/duration.rb', line 66

def measure
  Instant.now.tap { yield }.elapsed
end

.with_measureObject, Duration

Return the result of the yielded block alongside a Duration.

Examples:

Duration.with_measure { "bloop" } # => ["bloop", #<Monotime::Duration: ...>]


76
77
78
79
80
# File 'lib/monotime/duration.rb', line 76

def with_measure
  start = Instant.now
  ret = yield
  [ret, start.elapsed]
end

Instance Method Details

#*(other) ⇒ Duration

Multiply this duration by a Numeric.

Examples:

(Duration.from_secs(10) * 2).to_s # => "20s"


129
130
131
# File 'lib/monotime/duration.rb', line 129

def *(other)
  Duration.new(to_nanos * other)
end

#+(other) ⇒ Duration

Add another Duration or #to_nanos-coercible object to this one, returning a new Duration.

Examples:

(Duration.from_secs(10) + Duration.from_secs(5)).to_s # => "15s"

Raises:

  • (TypeError)


91
92
93
94
95
# File 'lib/monotime/duration.rb', line 91

def +(other)
  raise TypeError, 'Not one of: [Duration, #to_nanos]' unless other.respond_to?(:to_nanos)

  Duration.new(to_nanos + other.to_nanos)
end

#-(other) ⇒ Duration

Subtract another Duration or #to_nanos-coercible object from this one, returning a new Duration.

Examples:

(Duration.from_secs(10) - Duration.from_secs(5)).to_s # => "5s"

Raises:

  • (TypeError)


105
106
107
108
109
# File 'lib/monotime/duration.rb', line 105

def -(other)
  raise TypeError, 'Not one of: [Duration, #to_nanos]' unless other.respond_to?(:to_nanos)

  Duration.new(to_nanos - other.to_nanos)
end

#-@Duration

Unary minus: make a positive Duration negative, and vice versa.

Examples:

-Duration.from_secs(-1).to_s # => "1s"
-Duration.from_secs(1).to_s  # => "-1s"


140
141
142
# File 'lib/monotime/duration.rb', line 140

def -@
  Duration.new(-to_nanos)
end

#/(other) ⇒ Duration

Divide this duration by a Numeric.

Examples:

(Duration.from_secs(10) / 2).to_s # => "5s"


118
119
120
# File 'lib/monotime/duration.rb', line 118

def /(other)
  Duration.new(to_nanos / other)
end

#<=>(other) ⇒ -1, ...

Compare the value of this Duration with another, or any #to_nanos-coercible object, or nil if not comparable.



162
163
164
# File 'lib/monotime/duration.rb', line 162

def <=>(other)
  to_nanos <=> other.to_nanos if other.respond_to?(:to_nanos)
end

#==(other) ⇒ Boolean

Compare the equality of the value of this Duration with another, or any #to_nanos-coercible object, or nil if not comparable.



171
172
173
# File 'lib/monotime/duration.rb', line 171

def ==(other)
  other.respond_to?(:to_nanos) && to_nanos == other.to_nanos
end

#absDuration

Return a Duration that’s absolute (positive).

Examples:

Duration.from_secs(-1).abs.to_s # => "1s"
Duration.from_secs(1).abs.to_s  # => "1s"


151
152
153
154
155
# File 'lib/monotime/duration.rb', line 151

def abs
  return self if positive? || zero?

  Duration.new(to_nanos.abs)
end

#eql?(other) ⇒ Boolean

Check equality of the value and type of this Duration with another.



179
180
181
# File 'lib/monotime/duration.rb', line 179

def eql?(other)
  other.is_a?(Duration) && to_nanos == other.to_nanos
end

#hashInteger

Generate a hash for this type and value.



186
187
188
# File 'lib/monotime/duration.rb', line 186

def hash
  self.class.hash ^ to_nanos.hash
end

#negative?Boolean

Return true if this Duration is negative.



236
237
238
# File 'lib/monotime/duration.rb', line 236

def negative?
  to_nanos.negative?
end

#nonzero?Boolean

Return true if this Duration is non-zero.



250
251
252
# File 'lib/monotime/duration.rb', line 250

def nonzero?
  to_nanos.nonzero?
end

#positive?Boolean

Return true if this Duration is positive.



229
230
231
# File 'lib/monotime/duration.rb', line 229

def positive?
  to_nanos.positive?
end

#sleepInteger

Sleep for the duration of this Duration. Equivalent to Kernel.sleep(duration.to_secs).

Examples:

Duration.from_secs(1).sleep  # => 1
Duration.from_secs(-1).sleep # => raises NotImplementedError

Raises:

  • (NotImplementedError)

    negative Duration sleeps are not yet supported.

See Also:



264
265
266
267
268
# File 'lib/monotime/duration.rb', line 264

def sleep
  raise NotImplementedError, 'time travel module missing' if negative?

  Kernel.sleep(to_secs)
end

#to_microsFloat Also known as: micros

Return this Duration in microseconds.



211
212
213
# File 'lib/monotime/duration.rb', line 211

def to_micros
  to_nanos / 1_000.0
end

#to_millisFloat Also known as: millis

Return this Duration in milliseconds.



202
203
204
# File 'lib/monotime/duration.rb', line 202

def to_millis
  to_nanos / 1_000_000.0
end

#to_nanosInteger Also known as: nanos

Return this Duration in nanoseconds.



220
221
222
# File 'lib/monotime/duration.rb', line 220

def to_nanos
  @ns
end

#to_s(precision = 9) ⇒ String

Format this Duration into a human-readable string, with a given number of decimal places.

The exact format is subject to change, users with specific requirements are encouraged to use their own formatting methods.

Examples:

Duration.from_nanos(100).to_s  # => "100ns"
Duration.from_micros(100).to_s # => "100μs"
Duration.from_millis(100).to_s # => "100ms"
Duration.from_secs(100).to_s   # => "100s"
Duration.from_nanos(1234567).to_s # => "1.234567ms"
Duration.from_nanos(1234567).to_s(2) # => "1.23ms"


295
296
297
298
299
300
301
302
303
304
# File 'lib/monotime/duration.rb', line 295

def to_s(precision = 9)
  precision = Integer(precision).abs
  div, unit = DIVISORS.find { |d, _| to_nanos.abs >= d }

  if div.zero?
    format('%d%s', to_nanos, unit)
  else
    format("%#.#{precision}f", to_nanos / div).sub(/\.?0*\z/, '') << unit
  end
end

#to_secsFloat Also known as: secs

Return this Duration in seconds.



193
194
195
# File 'lib/monotime/duration.rb', line 193

def to_secs
  to_nanos / 1_000_000_000.0
end

#zero?Boolean

Return true if this Duration is zero.



243
244
245
# File 'lib/monotime/duration.rb', line 243

def zero?
  to_nanos.zero?
end