1 Introduction
1.1 Overview
std.lib.time is part of the standard foundation library set. This page collects the public API reference for the namespace.
2 Walkthrough
2.1 Reading the clock
std.lib.time provides thin wrappers around the system and high-resolution clocks. These are useful for timestamps, timeouts, and profiling.
system and high-resolution time are numbers
(system-ns) => number?
(system-ms) => number?
(time-ns) => number?
(time-us) => number?
(time-ms) => number?
2.2 Formatting and parsing durations
format-ms turns a millisecond count into a human readable string, while parse-ms does the reverse. format-ns and parse-ns work with nanosecond precision.
format milliseconds for display
(format-ms 10000000)
=> "02h 46m 40s"
(format-ms 500)
=> "500ms"
(format-ms 65000)
=> "01m 05s"
parse duration strings to milliseconds
(parse-ms "1s")
=> 1000
(parse-ms "0.5h")
=> 1800000
(parse-ms "2m")
=> 120000
format and parse nanosecond values
(format-ns 1000000)
=> "1.000ms"
(parse-ns "2ns")
=> 2
(parse-ns "0.3s")
=> 300000000
2.3 Elapsed time and benchmarking
Use elapsed-ms and elapsed-ns to measure how much time has passed since a captured timestamp. The bench-ms and bench-ns macros run a body multiple times and report the average duration.
measure elapsed time
(elapsed-ms (- (time-ms) 10) true)
=> string?
(elapsed-ns (time-ns) true)
=> string?
benchmark a block
(bench-ms (Thread/sleep 10))
=> integer?
(bench-ns (Thread/sleep 1))
=> integer?
2.4 End-to-end: timing a small computation
Combine parsing, benchmarking, and formatting to describe how long an operation takes in friendly units.
parse a duration, sleep, then report elapsed time
(let [duration (parse-ms "100ms")
start (time-ms)]
(Thread/sleep duration)
(format-ms (elapsed-ms start)))
=> string?
3 API
- *format*
- *no-gc*
- bench-form
- bench-ms
- bench-ns
- elapsed-ms
- elapsed-ns
- format-ms
- format-ns
- parse-ms
- parse-ns
- system-ms
- system-ns
- time-ms
- time-ns
- time-us
NONE
(defn- bench-form
[time-fn elapsed-fn opts body]
(let [[opts body] (cond (map? opts) [opts body]
:else [{} (cons opts body)])
{:keys [format no-gc runs]
:or {runs 1}} opts]
`(binding [*format* ~format]
(if-not (or ~no-gc *no-gc*)
(System/gc))
(let [start# (~time-fn)]
(dotimes [_# ~runs]
(do ~@body))
(quot (~elapsed-fn start#) ~runs)))))
link
v 3.0
(defmacro bench-ms
([opts & body]
(bench-form `time-ms `elapsed-ms opts body)))
link
(bench-ms (Thread/sleep 10)) => integer?
v 3.0
(defmacro bench-ns
([opts & body]
(bench-form `time-ns `elapsed-ns opts body)))
link
(bench-ns (Thread/sleep 1)) => integer?
v 3.0
(defn elapsed-ms
([ms] (elapsed-ms ms *format*))
([ms format]
(cond-> (- (time-ms) ms)
format format-ms)))
link
(elapsed-ms (- (time-ms) 10) true) => string?
v 3.0
(defn elapsed-ns
([ns] (elapsed-ns ns *format*))
([ns format]
(cond-> (- (time-ns) ns)
format (format-ns))))
link
(elapsed-ns (time-ns) true) ;; "35.42us" => string?
v 3.0
(defn format-ms
([time]
(let [millis (mod time 1000)
seconds (mod (quot time 1000) 60)
mins (mod (quot time (* 60 1000)) 60)
hours (mod (quot time (* 60 60 1000)) 24)
days (quot time (* 24 60 60 1000))
level (count (drop-while zero? [days hours mins seconds millis]))]
(case level
0 "0ms"
1 (format "%03dms" millis)
2 (format "%02ds %03dms" seconds millis)
3 (format "%02dm %02ds" mins seconds)
4 (format "%02dh %02dm %02ds" hours mins seconds)
5 (format "%02dd %02dh %02dm" days mins seconds)))))
link
(format-ms 10000000) => "02h 46m 40s"
v 3.0
(defn format-ns
([time]
(format-ns time 4))
([time digits]
(let [full (str time)
len (count full)
suffix (cond (<= 1 len 3)
"ns"
(<= 4 len 6)
"us"
(<= 7 len 9)
"ms"
(<= 10 len 12)
"s"
(<= 13 len 15)
"ks"
(<= 16 len 18)
"Ms"
(<= 19 len 21)
"Gs")
decimal (inc (rem (dec len) 3))]
(if (<= len digits)
(str full "ns")
(let [out (subs full 0 digits)]
(str (subs out 0 decimal)
"."
(subs out decimal)
suffix))))))
link
(format-ns 1000000) => "1.000ms"
v 3.0
(defn parse-ms
([^String s]
(let [len (count s)
[s unit] (cond (.endsWith s "ms")
[(subs s 0 (- len 2)) 1]
:else
(let [unit (case (last s)
d (* 24 60 60 1000)
h (* 60 60 1000)
m (* 60 1000)
s 1000)]
[(subs s 0 (dec len)) unit]))
v (Double/parseDouble s)]
(long (* v unit)))))
link
(parse-ms "1s") => 1000 (parse-ms "0.5h") => 1800000
v 3.0
(defn parse-ns
([^String s]
(if (.endsWith s "s")
(let [len (count s)
nchar (nth s (- len 2))
[s unit] (cond (<= (int 0) (int nchar) (int 9))
[(subs s 0 (dec len)) 1000000000]
:else
(let [unit (case nchar
n 1
u 1000
m 1000000
k 1000000000000
M 1000000000000000
G 1000000000000000000)]
[(subs s 0 (- len 2)) unit]))
v (Double/parseDouble s)]
(long (* v unit))))))
link
(parse-ns "2ns") => 2 (parse-ns "0.3s") => 300000000
4 std.lib.time: A Comprehensive Summary
The std.lib.time namespace provides a set of utility functions for working with time measurements in Clojure, offering high-resolution timing, human-readable formatting, and benchmarking capabilities. It leverages System/nanoTime and System/currentTimeMillis for precise measurements and includes functions for parsing time strings.
Key Features and Concepts:
- High-Resolution Time Measurement:n
system-ns: Returns the system's current time in nanoseconds (fromSystem/nanoTime).nsystem-ms: Returns the system's current time in milliseconds (fromSystem/currentTimeMillis).ntime-ns: Returns the current time in nanoseconds usinghara.lib.foundation.Clock/currentTimeNanosfor potentially more consistent or specialized timing.ntime-us: Returns the current time in microseconds usinghara.lib.foundation.Clock/currentTimeMicros.ntime-ms: Returns the current time in milliseconds usinghara.lib.foundation.Clock/currentTimeMillis).nn2. Time Formatting:nformat-ms: Converts a duration in milliseconds into a human-readable string format (e.g., "02h 46m 40s").nformat-ns: Converts a duration in nanoseconds into a human-readable string format, scaling to nanoseconds, microseconds, milliseconds, seconds, kiloseconds, megaseconds, or gigaseconds.nn3. Time Parsing:nparse-ms: Parses a string representation of time (e.g., "1s", "0.5h") into its equivalent duration in milliseconds.nparse-ns: Parses a string representation of time (e.g., "2ns", "0.3s") into its equivalent duration in nanoseconds.nn4. Elapsed Time Calculation:nelapsed-ms: Calculates the time elapsed in milliseconds since a given starting millisecond timestamp, with an option to format the output.nelapsed-ns: Calculates the time elapsed in nanoseconds since a given starting nanosecond timestamp, with an option to format the output.nn5. Benchmarking Macros:nbench-ns: A macro to measure the execution time of a code block in nanoseconds. It supports options for formatting, disabling garbage collection during measurement, and running the block multiple times.n *bench-ms: A macro to measure the execution time of a code block in milliseconds, with similar options tobench-ns.
Usage and Importance:
The std.lib.time module is essential for performance analysis, logging, and any application logic that requires precise timing or human-friendly time representations. Its benchmarking macros provide a convenient way to profile code execution, while the formatting and parsing functions facilitate user interaction and data processing involving time durations. This module contributes to the foundation-base project by offering robust and flexible tools for managing time-related aspects of applications.