Duration
cargo run --bin 50_timeDuration is a non-negative span of time. Build one with from_secs, from_millis, from_micros, from_nanos, or from_secs_f64; read it back with as_secs, as_millis, subsec_millis, or as_secs_f64. Durations add, subtract (checked or saturating), and multiply.
Instant is a monotonic clock reading: it never goes backwards, so it is the right tool for measuring how long something took. It has no meaning outside the running process. SystemTime is the wall clock: it can be shown to users and compared with UNIX_EPOCH, but it can jump when the OS clock changes. For calendars and time zones, use a crate such as chrono or jiff.
thread::sleep pauses the current thread for at least the given Duration. In async code, use the runtime's sleep instead so other tasks keep running.
Building and reading Durations
fn demo_duration() {
println!("-- Duration --");
let d = Duration::from_millis(1500);
println!(
"{}s {}ms subsec {}ms {:.3}s",
d.as_secs(),
d.as_millis(),
d.subsec_millis(),
d.as_secs_f64()
);
println!(
"{:?} {:?} {:?}",
Duration::from_secs(90),
Duration::from_micros(250),
Duration::from_secs_f64(0.125)
);
println!("ZERO {:?} MAX secs {}", Duration::ZERO, Duration::MAX.as_secs());
}Duration arithmetic
fn demo_duration_math() {
println!("-- Duration math --");
let a = Duration::from_secs(5);
let b = Duration::from_millis(1500);
println!("a + b {:?} a - b {:?} a * 3 {:?} a / 4 {:?}", a + b, a - b, a * 3, a / 4);
println!(
"checked_sub {:?} saturating_sub {:?}",
b.checked_sub(a),
b.saturating_sub(a)
);
println!("mul_f64 {:?}", a.mul_f64(0.1));
let total: Duration = [b, b, b].iter().sum();
println!("sum {total:?} max {:?}", a.max(b));
// Duration cannot be negative:
// let neg = b - a; // panics: overflow when subtracting durations
}Formatting a Duration for people
fn format_hms(d: Duration) -> String {
let s = d.as_secs();
format!("{:02}:{:02}:{:02}", s / 3600, (s / 60) % 60, s % 60)
}
fn demo_formatting() {
println!("-- formatting --");
for secs in [59, 3_725, 90_061] {
println!("{secs}s -> {}", format_hms(Duration::from_secs(secs)));
}
}Measuring elapsed time with Instant
fn demo_instant() {
println!("-- Instant --");
let start = Instant::now();
thread::sleep(Duration::from_millis(5));
let elapsed = start.elapsed();
println!("slept at least 5ms: {}", elapsed >= Duration::from_millis(5));
let later = Instant::now();
println!("monotonic: {}", later >= start);
println!("duration_since {:?}", later.duration_since(start) >= elapsed);
// Earlier minus later saturates to zero instead of going negative.
println!("reverse saturates to {:?}", start.saturating_duration_since(later));
// Timing a piece of work.
let t = Instant::now();
let sum: u64 = (0..1_000_000u64).sum();
println!(
"sum {sum} took less than a second: {}",
t.elapsed() < Duration::from_secs(1)
);
}Deadlines and timeouts
fn demo_deadline() {
println!("-- deadline --");
let deadline = Instant::now() + Duration::from_millis(20);
let mut rounds = 0;
while Instant::now() < deadline {
rounds += 1;
thread::sleep(Duration::from_millis(2));
}
println!("ran a few rounds before the deadline: {}", rounds > 1);
let remaining = deadline.checked_duration_since(Instant::now());
println!("time left after deadline {remaining:?}");
}Wall-clock time
fn demo_system_time() {
println!("-- SystemTime --");
let now = SystemTime::now();
let since_epoch = now.duration_since(UNIX_EPOCH).expect("clock is after 1970");
println!("unix seconds > 1.7e9: {}", since_epoch.as_secs() > 1_700_000_000);
let earlier = now - Duration::from_secs(60);
println!("one minute ago is earlier: {}", earlier < now);
println!(
"duration_since a later time is Err: {}",
earlier.duration_since(now).is_err()
);
let days = since_epoch.as_secs() / 86_400;
println!("days since epoch > 19000: {}", days > 19_000);
let t = UNIX_EPOCH + Duration::from_secs(1_000_000_000);
println!("1e9 seconds after epoch: {:?}", t.duration_since(UNIX_EPOCH).unwrap());
}Sleep and yield
fn demo_sleep() {
println!("-- sleep --");
let t = Instant::now();
thread::sleep(Duration::from_millis(3));
println!(
"sleep is at least as long as asked: {}",
t.elapsed() >= Duration::from_millis(3)
);
thread::yield_now(); // hint to the scheduler; sleep(Duration::ZERO) is not a reliable yield
println!("awake");
}$ cargo run --bin 50_time -- Duration -- 1s 1500ms subsec 500ms 1.500s 90s 250µs 125ms ZERO 0ns MAX secs 18446744073709551615 -- Duration math -- a + b 6.5s a - b 3.5s a * 3 15s a / 4 1.25s checked_sub None saturating_sub 0ns mul_f64 500ms sum 4.5s max 5s -- formatting -- 59s -> 00:00:59 3725s -> 01:02:05 90061s -> 25:01:01 -- Instant -- slept at least 5ms: true monotonic: true duration_since true reverse saturates to 0ns sum 499999500000 took less than a second: true -- deadline -- ran a few rounds before the deadline: true time left after deadline None -- SystemTime -- unix seconds > 1.7e9: true one minute ago is earlier: true duration_since a later time is Err: true days since epoch > 19000: true 1e9 seconds after epoch: 1000000000s -- sleep -- sleep is at least as long as asked: true awake
Full program
// 50. Duration, Instant, SystemTime, and sleep
//
// Duration is a non-negative span of time. Build one with from_secs, from_millis,
// from_micros, from_nanos, or from_secs_f64; read it back with as_secs, as_millis,
// subsec_millis, or as_secs_f64. Durations add, subtract (checked or saturating), and
// multiply.
//
// Instant is a monotonic clock reading: it never goes backwards, so it is the right
// tool for measuring how long something took. It has no meaning outside the running
// process. SystemTime is the wall clock: it can be shown to users and compared with
// UNIX_EPOCH, but it can jump when the OS clock changes. For calendars and time zones,
// use a crate such as chrono or jiff.
//
// thread::sleep pauses the current thread for at least the given Duration. In async
// code, use the runtime's sleep instead so other tasks keep running.
//
// Run: cargo run --bin 50_time
use std::thread;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
// Example 1: building and reading Durations.
fn demo_duration() {
println!("-- Duration --");
let d = Duration::from_millis(1500);
println!(
"{}s {}ms subsec {}ms {:.3}s",
d.as_secs(),
d.as_millis(),
d.subsec_millis(),
d.as_secs_f64()
);
println!(
"{:?} {:?} {:?}",
Duration::from_secs(90),
Duration::from_micros(250),
Duration::from_secs_f64(0.125)
);
println!("ZERO {:?} MAX secs {}", Duration::ZERO, Duration::MAX.as_secs());
}
// Example 2: Duration arithmetic.
fn demo_duration_math() {
println!("-- Duration math --");
let a = Duration::from_secs(5);
let b = Duration::from_millis(1500);
println!("a + b {:?} a - b {:?} a * 3 {:?} a / 4 {:?}", a + b, a - b, a * 3, a / 4);
println!(
"checked_sub {:?} saturating_sub {:?}",
b.checked_sub(a),
b.saturating_sub(a)
);
println!("mul_f64 {:?}", a.mul_f64(0.1));
let total: Duration = [b, b, b].iter().sum();
println!("sum {total:?} max {:?}", a.max(b));
// Duration cannot be negative:
// let neg = b - a; // panics: overflow when subtracting durations
}
fn format_hms(d: Duration) -> String {
let s = d.as_secs();
format!("{:02}:{:02}:{:02}", s / 3600, (s / 60) % 60, s % 60)
}
// Example 3: formatting a Duration for people.
fn demo_formatting() {
println!("-- formatting --");
for secs in [59, 3_725, 90_061] {
println!("{secs}s -> {}", format_hms(Duration::from_secs(secs)));
}
}
// Example 4: measuring elapsed time with Instant.
fn demo_instant() {
println!("-- Instant --");
let start = Instant::now();
thread::sleep(Duration::from_millis(5));
let elapsed = start.elapsed();
println!("slept at least 5ms: {}", elapsed >= Duration::from_millis(5));
let later = Instant::now();
println!("monotonic: {}", later >= start);
println!("duration_since {:?}", later.duration_since(start) >= elapsed);
// Earlier minus later saturates to zero instead of going negative.
println!("reverse saturates to {:?}", start.saturating_duration_since(later));
// Timing a piece of work.
let t = Instant::now();
let sum: u64 = (0..1_000_000u64).sum();
println!(
"sum {sum} took less than a second: {}",
t.elapsed() < Duration::from_secs(1)
);
}
// Example 5: deadlines and timeouts.
fn demo_deadline() {
println!("-- deadline --");
let deadline = Instant::now() + Duration::from_millis(20);
let mut rounds = 0;
while Instant::now() < deadline {
rounds += 1;
thread::sleep(Duration::from_millis(2));
}
println!("ran a few rounds before the deadline: {}", rounds > 1);
let remaining = deadline.checked_duration_since(Instant::now());
println!("time left after deadline {remaining:?}");
}
// Example 6: wall-clock time.
fn demo_system_time() {
println!("-- SystemTime --");
let now = SystemTime::now();
let since_epoch = now.duration_since(UNIX_EPOCH).expect("clock is after 1970");
println!("unix seconds > 1.7e9: {}", since_epoch.as_secs() > 1_700_000_000);
let earlier = now - Duration::from_secs(60);
println!("one minute ago is earlier: {}", earlier < now);
println!(
"duration_since a later time is Err: {}",
earlier.duration_since(now).is_err()
);
let days = since_epoch.as_secs() / 86_400;
println!("days since epoch > 19000: {}", days > 19_000);
let t = UNIX_EPOCH + Duration::from_secs(1_000_000_000);
println!("1e9 seconds after epoch: {:?}", t.duration_since(UNIX_EPOCH).unwrap());
}
// Example 7: sleep and yield.
fn demo_sleep() {
println!("-- sleep --");
let t = Instant::now();
thread::sleep(Duration::from_millis(3));
println!(
"sleep is at least as long as asked: {}",
t.elapsed() >= Duration::from_millis(3)
);
thread::yield_now(); // hint to the scheduler; sleep(Duration::ZERO) is not a reliable yield
println!("awake");
}
fn main() {
demo_duration();
demo_duration_math();
demo_formatting();
demo_instant();
demo_deadline();
demo_system_time();
demo_sleep();
}