Date and Time Handling in Rust with Chrono

The chrono crate is the standard way to work with dates and times in Rust. It helps you parse, format, and perform arithmetic on dates and times, whether you are building logs, schedulers, or working with timestamps from APIs.

I first used chrono when logging events in a CLI tool. I needed readable timestamps, but I also wanted to sort and calculate durations. Chrono handled everything I needed, from getting the current time to formatting it exactly how I wanted, all with full type safety.

This article will show you how to use chrono to work with current time, format it, parse strings into dates, perform time arithmetic, and work with time zones.

Add chrono to Your Project

In Cargo.toml:

[dependencies]
chrono = "0.4"

Chrono supports both naive (timezone-unaware) and UTC/local time handling.

Getting the Current Time

Use Utc::now() or Local::now():

use chrono::Utc;

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

For local time:

use chrono::Local;

fn main() {
    let local = Local::now();
    println!("Local time: {}", local);
}

Both give you a DateTime object.

Formatting Dates and Times

Use format with strftime-like strings:

use chrono::Local;

fn main() {
    let now = Local::now();
    let formatted = now.format("%Y-%m-%d %H:%M:%S");
    println!("Formatted: {}", formatted);
}

Common format patterns:

  • %Y = Year
  • %m = Month
  • %d = Day
  • %H:%M:%S = Hours:Minutes:Seconds

Parsing Strings into DateTime

You can turn strings into NaiveDateTime:

use chrono::NaiveDateTime;

fn main() {
    let input = "2025-06-10 18:00:00";
    let dt = NaiveDateTime::parse_from_str(input, "%Y-%m-%d %H:%M:%S")
        .expect("Invalid date");
    println!("Parsed: {}", dt);
}

This is useful when reading logs or config files.

Time Arithmetic

You can add or subtract durations:

use chrono::{Duration, Utc};

fn main() {
    let now = Utc::now();
    let later = now + Duration::days(3);
    let earlier = now - Duration::hours(5);

    println!("3 days later: {}", later);
    println!("5 hours earlier: {}", earlier);
}

Duration supports days, hours, minutes, seconds, and milliseconds.

Getting Date Components

You can access year, month, day, etc:

let date = Utc::now().date_naive();
println!("Year: {}", date.year());
println!("Month: {}", date.month());
println!("Day: {}", date.day());

Useful for grouping or filtering by date parts.

Timestamps

To get a Unix timestamp:

let now = Utc::now();
let timestamp = now.timestamp(); // seconds since epoch
println!("Timestamp: {}", timestamp);

To convert from timestamp:

let dt = chrono::NaiveDateTime::from_timestamp_opt(1_600_000_000, 0)
    .expect("Invalid timestamp");
println!("DateTime: {}", dt);

You can also use timestamp_millis or timestamp_nanos.

Working with Time Zones

You can convert between time zones:

use chrono::{Utc, Local};

let utc_time = Utc::now();
let local_time = utc_time.with_timezone(&Local);
println!("Local time: {}", local_time);

Chrono does not handle timezone database lookups (like IANA), but it supports UTC and system-local conversion.

Summary

The chrono crate makes it easy to work with dates and times in Rust. From formatting to arithmetic to converting between UTC and local, it covers the core functionality every application needs. Whether you are scheduling tasks or printing logs, Chrono helps you do it safely and correctly.