|
| 1 | +# Returns the current reading of the monotonic clock. |
| 2 | +# |
| 3 | +# The execution time of a block can be measured using `.measure`. |
| 4 | +def Time.instant : Time::Instant |
| 5 | + seconds, nanoseconds = Crystal::System::Time.monotonic |
| 6 | + Time::Instant.new(seconds: seconds, nanoseconds: nanoseconds) |
| 7 | +end |
| 8 | + |
| 9 | +# `Time::Instant` represents a reading of a monotonic non-decreasing |
| 10 | +# clock for the purpose of measuring elapsed time or timing an event in the future. |
| 11 | +# |
| 12 | +# Instants are opaque values that have no public constructor or raw accessors by |
| 13 | +# default. They can only be obtained from the clock (`Time.instant`) and compared to one another. |
| 14 | +# The only useful values are differences between readings, represented as `Time::Span`. |
| 15 | +# |
| 16 | +# ## Clock properties |
| 17 | +# |
| 18 | +# Clock readings are guaranteed, barring platform bugs, to be no less than any |
| 19 | +# previous reading (monotonic clock). |
| 20 | +# |
| 21 | +# The measurement itself is expected to be fast (low latency) and precise within |
| 22 | +# nanosecond resolution. This means it might not provide the best available |
| 23 | +# accuracy for long-term measurements. |
| 24 | +# |
| 25 | +# The clock is not guaranteed to be steady. Ticks of the underlying clock might |
| 26 | +# vary in length. The clock may jump forwards or experience time dilation. But |
| 27 | +# it never goes backwards. |
| 28 | +# |
| 29 | +# The clock is expected to tick while the system is suspended. But this cannot be |
| 30 | +# guaranteed on all platforms. |
| 31 | +# |
| 32 | +# The clock is only guaranteed to apply to the current process. In practice, it is |
| 33 | +# usually relative to system boot, so should be interchangeable between processes. |
| 34 | +# But this is not guaranteed on all platforms. |
| 35 | +# |
| 36 | +# ## Example |
| 37 | +# |
| 38 | +# ``` |
| 39 | +# start = Time.instant |
| 40 | +# # do something |
| 41 | +# elapsed = start.elapsed |
| 42 | +# ``` |
| 43 | +# |
| 44 | +# `Time.measure(&)` is a convenient alternative for measuring elapsed time of an |
| 45 | +# individual code block. |
| 46 | +struct Time::Instant |
| 47 | + include Comparable(self) |
| 48 | + |
| 49 | + # :nodoc: |
| 50 | + def initialize(@seconds : Int64, @nanoseconds : Int32) |
| 51 | + end |
| 52 | + |
| 53 | + def -(other : self) : Time::Span |
| 54 | + Time::Span.new(seconds: @seconds - other.@seconds, nanoseconds: @nanoseconds - other.@nanoseconds) |
| 55 | + end |
| 56 | + |
| 57 | + def +(other : Time::Span) : self |
| 58 | + span = Time::Span.new(seconds: @seconds, nanoseconds: @nanoseconds) + other |
| 59 | + Instant.new(span.@seconds, span.@nanoseconds) |
| 60 | + end |
| 61 | + |
| 62 | + def -(other : Time::Span) : self |
| 63 | + span = Time::Span.new(seconds: @seconds, nanoseconds: @nanoseconds) - other |
| 64 | + Instant.new(span.@seconds, span.@nanoseconds) |
| 65 | + end |
| 66 | + |
| 67 | + def <=>(other : self) : Int32 |
| 68 | + cmp = @seconds <=> other.@seconds |
| 69 | + cmp = @nanoseconds <=> other.@nanoseconds if cmp == 0 |
| 70 | + cmp |
| 71 | + end |
| 72 | + |
| 73 | + # Returns the duration between `other` and `self`. |
| 74 | + # |
| 75 | + # The resulting duration is positive or zero. |
| 76 | + def duration_since(other : self) : Time::Span |
| 77 | + (self - other).clamp(Time::Span.zero..) |
| 78 | + end |
| 79 | + |
| 80 | + # Returns the amount of time elapsed since `self`. |
| 81 | + # |
| 82 | + # The resulting duration is positive or zero. |
| 83 | + def elapsed : Time::Span |
| 84 | + Time.instant.duration_since(self) |
| 85 | + end |
| 86 | +end |
0 commit comments