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

Date and Time with time

time is a smaller date and time crate. It has no time zone database, only fixed UTC offsets. Formats are written as compile-time checked format descriptions. These recipes show where time differs from chrono and jiff; see Choosing between chrono, time and jiff for how they compare.

Examine the current time with a UTC offset

time Date and time

Use time when fixed UTC offsets are enough and you want a small API; see Choosing between chrono, time and jiff. Gets the current OffsetDateTime in UTC and converts it to a fixed offset with OffsetDateTime::to_offset. time has no time zone database, so named zones such as Asia/Tokyo are not available and daylight saving time is never applied. If you need either, use jiff or chrono with chrono-tz.

use time::{OffsetDateTime, UtcOffset};

fn main() -> Result<(), time::error::ComponentRange> {
    let now = OffsetDateTime::now_utc();
    println!("UTC time:   {now}");

    // `time` has no time zone database, only fixed UTC offsets.
    let tokyo = now.to_offset(UtcOffset::from_hms(9, 0, 0)?);
    println!("UTC+09:00:  {tokyo}");

    println!(
        "Year {}, month {}, day {}, weekday {}",
        now.year(),
        now.month(),
        now.day(),
        now.weekday()
    );
    println!(
        "Time {:02}:{:02}:{:02}",
        now.hour(),
        now.minute(),
        now.second()
    );
    Ok(())
}

Parse and format a datetime with format descriptions

time Date and time

Use time when you want format strings checked at compile time; see Choosing between chrono, time and jiff. Parses an RFC 3339 string with OffsetDateTime::parse and Rfc3339. Custom patterns are written with the format_description! macro, so a typo in "[hour repr:12]" is a build error rather than a runtime one, and used with OffsetDateTime::format and Date::parse. Invalid input returns an Err.

This recipe requires the formatting, macros and parsing feature flags of time to be enabled in Cargo.toml.

use time::format_description::well_known::Rfc3339;
use time::macros::format_description;
use time::{Date, OffsetDateTime};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let parsed = OffsetDateTime::parse("2024-07-11T01:14:00-04:00", &Rfc3339)?;
    println!("Parsed:    {parsed}");

    let format = format_description!(
        "[weekday], [month repr:long] [day padding:none], [year] at [hour repr:12 padding:none]:[minute] [period] [offset_hour sign:mandatory]:[offset_minute]"
    );
    println!("Formatted: {}", parsed.format(&format)?);

    // Parsing with a custom format description.
    let date = Date::parse("11/07/2024", format_description!("[day]/[month]/[year]"))?;
    println!("Custom:    {date}");

    // Invalid input is an `Err`, not a panic.
    let bad = OffsetDateTime::parse("not a date", &Rfc3339);
    println!("Invalid:   {}", bad.is_err());
    Ok(())
}

Perform checked date and time calculations with Duration

time Date and time

Use time when exact elapsed time is what you want; see Choosing between chrono, time and jiff. Adds a Duration with OffsetDateTime::checked_add, which returns None on overflow. A Duration is an exact length of time, so a day is always 24 hours and daylight saving time is not applied: this is the opposite of the jiff Span recipe, where adding a day can be 23 or 25 hours. Subtracting two datetimes gives the Duration between them.

This recipe requires the macros feature flag of time to be enabled in Cargo.toml.

use time::macros::datetime;
use time::{Duration, OffsetDateTime};

fn main() {
    let start = datetime!(2024-03-09 12:00 -5);

    // A `Duration` is an exact length of time, so a "day" is always 24 hours.
    // There is no time zone database, so DST changes are not applied.
    let next_day = start.checked_add(Duration::days(1));
    println!("{start} + 1 day = {next_day:?}");

    let later = start
        .checked_add(Duration::weeks(2))
        .and_then(|t| t.checked_add(Duration::hours(27)));
    println!("Two weeks and 27 hours later: {later:?}");

    // `checked_add` returns `None` on overflow instead of panicking.
    let overflow = start.checked_add(Duration::MAX);
    println!("Overflow is None: {}", overflow.is_none());

    let end: OffsetDateTime = datetime!(2024-03-12 09:30 -4);
    let diff = end - start;
    println!(
        "Until {end}: {}h {}m",
        diff.whole_hours(),
        diff.whole_minutes() % 60
    );
}