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
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
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,macrosandparsingfeature flags oftimeto be enabled inCargo.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
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
macrosfeature flag oftimeto be enabled inCargo.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
);
}