在 Rust 中处理日期和时间:高级技术与库

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

在 Rust 中高级处理日期和时间:从 NaiveDateTime 到时区



处理日期和时间是后端开发、日志记录、金融系统和数据处理中最常见的任务之一。在 Rust 中,标准库提供了基本的 std::time 模块,但对于严肃的项目来说,这还不够。在高级层面上,我们会使用 chrono crate——这是处理日期和时间的事实标准。在本文中,我们将探讨复杂场景:处理时区、解析非标准格式、操作持续时间以及性能优化。



1. 安装和 chrono 的基本结构



在 Cargo.toml 中添加依赖:



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


用于高级工作的 chrono 主要类型:

  • NaiveDateTime — 不带时区的日期时间(本地时间)。
  • DateTime<Tz> — 绑定到时区的日期时间(例如 Utc、Local、FixedOffset)。
  • Duration — 时间间隔(与 std::time::Duration 不同,支持负值)。
  • TimeDelta — 新版本中 Duration 的同义词。


创建当前 UTC 时间和本地时间的示例:



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. 处理时区



chrono 的强大功能之一是通过 chrono-tz crate 支持 Olson 时区数据库。这允许您使用诸如 "Europe/Moscow" 或 "America/New_York" 等区域名称。



安装:



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


在时区之间转换时间的示例:



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);}


重要提示:始终在数据库中存储 UTC 时间,仅在向用户显示时转换为本地时间。这可以避免夏令时/冬令时造成的混乱。



2.1. 使用 FixedOffset



如果您知道固定的偏移量(例如 +03:00),请使用 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. 日期解析和格式化(高级技术)



通过 parse_from_str 进行标准解析需要精确的格式。但在实际项目中,格式可能有所不同(例如,来自不同系统的日志)。让我们探讨几种方法。



3.1. 使用 try_parse 处理多种格式



使用格式遍历:



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

博客

书籍推荐