Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Duration and Calculation

Measure the elapsed time between two code sections

std-badge cat-time-badge

Measures time::Instant::elapsed since time::Instant::now.

Calling time::Instant::elapsed returns a time::Duration that we print at the end of the recipe. This method will not mutate or reset the time::Instant object.

use std::time::{Duration, Instant};
use std::thread;

fn expensive_function() {
    thread::sleep(Duration::from_secs(1));
}

fn main() {
    let start = Instant::now();
    expensive_function();
    let duration = start.elapsed();

    println!("Time elapsed in expensive_function() is: {:?}", duration);
}

Deadline arithmetic with Instant

std-badge cat-time-badge

Calculates a one second Duration. Computes deadline one second from Instant::now. Sleeps for one second and compares deadline with Instant::now to check if the deadline has passed.

use std::thread;
use std::time::{Duration, Instant};
fn sleep(duration: Duration) {
   thread::sleep(duration);
}

fn main() {
    let one_second = Duration::from_secs(1);
    let deadline = Instant::now() + one_second;

    sleep(Duration::from_secs(1));
    if Instant::now() > deadline {
        println!("Deadline has passed");
    }
}

Convert SystemTime to Unix timestamp

std-badge cat-time-badge

Converts the current SystemTime to seconds since the Unix epoch, then computes the original time by adding the unix timestamp to SystemTime::UNIX_EPOCH constant.

use std::time::{SystemTime, SystemTimeError};

fn main() -> Result<(), SystemTimeError> {
    let now = SystemTime::now();
    let since_unix_epoch = now.duration_since(SystemTime::UNIX_EPOCH)?;
    println!("Unix timestamp: {}", since_unix_epoch.as_secs());

    let from_unix_timestamp = SystemTime::UNIX_EPOCH + since_unix_epoch;
    println!("Back to SystemTime: {:?}", from_unix_timestamp);

    Ok(())
}

Benchmark a closure with Instant

std-badge cat-time-badge

Initializes a weights vector, calculates half of its total sum into half_load, and uses benchmark to measure the performance of subset_sum which takes a slice of weights and a target value and finds a subset whose weights sum to the target.

benchmark measures the average time required to call a closure a specified number of times using Instant::now and Instant::elapsed. It uses black_box to prevent the compiler from optimizing away the closure’s computation since its return value is ignored.

use std::time::{Duration, Instant};

fn subset_sum(weights: &[u64], target: u64) -> Option<u32> {
    for mask in 0..1u32 << weights.len() {
        let sum: u64 = weights
            .iter()
            .enumerate()
            .filter(|(i, _)| mask >> i & 1 == 1)
            .map(|(_, weight)| weight)
            .sum();

        if sum == target {
            return Some(mask);
        }
    }
    None
}

fn benchmark<F, T>(runs: u32, mut f: F) -> Duration
where
    F: FnMut() -> T,
{
    let start = Instant::now();

    for _ in 0..runs {
        std::hint::black_box(f());
    }

    start.elapsed() / runs
}

fn main() {
    let weights: Vec<u64> = (1..=18).map(|kg| kg * 2).collect();
    let half_load = weights.iter().sum::<u64>() / 2;

    for parcels in 12..=weights.len() {
        let mean = benchmark(3, || subset_sum(&weights[..parcels], half_load));
        println!("{:2} parcels: {:>10.2?}", parcels, mean);
    }
}

Perform checked date and time calculations

chrono-badge cat-date-and-time-badge

Calculates and displays the date and time two weeks from now using DateTime::checked_add_signed and the date of the day before that using DateTime::checked_sub_signed. The methods return None if the date and time cannot be calculated.

Escape sequences that are available for the DateTime::format can be found at chrono::format::strftime.

use chrono::{DateTime, Duration, Utc};

fn day_earlier(date_time: DateTime<Utc>) -> Option<DateTime<Utc>> {
    date_time.checked_sub_signed(Duration::days(1))
}

fn main() {
    let now = Utc::now();
    println!("{}", now);

    let almost_three_weeks_from_now = now.checked_add_signed(Duration::weeks(2))
            .and_then(|in_2weeks| in_2weeks.checked_add_signed(Duration::weeks(1)))
            .and_then(day_earlier);

    match almost_three_weeks_from_now {
        Some(x) => println!("{}", x),
        None => eprintln!("Almost three weeks from now overflows!"),
    }

    match now.checked_add_signed(Duration::max_value()) {
        Some(x) => println!("{}", x),
        None => eprintln!("We can't use chrono to tell the time for the Solar System to complete more than one full orbit around the galactic center."),
    }
}

Convert a local time to another timezone

chrono-badge cat-date-and-time-badge

Gets the local time and displays it using offset::Local::now and then converts it to the UTC standard using the DateTime::from_utc struct method. A time is then converted using the offset::FixedOffset struct and the UTC time is then converted to UTC+8 and UTC-2.

use chrono::{DateTime, FixedOffset, Local, Utc};

fn main() {
    let local_time = Local::now();
    let utc_time = DateTime::<Utc>::from_utc(local_time.naive_utc(), Utc);
    let china_timezone = FixedOffset::east(8 * 3600);
    let rio_timezone = FixedOffset::west(2 * 3600);
    println!("Local time now is {}", local_time);
    println!("UTC time now is {}", utc_time);
    println!(
        "Time in Hong Kong now is {}",
        utc_time.with_timezone(&china_timezone)
    );
    println!("Time in Rio de Janeiro now is {}", utc_time.with_timezone(&rio_timezone));
}