class Monotime::Instant

A measurement from the operating system's monotonic clock, with up to nanosecond precision.

Attributes

ns[R]

A measurement, in nanoseconds. Should be considered opaque and non-portable outside the process that created it.

Public Class Methods

new(nanos = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)) click to toggle source

Create a new Instant from an optional nanosecond measurement.

Users should generally not pass anything to this function.

@param nanos [Integer] @see now

# File lib/monotime/instant.rb, line 20
def initialize(nanos = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond))
  @ns = Integer(nanos)
end
now() click to toggle source

An alias to new, and generally preferred over it.

@return [Instant]

# File lib/monotime/instant.rb, line 27
def self.now
  new
end

Public Instance Methods

+(other) click to toggle source

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

@example

(Instant.now + Duration.from_secs(1)).to_s # => "-999.983976ms"

@param other [Duration, to_nanos] @return [Instant]

# File lib/monotime/instant.rb, line 126
def +(other)
  return TypeError, 'Not one of: [Duration, #to_nanos]' unless other.respond_to?(:to_nanos)

  Instant.new(@ns + other.to_nanos)
end
-(other) click to toggle source

Subtract another Instant to generate a Duration between the two, or a Duration or #to_nanos-coercible object, to generate an Instant offset by it.

@example

(Instant.now - Duration.from_secs(1)).to_s # => "1.000016597s"
(Instant.now - Instant.now).to_s           # => "-3.87μs"

@param other [Instant, Duration, to_nanos] @return [Duration, Instant]

# File lib/monotime/instant.rb, line 142
def -(other)
  if other.is_a?(Instant)
    Duration.new(@ns - other.ns)
  elsif other.respond_to?(:to_nanos)
    Instant.new(@ns - other.to_nanos)
  else
    raise TypeError, 'Not one of: [Instant, Duration, #to_nanos]'
  end
end
<=>(other) click to toggle source

Determine if the given Instant is before, equal to or after this one. nil if not passed an Instant.

@return [-1, 0, 1, nil]

# File lib/monotime/instant.rb, line 156
def <=>(other)
  @ns <=> other.ns if other.is_a?(Instant)
end
==(other) click to toggle source

Determine if other's value equals that of this Instant. Use eql? if type checks are desired for future compatibility.

@return [Boolean] @see eql?

# File lib/monotime/instant.rb, line 165
def ==(other)
  other.is_a?(Instant) && @ns == other.ns
end
Also aliased as: eql?
duration_since(earlier) click to toggle source

Return a Duration between this Instant and another.

@param earlier [Instant] @return [Duration]

# File lib/monotime/instant.rb, line 35
def duration_since(earlier)
  raise TypeError, 'Not an Instant' unless earlier.is_a?(Instant)

  earlier - self
end
elapsed() click to toggle source

Return a Duration since this Instant and now.

@return [Duration]

# File lib/monotime/instant.rb, line 44
def elapsed
  duration_since(self.class.now)
end
eql?(other)
Alias for: ==
future?()
Alias for: in_future?
hash() click to toggle source

Generate a hash for this type and value.

@return [Integer]

# File lib/monotime/instant.rb, line 174
def hash
  self.class.hash ^ @ns.hash
end
in_future?() click to toggle source

Return whether this Instant is in the future.

@return [Boolean]

# File lib/monotime/instant.rb, line 60
def in_future?
  elapsed.negative?
end
Also aliased as: future?
in_past?() click to toggle source

Return whether this Instant is in the past.

@return [Boolean]

# File lib/monotime/instant.rb, line 51
def in_past?
  elapsed.positive?
end
Also aliased as: past?
past?()
Alias for: in_past?
sleep(duration = nil) click to toggle source

Sleep until this Instant, plus an optional Duration, returning a Duration that's either positive if any time was slept, or negative if sleeping would require time travel.

@example Sleeps for a second

start = Instant.now
sleep 0.5 # do stuff for half a second
start.sleep(Duration.from_secs(1)).to_s # => "490.088706ms" (slept)
start.sleep(Duration.from_secs(1)).to_s # => "-12.963502ms" (did not sleep)

@example Also sleeps for a second.

one_second_in_the_future = Instant.now + Duration.from_secs(1)
one_second_in_the_future.sleep.to_s     # => "985.592712ms" (slept)
one_second_in_the_future.sleep.to_s     # => "-4.71217ms" (did not sleep)

@param duration [nil, Duration, to_nanos] @return [Duration] the slept duration, if #positive?, else the overshot time

# File lib/monotime/instant.rb, line 83
def sleep(duration = nil)
  remaining = duration ? duration - elapsed : -elapsed

  remaining.tap { |rem| rem.sleep if rem.positive? }
end
sleep_millis(millis) click to toggle source

Sleep for the given number of milliseconds past this Instant, if any.

Equivalent to +#sleep(Duration.from_millis(millis))+

@param millis [Numeric] number of milliseconds to sleep past this Instant @return [Duration] the slept duration, if #positive?, else the overshot time @see sleep

# File lib/monotime/instant.rb, line 107
def sleep_millis(millis)
  sleep(Duration.from_millis(millis))
end
sleep_secs(secs) click to toggle source

Sleep for the given number of seconds past this Instant, if any.

Equivalent to +#sleep(Duration.from_secs(secs))+

@param secs [Numeric] number of seconds to sleep past this Instant @return [Duration] the slept duration, if #positive?, else the overshot time @see sleep

# File lib/monotime/instant.rb, line 96
def sleep_secs(secs)
  sleep(Duration.from_secs(secs))
end
to_s(*args) click to toggle source

Sugar for #elapsed.to_s.

@see Duration#to_s

# File lib/monotime/instant.rb, line 114
def to_s(*args)
  elapsed.to_s(*args)
end