Loading page…
Rust walkthroughs
Loading page…
The chrono crate is the de facto standard for date and time handling in Rust. It provides types for dates, times, datetimes, durations, and timezones. Chrono focuses on correctness, ergonomics, and interoperability with the standard library. It handles parsing, formatting, arithmetic, timezone conversions, and more.
Key types:
DateTime<Utc> — datetime with UTC timezoneDateTime<Local> — datetime in local timezoneNaiveDateTime — datetime without timezoneNaiveDate — date without timezoneNaiveTime — time without timezoneDuration — span of timeChrono is feature-rich and well-tested for real-world datetime handling.
# Cargo.toml
[dependencies]
chrono = "0.4"use chrono::{DateTime, Utc, Local, NaiveDate, NaiveTime, NaiveDateTime, Duration};
fn main() {
// Current time
let now_utc: DateTime<Utc> = Utc::now();
let now_local: DateTime<Local> = Local::now();
println!("UTC: {}", now_utc);
println!("Local: {}", now_local);
// Create specific date and time
let date = NaiveDate::from_ymd_opt(2024, 3, 15).unwrap();
let time = NaiveTime::from_hms_opt(14, 30, 0).unwrap();
let datetime = NaiveDateTime::new(date, time);
println!("DateTime: {}", datetime);
}use chrono::{NaiveDate, NaiveTime, NaiveDateTime, DateTime, Utc, Local, TimeZone};
fn main() {
// Create a date
let date1 = NaiveDate::from_ymd_opt(2024, 3, 15).unwrap();
println!("Date: {}", date1);
// Create a date from ordinal (year, day of year)
let date2 = NaiveDate::from_yo_opt(2024, 75).unwrap(); // 75th day of 2024
println!("From ordinal: {}", date2);
// Create a date from ISO week
let date3 = NaiveDate::from_isoywd_opt(2024, 10, chrono::Weekday::Mon).unwrap();
println!("From ISO week: {}", date3);
// Parse a date from string
let date4 = NaiveDate::parse_from_str("2024-03-15", "%Y-%m-%d").unwrap();
println!("Parsed date: {}", date4);
// Create a time
let time1 = NaiveTime::from_hms_opt(14, 30, 45).unwrap();
println!("Time: {}", time1);
let time2 = NaiveTime::from_hms_milli_opt(14, 30, 45, 500).unwrap();
println!("Time with millis: {}", time2);
let time3 = NaiveTime::from_hms_micro_opt(14, 30, 45, 500_000).unwrap();
println!("Time with micros: {}", time3);
// Parse time from string
let time4 = NaiveTime::parse_from_str("14:30:45", "%H:%M:%S").unwrap();
println!("Parsed time: {}", time4);
// Combine date and time
let datetime = NaiveDateTime::new(date1, time1);
println!("DateTime: {}", datetime);
// Create DateTime with timezone
let utc_dt = Utc.with_ymd_and_hms(2024, 3, 15, 14, 30, 45).unwrap();
println!("UTC DateTime: {}", utc_dt);
let local_dt = Local.with_ymd_and_hms(2024, 3, 15, 14, 30, 45).unwrap();
println!("Local DateTime: {}", local_dt);
}use chrono::{DateTime, Utc, Local, FixedOffset, TimeZone};
fn main() {
// Current time in different timezones
let utc_now: DateTime<Utc> = Utc::now();
let local_now: DateTime<Local> = Local::now();
println!("UTC now: {}", utc_now);
println!("Local now: {}", local_now);
println!("Local timezone: {}", local_now.timezone());
// Create a fixed offset timezone (UTC+8)
let east8 = FixedOffset::east_opt(8 * 3600).unwrap();
let dt_east8 = east8.from_utc_datetime(&utc_now.naive_utc());
println!("UTC+8: {}", dt_east8);
// Create a fixed offset timezone (UTC-5)
let west5 = FixedOffset::west_opt(5 * 3600).unwrap();
let dt_west5 = west5.from_utc_datetime(&utc_now.naive_utc());
println!("UTC-5: {}", dt_west5);
// Convert between timezones
let utc_dt = Utc.with_ymd_and_hms(2024, 3, 15, 14, 30, 0).unwrap();
let local_dt: DateTime<Local> = utc_dt.into();
println!("\nConverted UTC to local: {}", local_dt);
// Get timezone offset
let offset = local_now.offset();
println!("Local offset: {}", offset);
// Unix timestamp
let timestamp = utc_now.timestamp();
println!("\nUnix timestamp: {}", timestamp);
// From timestamp
let from_timestamp = Utc.timestamp_opt(timestamp, 0).unwrap();
println!("From timestamp: {}", from_timestamp);
}use chrono::{DateTime, Utc, NaiveDate, NaiveDateTime};
fn main() {
let dt = Utc.with_ymd_and_hms(2024, 3, 15, 14, 30, 45).unwrap();
// Common formats
println!("Default: {}", dt);
println!("RFC 2822: {}", dt.to_rfc2822());
println!("RFC 3339: {}", dt.to_rfc3339());
// Custom formatting
println!("\nCustom formats:");
println!("Date: {}", dt.format("%Y-%m-%d"));
println!("Time: {}", dt.format("%H:%M:%S"));
println!("DateTime: {}", dt.format("%Y-%m-%d %H:%M:%S"));
println!("US format: {}", dt.format("%m/%d/%Y %I:%M %p"));
println!("European: {}", dt.format("%d.%m.%Y %H:%M"));
println!("Verbose: {}", dt.format("%A, %B %d, %Y at %I:%M %p"));
// Format specifiers
println!("\nFormat specifiers:");
println!("Year: {}", dt.format("%Y")); // 2024
println!("Year (short): {}", dt.format("%y")); // 24
println!("Month: {}", dt.format("%m")); // 03
println!("Month name: {}", dt.format("%B")); // March
println!("Month (short): {}", dt.format("%b")); // Mar
println!("Day: {}", dt.format("%d")); // 15
println!("Weekday: {}", dt.format("%A")); // Friday
println!("Weekday (short): {}", dt.format("%a")); // Fri
println!("Hour (24): {}", dt.format("%H")); // 14
println!("Hour (12): {}", dt.format("%I")); // 02
println!("Minute: {}", dt.format("%M")); // 30
println!("Second: {}", dt.format("%S")); // 45
println!("AM/PM: {}", dt.format("%p")); // PM
// Parsing
println!("\nParsing:");
let parsed1 = NaiveDate::parse_from_str("2024-03-15", "%Y-%m-%d").unwrap();
println!("Parsed date: {}", parsed1);
let parsed2 = NaiveDateTime::parse_from_str(
"2024-03-15 14:30:45",
"%Y-%m-%d %H:%M:%S"
).unwrap();
println!("Parsed datetime: {}", parsed2);
let parsed3 = DateTime::parse_from_rfc3339("2024-03-15T14:30:45Z").unwrap();
println!("Parsed RFC 3339: {}", parsed3);
let parsed4 = DateTime::parse_from_rfc2822("Fri, 15 Mar 2024 14:30:45 +0000").unwrap();
println!("Parsed RFC 2822: {}", parsed4);
// Parse with timezone
let parsed5 = DateTime::parse_from_str(
"2024-03-15 14:30:45 +0800",
"%Y-%m-%d %H:%M:%S %z"
).unwrap();
println!("Parsed with TZ: {}", parsed5);
}use chrono::{Duration, NaiveDate, NaiveDateTime, DateTime, Utc, Days, Months};
fn main() {
let dt = Utc.with_ymd_and_hms(2024, 3, 15, 14, 30, 0).unwrap();
println!("Original: {}", dt);
// Add/subtract durations
let tomorrow = dt + Duration::days(1);
let yesterday = dt - Duration::days(1);
let next_week = dt + Duration::weeks(1);
let last_hour = dt - Duration::hours(1);
let in_30_min = dt + Duration::minutes(30);
let in_5_sec = dt + Duration::seconds(5);
println!("\nDuration arithmetic:");
println!("+1 day: {}", tomorrow);
println!("-1 day: {}", yesterday);
println!("+1 week: {}", next_week);
println!("-1 hour: {}", last_hour);
println!("+30 min: {}", in_30_min);
println!("+5 sec: {}", in_5_sec);
// Duration from components
let duration = Duration::new(3600, 500_000_000); // 3600 seconds + 500ms
println!("\nCustom duration: {} seconds", duration.num_seconds());
// Difference between dates
let date1 = NaiveDate::from_ymd_opt(2024, 3, 15).unwrap();
let date2 = NaiveDate::from_ymd_opt(2024, 3, 20).unwrap();
let diff = date2 - date1;
println!("\nDifference: {} days", diff.num_days());
// Compare dates
println!("date1 < date2: {}", date1 < date2);
// Add days (checked)
let date = NaiveDate::from_ymd_opt(2024, 3, 15).unwrap();
let future_date = date.checked_add_days(Days::new(10)).unwrap();
println!("\n+10 days: {}", future_date);
// Add months (handles month boundaries)
let jan_31 = NaiveDate::from_ymd_opt(2024, 1, 31).unwrap();
let feb = jan_31.checked_add_months(Months::new(1)).unwrap();
println!("Jan 31 + 1 month: {}", feb); // Feb 29 (leap year)
// Calculate age
let birth_date = NaiveDate::from_ymd_opt(1990, 6, 15).unwrap();
let today = Utc::now().date_naive();
let age = today.years_since(birth_date).unwrap();
println!("\nAge: {} years", age);
}use chrono::{DateTime, Utc, Datelike, Timelike, Weekday};
fn main() {
let dt = Utc.with_ymd_and_hms(2024, 3, 15, 14, 30, 45).unwrap();
// Date components
println!("Date components:");
println!(" Year: {}", dt.year());
println!(" Month: {}", dt.month());
println!(" Day: {}", dt.day());
println!(" Ordinal (day of year): {}", dt.ordinal());
println!(" Weekday: {}", dt.weekday());
// Time components
println!("\nTime components:");
println!(" Hour: {}", dt.hour());
println!(" Minute: {}", dt.minute());
println!(" Second: {}", dt.second());
println!(" Nanosecond: {}", dt.nanosecond());
// Weekday checks
println!("\nWeekday:");
println!(" Is weekday: {}", !matches!(dt.weekday(), Weekday::Sat | Weekday::Sun));
println!(" Is weekend: {}", matches!(dt.weekday(), Weekday::Sat | Weekday::Sun));
println!(" Is Friday: {}", dt.weekday() == Weekday::Fri);
// Week of year
let iso_week = dt.iso_week();
println!("\nISO Week:");
println!(" Week number: {}", iso_week.week());
println!(" Year: {}", iso_week.year());
// Quarter
let quarter = (dt.month() - 1) / 3 + 1;
println!("\nQuarter: Q{}", quarter);
// Check if leap year
let year = dt.year();
let is_leap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
println!("Is leap year: {}", is_leap);
// Days in month
let days_in_month = dt.with_day(1).unwrap()
.with_month(dt.month() % 12 + 1).unwrap()
.pred_opt().unwrap()
.day();
println!("Days in month: {}", days_in_month);
// Time of day checks
let hour = dt.hour();
if hour < 12 {
println!("\nGood morning!");
} else if hour < 17 {
println!("\nGood afternoon!");
} else {
println!("\nGood evening!");
}
}use chrono::{DateTime, Utc, Duration, NaiveDate};
fn main() {
// Create Duration from various units
let d1 = Duration::seconds(90);
let d2 = Duration::minutes(5);
let d3 = Duration::hours(2);
let d4 = Duration::days(7);
let d5 = Duration::weeks(2);
println!("Duration from units:");
println!(" 90 seconds: {} seconds", d1.num_seconds());
println!(" 5 minutes: {} seconds", d2.num_seconds());
println!(" 2 hours: {} minutes", d3.num_minutes());
println!(" 7 days: {} hours", d4.num_hours());
println!(" 2 weeks: {} days", d5.num_days());
// Duration arithmetic
let combined = Duration::hours(1) + Duration::minutes(30);
println!("\n1h + 30m = {} minutes", combined.num_minutes());
let doubled = Duration::hours(2) * 2;
println!("2h * 2 = {} hours", doubled.num_hours());
// Difference between DateTimes
let start = Utc.with_ymd_and_hms(2024, 3, 15, 9, 0, 0).unwrap();
let end = Utc.with_ymd_and_hms(2024, 3, 15, 17, 30, 0).unwrap();
let elapsed = end - start;
println!("\nWork day: {} hours {} minutes",
elapsed.num_hours(),
elapsed.num_minutes() % 60);
// Calculate time until event
let now = Utc::now();
let event = Utc.with_ymd_and_hms(2024, 12, 25, 0, 0, 0).unwrap();
let until = event - now;
println!("\nUntil Christmas: {} days", until.num_days());
// Age calculation
let birth = NaiveDate::from_ymd_opt(1990, 6, 15).unwrap();
let today = Utc::now().date_naive();
let age_duration = today - birth;
println!("\nAge in days: {}", age_duration.num_days());
println!("Age in years (approx): {}", age_duration.num_days() / 365);
// Countdown timer
let deadline = Utc::now() + Duration::hours(24);
let remaining = deadline - Utc::now();
println!("\nDeadline in {} hours", remaining.num_hours());
}use chrono::{NaiveDate, Duration, Days};
fn main() {
// Iterate over a range of dates
let start = NaiveDate::from_ymd_opt(2024, 3, 1).unwrap();
let end = NaiveDate::from_ymd_opt(2024, 3, 7).unwrap();
println!("Week of March 2024:");
let mut current = start;
while current <= end {
println!(" {} - {}", current.format("%Y-%m-%d"), current.weekday());
current = current + Duration::days(1);
}
// Generate all days in a month
println!("\nAll days in March 2024:");
let march_1 = NaiveDate::from_ymd_opt(2024, 3, 1).unwrap();
let april_1 = NaiveDate::from_ymd_opt(2024, 4, 1).unwrap();
let days_in_march: Vec<NaiveDate> = (0..)
.map(|i| march_1.checked_add_days(Days::new(i)).unwrap())
.take_while(|&d| d < april_1)
.collect();
for day in &days_in_march {
println!(" {}", day.format("%a %d"));
}
println!("Total days: {}", days_in_march.len());
// Find all weekends in a month
println!("\nWeekends in March 2024:");
for day in &days_in_march {
if matches!(day.weekday(), chrono::Weekday::Sat | chrono::Weekday::Sun) {
println!(" {} - {}", day.format("%Y-%m-%d"), day.weekday());
}
}
// Get all Mondays in a range
println!("\nMondays in range:");
for day in &days_in_march {
if day.weekday() == chrono::Weekday::Mon {
println!(" {}", day.format("%Y-%m-%d"));
}
}
}use chrono::{NaiveDate, NaiveDateTime, NaiveTime, DateTime, Utc};
fn parse_date_flexible(input: &str) -> Option<NaiveDate> {
// Try various common formats
let formats = [
"%Y-%m-%d", // 2024-03-15
"%d/%m/%Y", // 15/03/2024
"%m/%d/%Y", // 03/15/2024
"%Y%m%d", // 20240315
"%d-%b-%Y", // 15-Mar-2024
"%d %B %Y", // 15 March 2024
"%B %d, %Y", // March 15, 2024
];
for fmt in &formats {
if let Ok(date) = NaiveDate::parse_from_str(input, fmt) {
return Some(date);
}
}
None
}
fn main() {
// Parse various date formats
let date_strings = [
"2024-03-15",
"15/03/2024",
"03/15/2024",
"20240315",
"15-Mar-2024",
"15 March 2024",
"March 15, 2024",
];
println!("Parsing dates:");
for s in &date_strings {
match parse_date_flexible(s) {
Some(date) => println!(" '{}' -> {}", s, date),
None => println!(" '{}' -> Failed to parse", s),
}
}
// Parse datetime with timezone
let inputs = [
"2024-03-15T14:30:45Z",
"2024-03-15T14:30:45+00:00",
"2024-03-15T14:30:45-05:00",
"2024-03-15 14:30:45",
];
println!("\nParsing datetimes:");
for input in &inputs {
if let Ok(dt) = DateTime::parse_from_rfc3339(input) {
println!(" '{}' -> {}", input, dt);
} else if let Ok(dt) = NaiveDateTime::parse_from_str(input, "%Y-%m-%d %H:%M:%S") {
println!(" '{}' -> {} (naive)", input, dt);
} else {
println!(" '{}' -> Failed", input);
}
}
}use chrono::{DateTime, Utc, Local, NaiveDate, Duration, Datelike, TimeZone};
fn format_elapsed(seconds: i64) -> String {
if seconds < 60 {
format!("{} seconds ago", seconds)
} else if seconds < 3600 {
format!("{} minutes ago", seconds / 60)
} else if seconds < 86400 {
format!("{} hours ago", seconds / 3600)
} else {
format!("{} days ago", seconds / 86400)
}
}
fn is_business_day(date: NaiveDate) -> bool {
!matches!(date.weekday(), chrono::Weekday::Sat | chrono::Weekday::Sun)
}
fn next_business_day(date: NaiveDate) -> NaiveDate {
let mut next = date + Duration::days(1);
while !is_business_day(next) {
next = next + Duration::days(1);
}
next
}
fn days_until_deadline(deadline: NaiveDate) -> i64 {
let today = Utc::now().date_naive();
(deadline - today).num_days()
}
fn format_datetime_friendly(dt: DateTime<Local>) -> String {
let now = Local::now();
let diff = now - dt;
if diff.num_minutes() < 1 {
"just now".to_string()
} else if diff.num_hours() < 1 {
format!("{} minutes ago", diff.num_minutes())
} else if diff.num_days() < 1 {
format!("{} hours ago", diff.num_hours())
} else if diff.num_days() < 7 {
format!("{} days ago", diff.num_days())
} else {
dt.format("%b %d, %Y").to_string()
}
}
fn main() {
// Time elapsed
println!("Time elapsed:");
println!(" 30 seconds: {}", format_elapsed(30));
println!(" 5 minutes: {}", format_elapsed(300));
println!(" 2 hours: {}", format_elapsed(7200));
println!(" 3 days: {}", format_elapsed(259200));
// Business days
let friday = NaiveDate::from_ymd_opt(2024, 3, 15).unwrap();
let saturday = NaiveDate::from_ymd_opt(2024, 3, 16).unwrap();
println!("\nBusiness days:");
println!(" {} is business day: {}", friday, is_business_day(friday));
println!(" {} is business day: {}", saturday, is_business_day(saturday));
println!(" Next business day after Fri: {}", next_business_day(friday));
println!(" Next business day after Sat: {}", next_business_day(saturday));
// Deadline countdown
let deadline = NaiveDate::from_ymd_opt(2024, 12, 31).unwrap();
println!("\nDays until deadline: {}", days_until_deadline(deadline));
// Friendly datetime
let past = Local.with_ymd_and_hms(2024, 3, 15, 10, 0, 0).unwrap();
println!("\nFriendly format: {}", format_datetime_friendly(past));
}# Cargo.toml
[dependencies]
chrono = { version = "0.4", features = ["serde"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"use chrono::{DateTime, Utc, NaiveDate};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Event {
name: String,
#[serde(with = "chrono::serde::ts_seconds")]
timestamp: DateTime<Utc>,
date: NaiveDate,
}
fn main() {
let event = Event {
name: "Conference".to_string(),
timestamp: Utc.with_ymd_and_hms(2024, 6, 15, 9, 0, 0).unwrap(),
date: NaiveDate::from_ymd_opt(2024, 6, 15).unwrap(),
};
// Serialize
let json = serde_json::to_string(&event).unwrap();
println!("JSON: {}", json);
// Deserialize
let decoded: Event = serde_json::from_str(&json).unwrap();
println!("Decoded: {:?}", decoded);
}chrono crate for date and time handling in RustUtc::now() and Local::now() for current datetimeNaiveDate::from_ymd_opt(year, month, day) to create datesNaiveTime::from_hms_opt(hour, minute, second) to create timesDateTime<Utc> and DateTime<Local> for timezone-aware datetimes.format("pattern") for custom formatting%Y-%m-%d, %H:%M:%S, %Y-%m-%d %H:%M:%Sparse_from_str(input, pattern)Duration for time spans: Duration::days(n), Duration::hours(n)+ Duration and - DurationDatelike trait for date components: .year(), .month(), .day()Timelike trait for time components: .hour(), .minute(), .second().weekday() returns Weekday enum (Mon, Tue, Wed, Thu, Fri, Sat, Sun).timestamp() for Unix timestamp.checked_add_months() and .checked_add_days() for safe arithmetic