🎓 A1Learner
🔍
0 of 149 lessons completed

Rust Times of Day

`NaiveTime` holds a time of day. `NaiveDateTime` joins a time of day to a date.

Make a time of day

The constructor takes hours, minutes, and seconds:

let time = NaiveTime::from_hms_opt(9, 30, 15).unwrap();
println!("time = {}", time);

Read the pieces

`Timelike` is the trait for clock pieces. Bring it into scope first:

use chrono::Timelike;
let time = NaiveTime::from_hms_opt(9, 30, 15).unwrap();
println!("hour = {}", time.hour());
println!("minute = {}", time.minute());
println!("second = {}", time.second());

A bad clock reading says no

Hour 24 is not a normal time of day. The `_opt` form returns `None`:

println!("hour 24 exists = {}", NaiveTime::from_hms_opt(24, 0, 0).is_some());

Join a date and a time

A date can grow a time. You can build the pair in two steps or in one call:

let date = NaiveDate::from_ymd_opt(2026, 10, 22).unwrap();
let time = NaiveTime::from_hms_opt(9, 30, 15).unwrap();
let joined = date.and_time(time);
let direct = date.and_hms_opt(9, 30, 15).unwrap();
println!("same value = {}", joined == direct);
println!("joined = {}", joined);

Split the pair again

`.date()` and `.time()` hand the two parts back:

use chrono::Datelike;
let moment = NaiveDate::from_ymd_opt(2026, 10, 22).unwrap().and_hms_opt(9, 30, 15).unwrap();
println!("date = {}", moment.date());
println!("time = {}", moment.time());
println!("weekday = {:?}", moment.weekday());

Step across midnight

Add three hours to a late start. The clock wraps. The date moves too:

let late = NaiveDate::from_ymd_opt(2026, 10, 22).unwrap().and_hms_opt(22, 30, 0).unwrap();
let later = late + TimeDelta::hours(3);
println!("later = {}", later);

Example

// Cargo.toml: chrono = "0.4" (verified with chrono 0.4.45)
use chrono::{NaiveDate, NaiveTime, TimeDelta};

fn main() {
    let date = NaiveDate::from_ymd_opt(2026, 11, 3).unwrap();
    let time = NaiveTime::from_hms_opt(16, 45, 0).unwrap();
    let start = date.and_time(time);
    let end = start + TimeDelta::minutes(95);
    println!("starts {} on {}", start.time(), start.format("%A %d %B"));
    println!("ends {} on {}", end.time(), end.format("%A %d %B"));
    println!("length = {} minutes", end.signed_duration_since(start).num_minutes());
}

Key points

  • `NaiveTime`: one time of day.
  • It holds no date and no zone.
  • Use `NaiveTime::from_hms_opt` to build a time.
  • It returns `None` for a time that cannot exist.
  • Use `and_time` to join a `NaiveDate` and a `NaiveTime`.
  • The result is a `NaiveDateTime`.
  • `Timelike` gives the pieces of a time.
  • Use `hour()`, `minute()`, and `second()`.
  • Add a `TimeDelta` to move across midnight.
  • The date part moves with the clock.

In this example, a date and a time are built apart. `and_time` joins them into one start moment. Adding 95 minutes gives the end moment. The end stays on the same date here. The gap reads back as 95 minutes.

Note

Naive means no zone is attached.

It does not mean the value is rough or unsafe.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

Which type fits “14:05 on 3 May”, with no zone named?