Rust
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Ownership and Borrowing
-
Section 4: Structuring Data
-
Section 5: Collections and Error Handling
-
Section 6: Traits and Generics
-
Section 7: Concurrency
-
Section 8: Building for the Web
-
Section 9: Memory and Performance
-
Section 10: More Standard Library and Ecosystem
-
Section 11: Advanced Rust
-
Section 12: Rust for Systems and WebAssembly
-
Section 13: Tooling and Best Practices
-
Section 14: Data Structures and Algorithms in Rust
-
Section 15: Practical Projects
-
Section 16: Interview Practice
-
Section 17: std::collections In Depth
-
Section 18: std::io and std::fs In Depth
-
Section 19: std::net
-
Section 20: std::option and std::result In Depth
-
Section 21: std::iter In Depth
-
Section 22: std::sync In Depth
-
Section 23: std::string and std::str
-
Section 24: Cargo and Crates.io Ecosystem
-
Section 25: Popular Crates Ecosystem
-
Section 26: Rust Memory Model Deep Dive
-
Section 27: More Practice Exercises
-
Section 28: More Interview Practice
-
Section 29: Async Rust Deep Dive
-
Section 30: Tokio Ecosystem In Depth
-
Section 31: Error Handling Ecosystem Deep Dive
-
Section 32: Serde In Depth
-
Section 33: Web Development with Rust Deep Dive
-
Section 34: Database Access Ecosystem
-
Section 35: Rust for Embedded Systems Deep Dive
-
Section 36: Rust Macros In Depth
-
Section 37: Advanced Trait System
-
Section 38: Unsafe Rust In Depth
-
Section 39: Rust CLI Development
-
Section 40: Testing Ecosystem Deep Dive
-
Section 41: WebAssembly Deep Dive
-
Section 42: Rust Design Patterns
-
Section 43: More Data Structures in Rust
-
Section 44: Final Practice Projects
-
Section 45: Rust Performance Optimization
-
Section 46: Rust Ecosystem Tooling
-
Section 47: More Interview and Review
131: chrono for Date and Time
A few years ago, I was reviewing a PR for a distributed logging system. The developer had used std::time::SystemTime to timestamp events. On the surface, it looked fine. But once we deployed to a cluster spanning three different AWS regions, the logs became a nightmare. One region was logging in UTC, another was using the system local time of the instance, and we spent an entire weekend trying to reconstruct a sequence of events that looked like they were happening in the future or the past. It was a classic case of "treating time as a simple number" instead of a complex domain.
In Rust, the standard library is intentionally lean. std::time is great for measuring how long a function takes to run (using Instant) or getting a raw system timestamp, but it's completely inadequate for calendars, timezones, or formatting a date for a user. That's where the chrono crate comes in. It is the industry standard for almost every Rust project that needs to handle "human time."
Managing UTC and Local Time
The first thing you need to wrap your head around is the difference between Utc and Local. In a professional backend environment, the rule of thumb is: always store and move time in UTC. Only convert to local time at the very last moment when you're displaying it to a human.
use chrono::{Utc, Local, DateTime};
fn main() {
// Get the current time in UTC
let now_utc: DateTime<Utc> = Utc::now();
println!("UTC time: {}", now_utc);
// Get the current time based on the system's local timezone
let now_local: DateTime<Local> = Local::now();
println!("Local time: {}", now_local);
}
I've seen too many bugs caused by developers using Local::now() in their database records. If your server migrates to a different data center or the OS timezone is misconfigured, your data is corrupted. Stick to Utc::now() unless you have a very specific reason not to.
The Danger of Naive Types
You'll see types like NaiveDate and NaiveDateTime in the documentation. The word "naive" isn't an insult—it's a technical term. A naive date/time is one that has no timezone associated with it. It's just a date and a time, like a wall clock in a room with no windows.
use chrono::{NaiveDate, NaiveDateTime};
fn main() {
// A specific date without a timezone
let birthday = NaiveDate::from_yml_opt(1990, 5, 15).expect("Invalid date");
// A specific date and time without a timezone
let appointment = NaiveDateTime::parse_from_str(
"2023-12-25 09:00:00",
"%Y-%m-%d %H:%M:%S"
).expect("Parse error");
println!("Birthday: {}", birthday);
println!("Appointment: {}", appointment);
}
Naive types are useful when the timezone is implied or irrelevant—like a birthday or a store's "opening hours" that apply regardless of where the store is. But if you use them for a global event, you're asking for trouble. If you have a NaiveDateTime and you need to make it "aware," you'll have to explicitly tell Rust which timezone it belongs to before converting it to a DateTime<Utc> or DateTime<Local>.
Formatting and Parsing for Users
Eventually, you have to turn these objects into strings. chrono uses a formatting syntax similar to C's strftime. It can feel a bit cryptic at first, but you'll get used to it. The most common ones are %Y for year, %m for month, and %d for day.
use chrono::{Utc, Local};
fn main() {
let now = Utc::now();
// Custom formatting: "2023-10-27 14:30:05"
let formatted = now.format("%Y-%m-%d %H:%M:%S").to_string();
println!("Formatted: {}", formatted);
// You can also use predefined formats or just the Debug trait
println!("Debug view: {:?}", now);
}
One tip: if you're building an API, don't invent your own format. Use RFC 3339 (which chrono supports out of the box via the to_rfc3339() method). It's the standard for JSON APIs and ensures that any client—whether written in TypeScript, Python, or Go—can parse your timestamps without guessing.
📋 Practical Task
Exercise: Global Event Countdown Timer
You are building a feature for a global gaming tournament. The tournament starts at a fixed UTC time, and you need to display the countdown and the local start time for the user.
Requirements:
- Define a constant or variable for the tournament start time:
2025-12-31 23:59:59 UTC. - Calculate the duration between the current time (
Utc::now()) and the start time. - Print the remaining time in a human-readable format (days, hours, minutes).
- Convert the UTC start time to the user's
Localtime and print it using the format:"Your local start time is: YYYY-MM-DD HH:MM". - Handle the case where the tournament has already started by printing "The tournament has already begun!" instead of a negative duration.
Hint: Use chrono::Duration to handle the subtraction of two DateTime objects.
There are no comments for now.