在 Rust 中处理时区:后端开发人员完整指南

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

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

开始课程

引言:为什么时间是个头疼的问题

\n\n

在任何严肃的 Rust 项目中,无论是基于 Actix 的 Web 服务器、日志解析器还是监控系统,迟早都会面临一个问题:如何在 Rust 中正确处理时区。看起来很简单?获取时间戳,显示在屏幕上——就完成了。但现实很残酷:一个被忽略的时区会让日志变得混乱,数据库也开始出错。

\n\n

在本文中,我们将探讨 Rust 生态系统如何解决时间问题。您将了解为什么 chrono 成为事实上的标准,如何在使用 UTC 和 Local 时不迷失方向,以及如何轻松处理像“Asia/Yekaterinburg”这样的特殊时区。开始吧!

\n\n

为什么 Rust 标准库不够用?

\n\n

std::time 提供了 SystemTime、Instant 和 Duration。这对于性能测量和简单定时器来说足够了。但当涉及到在 Rust 中处理时区时,标准库就显得力不从心了:它既不能解析像“2024-03-15T10:30:00+05:00”这样的字符串,也不提供时区信息,更无法将 UTC 转换为本地时间。

\n\n

这时,chrono crate 登场了。它是 Rust 中处理日期和时间的瑞士军刀。在 Cargo.toml 中安装它:

\n\n
[dependencies]\nchrono = { version = "0.4", features = ["serde"] }
\n\n

serde 标志用于序列化/反序列化——如果您使用 JSON API,这会很有用。

\n\n

chrono 基础:UTC、Local 和 Naive 时间

\n\n

在 chrono 中,有三种主要类型来表示时间点:

\n\n
    \n
  • DateTime<Utc> — UTC 时间。服务器的黄金标准。
  • \n
  • DateTime<Local> — 系统的本地时间。适合桌面端的日志。
  • \n
  • NaiveDateTime — 不带时区的“朴素”时间。有风险,但有时需要。
  • \n
\n\n

让我们看看如何获取不同时区的当前时间:

\n\n
use chrono::{Utc, Local, DateTime};\n\nfn main() {\n    let utc_now: DateTime<Utc> = Utc::now();\n    println!("当前 UTC 时间: {}", utc_now);\n\n    let local_now: DateTime<Local> = Local::now();\n    println!("当前本地时间: {}", local_now);\n}
\n\n

运行这段代码——您会看到差异。注意:DateTime 是一个泛型类型,由时区参数化。这意味着编译器不会让您在没有显式转换的情况下意外地将 UTC 和 Local 时间相加。类型安全守护时间!

\n\n

时区之间的转换

\n\n

最常见的任务是将 UTC 转换为用户的本地时间。假设您的服务器将所有内容存储在 UTC,而客户端位于 Asia/Yekaterinburg 时区(UTC+5)。如何实现?

\n\n

使用 with_timezone 方法:

\n\n
use chrono::{Utc, Local, TimeZone, DateTime};\n\nfn main() {\n    let utc_time: DateTime<Utc> = Utc::now();\n    \n    // 转换为系统本地时间\n    let local_time: DateTime<Local> = utc_time.with_timezone(&Local);\n    println!("UTC: {} -> Local: {}", utc_time, local_time);\n    \n    // 如果需要特定时区——使用 FixedOffset\n    let ekb_offset = chrono::FixedOffset::east_opt(5 * 3600).unwrap();\n    let ekb_time: DateTime<FixedOffset> = utc_time.with_timezone(&ekb_offset);\n    println!("UTC: {} -> EKB: {}", utc_time, ekb_time);\n}
\n\n

注意:FixedOffset::east_opt 返回 Option,因为并非所有偏移量都有效(例如,25 小时就太多了)。始终处理 None 的情况。

\n\n

如果您的在 Rust 中处理时区比简单的固定偏移更复杂呢?例如,需要考虑夏令时?这时

博客

书籍推荐