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.

Constant Summary collapse

ZERO =

A static instance for zero durations

allocate.tap { |d| d.__send__(:initialize, 0) }

Class Attribute Summary collapse

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 Duration.from_nanos instead.

Parameters:

  • nanos (Integer) (defaults to: 0)

See Also:



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

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

Class Attribute Details

.default_to_s_precision=(precision) ⇒ Object

Precision for Duration#to_s if not otherwise specified

Defaults to 9.

Parameters:

  • precision (Numeric)


41
42
43
# File 'lib/monotime/duration.rb', line 41

def default_to_s_precision
  @default_to_s_precision
end

.sleep_function=(function) ⇒ Object

The sleep function used by all Monotime sleep functions.

This function must accept a positive Float number of seconds and return the Float time slept.

Defaults to Kernel.method(:sleep)

Parameters:

  • function (#call)


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

def sleep_function
  @sleep_function
end

Class Method Details

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

Generate a new Duration measuring the given number of microseconds.

Parameters:

  • micros (Numeric)

Returns:



86
87
88
# File 'lib/monotime/duration.rb', line 86

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.

Parameters:

  • millis (Numeric)

Returns:



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

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.

Parameters:

  • nanos (Numeric)

Returns:



96
97
98
# File 'lib/monotime/duration.rb', line 96

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.

Parameters:

  • secs (Numeric)

Returns:



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

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"

Returns:



108
109
110
111
112
# File 'lib/monotime/duration.rb', line 108

def measure
  start = Instant.now
  yield
  start.elapsed
end

.with_measureObject, Duration

Return the result of the yielded block alongside a Duration.

Examples:

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

Returns:



120
121
122
123
124
# File 'lib/monotime/duration.rb', line 120

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

.zeroDuration

Return a zero Duration.

Returns:



58
59
60
# File 'lib/monotime/duration.rb', line 58

def zero
  ZERO
end

Instance Method Details

#*(other) ⇒ Duration

Multiply this duration by a Numeric.

Examples:

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

Parameters:

  • other (Numeric)

Returns:



173
174
175
# File 'lib/monotime/duration.rb', line 173

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"

Parameters:

Returns:

Raises:

  • (TypeError)


135
136
137
138
139
# File 'lib/monotime/duration.rb', line 135

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"

Parameters:

Returns:

Raises:

  • (TypeError)


149
150
151
152
153
# File 'lib/monotime/duration.rb', line 149

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"

Returns:



184
185
186
# File 'lib/monotime/duration.rb', line 184

def -@
  Duration.new(-to_nanos)
end

#/(other) ⇒ Duration

Divide this duration by a Numeric.

Examples:

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

Parameters:

  • other (Numeric)

Returns:



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

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.

Parameters:

Returns:

  • (-1, 0, 1, nil)


206
207
208
# File 'lib/monotime/duration.rb', line 206

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.

Parameters:

Returns:

  • (Boolean)


215
216
217
# File 'lib/monotime/duration.rb', line 215

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"

Returns:



195
196
197
198
199
# File 'lib/monotime/duration.rb', line 195

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.

Parameters:

Returns:

  • (Boolean)


223
224
225
# File 'lib/monotime/duration.rb', line 223

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

#hashInteger

Generate a hash for this type and value.

Returns:

  • (Integer)


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

def hash
  [self.class, to_nanos].hash
end

#negative?Boolean

Return true if this Duration is negative.

Returns:

  • (Boolean)


280
281
282
# File 'lib/monotime/duration.rb', line 280

def negative?
  to_nanos.negative?
end

#nonzero?Boolean

Return true if this Duration is non-zero.

Returns:

  • (Boolean)


294
295
296
# File 'lib/monotime/duration.rb', line 294

def nonzero?
  to_nanos.nonzero?
end

#positive?Boolean

Return true if this Duration is positive.

Returns:

  • (Boolean)


273
274
275
# File 'lib/monotime/duration.rb', line 273

def positive?
  to_nanos.positive?
end

#sleepInteger

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

The sleep function may be overridden globally using Duration.sleep_function=

Examples:

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

Returns:

  • (Integer)

Raises:

  • (NotImplementedError)

    negative Duration sleeps are not yet supported.

See Also:



311
312
313
314
315
# File 'lib/monotime/duration.rb', line 311

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

  self.class.sleep_function.call(to_secs)
end

#to_microsFloat Also known as: micros

Return this Duration in microseconds.

Returns:

  • (Float)


255
256
257
# File 'lib/monotime/duration.rb', line 255

def to_micros
  to_nanos / 1_000.0
end

#to_millisFloat Also known as: millis

Return this Duration in milliseconds.

Returns:

  • (Float)


246
247
248
# File 'lib/monotime/duration.rb', line 246

def to_millis
  to_nanos / 1_000_000.0
end

#to_nanosInteger Also known as: nanos

Return this Duration in nanoseconds.

Returns:

  • (Integer)


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

def to_nanos
  @ns
end

#to_s(precision = self.class.default_to_s_precision) ⇒ String

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

The default precision may be set globally using Duration.default_to_s_precision=

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"

Parameters:

  • precision (Integer) (defaults to: self.class.default_to_s_precision)

    the maximum number of decimal places

Returns:

  • (String)

See Also:



345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/monotime/duration.rb', line 345

def to_s(precision = self.class.default_to_s_precision)
  precision = Integer(precision).abs
  nanos = to_nanos

  # This is infallible provided DIVISORS has an entry for 0
  div, unit = DIVISORS.find { |d, _| nanos.abs >= d }

  if div&.zero?
    format('%d%s', nanos, unit)
  else
    # `#' for `f' forces to show the decimal point.
    format("%#.#{precision}f", nanos / div).sub(/\.?0*\z/, '') << unit.to_s
  end
end

#to_secsFloat Also known as: secs

Return this Duration in seconds.

Returns:

  • (Float)


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

def to_secs
  to_nanos / 1_000_000_000.0
end

#zero?Boolean

Return true if this Duration is zero.

Returns:

  • (Boolean)


287
288
289
# File 'lib/monotime/duration.rb', line 287

def zero?
  to_nanos.zero?
end