Working with Dates and Time in Rust: Advanced Techniques and Libraries

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Advanced Work with Dates and Time in Rust: from NaiveDateTime to Timezone



Working with dates and time is one of the most common tasks in backend development, logging, financial systems, and data processing. In Rust, the standard library provides the basic std::time module, but it is insufficient for serious projects. At an advanced level, we turn to the chrono crate — the de facto standard for working with dates and time. In this article, we will cover complex scenarios: working with time zones, parsing non-standard formats, duration manipulations, and performance optimization.



1. Installation and Basic Structure of chrono



Add the dependency to Cargo.toml:



[dependencies]chrono = { version = "0.4", features = ["serde"] }


Main chrono types for advanced work:

  • NaiveDateTime — date-time without a time zone (local).
  • DateTime<Tz> — date-time associated with a time zone (e.g., Utc, Local, FixedOffset).
  • Duration — time interval (differs from std::time::Duration, supports negative values).
  • TimeDelta — synonym for Duration in newer versions.


Example of creating the current moment in UTC and local time:



use chrono::{Utc, Local, DateTime};

fn main() { let utc_now: DateTime<Utc> = Utc::now(); let local_now: DateTime<Local> = Local::now(); println!("UTC: {}", utc_now); println!("Local: {}", local_now);}


2. Working with Time Zones (Timezone)



One of the powerful features of chrono is support for the Olson timezone database via the chrono-tz crate. This allows working with zone names such as "Europe/Moscow" or "America/New_York".



Install:



[dependencies]chrono = "0.4"chrono-tz = "0.8"


Example of converting time between zones:



use chrono::{Utc, DateTime, TimeZone};use chrono_tz::Europe::Moscow;

fn main() { let utc_time: DateTime<Utc> = Utc::now(); let moscow_time = utc_time.with_timezone(&Moscow); println!("UTC: {}", utc_time); println!("Moscow: {}", moscow_time);}


Important point: always store time in UTC in the database, and convert to local time only when displaying to the user. This prevents confusion with daylight saving time.



2.1. Working with FixedOffset



If you know a fixed offset (e.g., +03:00), use FixedOffset:



use chrono::{FixedOffset, DateTime, Utc};

fn main() { let offset = FixedOffset::east_opt(3 * 3600).unwrap(); // +03:00 let now_utc: DateTime<Utc> = Utc::now(); let now_offset = now_utc.with_timezone(&offset); println!("With offset +03:00: {}", now_offset);}


3. Parsing and Formatting Dates (Advanced Techniques)



Standard parsing via parse_from_str requires an exact format. But in real projects, formats can vary (e.g., logs from different systems). Let's look at several approaches.



3.1. Multiple Formats with try_parse



Use format iteration:



use chrono::NaiveDateTime;

fn parse_flexible(date_str: &str) -> Option<NaiveDateTime> { let formats = [ "%Y-%m-%d %H:%M:%S", "%d/%m/%Y %H:%M", "%Y%m%dT%H%M%S", "%b %d %Y %I:%M:%S%p", ];

for fmt in &formats { if let Ok(dt) = NaiveDateTime::parse_from_str(date_str, fmt) { return Some(dt); } } None}

fn main() { let dates = vec![ "2024-03-15 14:30:00", "15/03/2024 14:30", "2

Blogs

Book Recommendations