介绍
Rust 标准库的 std::time 模块提供了处理时间的基础类型
| 类型 | 作用 |
|---|---|
| Duration | 时间间隔(一段时间, 比如 5 秒) |
| Instant | 时刻(用来测量耗时, 单调递增) |
| SystemTime | 系统时间(可以转换为日期, 但可能被调整) |
注意点
std::time 只提供了"时间间隔"和"系统时钟", 没有提供日期/日历类型(比如"今天是 2026 年 6 月 1 日"), 日期相关的功能需要第三方库 chrono, 本章最后一节会介绍
时间间隔 Duration
Duration 表示一段时间的长度, 内部由"秒 + 纳秒"两部分组成
创建 Duration
| 方法 | 作用 |
|---|---|
| new | 由 (秒, 纳秒) 两部分创建 |
| from_secs | 从秒创建 |
| from_millis | 从毫秒创建 |
| from_micros | 从微秒创建 |
| from_nanos | 从纳秒创建 |
rust
use std::time::Duration;
fn main() {
// 1. Duration::new: 由 (秒, 纳秒) 两部分创建
let d = Duration::new(2, 500_000_000); // 2 秒 + 0.5 秒
println!("{d:?}"); // 2.5s
// 2. 从各种时间单位创建
let secs = Duration::from_secs(90);
println!("{secs:?}"); // 90s
let millis = Duration::from_millis(1500);
println!("{millis:?}"); // 1.5s
let micros = Duration::from_micros(1_000_000);
println!("{micros:?}"); // 1s
let nanos = Duration::from_nanos(1_000);
println!("{nanos:?}"); // 1µs
}Duration 的运算
| 方法 | 作用 |
|---|---|
| checked_add | 加法, 溢出返回 None |
| saturating_sub | 减法, 不够减返回 0(不会变负) |
| mul | 乘法, 可以直接 duration * n |
rust
use std::time::Duration;
fn main() {
let a = Duration::from_secs(2);
let b = Duration::from_secs(3);
// checked_add: 加法, 返回 Option
let c = a.checked_add(b).expect("溢出");
println!("{c:?}"); // 5s
// saturating_sub: 不够减时返回 0
let small = Duration::from_secs(1);
println!("{:?}", small.saturating_sub(b)); // 0ns
println!("{:?}", b.saturating_sub(small)); // 2s
// 乘法
println!("{:?}", a * 3); // 6s
// Duration 实现了比较运算
println!("a < b = {}", a < b); // a < b = true
}转换 Duration
| 方法 | 作用 |
|---|---|
| as_secs | 整秒部分(丢弃小数) |
| as_millis | 毫秒 |
| as_micros | 微秒 |
| as_secs_f64 | 秒(浮点数, 带小数) |
rust
use std::time::Duration;
fn main() {
let d = Duration::from_millis(2500);
// as_secs: 只取整秒部分, 丢弃小数
println!("as_secs = {}", d.as_secs()); // as_secs = 2
// as_millis / as_micros
println!("as_millis = {}", d.as_millis()); // as_millis = 2500
println!("as_micros = {}", d.as_micros()); // as_micros = 2500000
// as_secs_f64: 带小数的秒
println!("as_secs_f64 = {}", d.as_secs_f64()); // as_secs_f64 = 2.5
}测量耗时 Instant
Instant 表示一个时刻, 常用于测量代码执行耗时, 它的时间是单调递增的, 不会因为系统时间被调整而受影响
测量代码执行耗时
rust
use std::time::Instant;
fn main() {
// Instant::now: 记录当前时刻
let start = Instant::now();
// 模拟一段耗时操作(1 亿次循环)
let mut sum = 0u64;
for i in 0..100_000_000 {
sum += i;
}
println!("sum = {sum}");
// elapsed: 从 start 时刻到现在经过的时间
let elapsed = start.elapsed();
println!("耗时: {elapsed:?}"); // 耗时: 几十毫秒 (每次运行结果不同)
}让线程休眠
rust
use std::thread;
use std::time::{Duration, Instant};
fn main() {
// thread::sleep: 让当前线程休眠一段时间
let start = Instant::now();
thread::sleep(Duration::from_millis(100));
println!("睡了 {:?}", start.elapsed()); // 睡了 100ms 左右 (每次运行略有差异)
}利用这一点可以实现类似 JS 的定时器 API
rust
use std::{thread, time::Duration};
// 超时器
pub fn set_time_out<F>(callback: F, time_out: Duration)
where
F: Fn(),
{
thread::sleep(time_out); // 阻塞当前线程
callback();
}
// 定时器
pub fn set_interval<F>(callback: F, time_out: Duration)
where
F: Fn(),
{
loop {
thread::sleep(time_out); // 阻塞当前线程
callback();
}
}系统时间 SystemTime
SystemTime 表示系统时间, 可以获取当前时间的UNIX 时间戳(距离 1970-01-01 的秒数)
获取当前时间戳
rust
use std::time::{SystemTime, UNIX_EPOCH};
fn main() {
// SystemTime::now: 当前系统时间
let now = SystemTime::now();
// duration_since(UNIX_EPOCH): 计算距离 1970-01-01 的时间
// 返回 Result: 如果系统时间早于 1970 年会返回 Err
let since_epoch = now.duration_since(UNIX_EPOCH).expect("系统时间异常");
println!("距离 1970 年: {since_epoch:?}"); // 每次运行结果不同
// 这就是常见的"UNIX 时间戳"
println!("时间戳(秒): {}", since_epoch.as_secs()); // 每次运行结果不同
println!("时间戳(毫秒): {}", since_epoch.as_millis());
}比较两个时间点
rust
use std::time::{Duration, SystemTime, UNIX_EPOCH};
fn main() {
// elapsed: 当前时间距离该时刻经过的时间
let t = SystemTime::now();
println!("{:?}", t.elapsed().expect("系统时间异常")); // 极短的时间 (每次运行不同)
// 模拟两个时间点: t2 比 t1 晚 5 秒
let t1 = SystemTime::now();
let t2 = t1 + Duration::from_secs(5);
// duration_since: t2 距离 t1 过了多久
let diff = t2.duration_since(t1).expect("时间倒退");
println!("diff = {diff:?}"); // diff = 5s
// 反过来计算会返回 Err(时间不能倒退)
let result = t1.duration_since(t2);
println!("{result:?}"); // Err(...)
println!("{:?}", UNIX_EPOCH.elapsed().expect("系统时间异常")); // 系统启动至今的秒数
}日期与日历(第三方库 chrono)
标准库没有日期类型, 处理"年/月/日/星期"需要第三方库, chrono 是事实标准
介绍与创建日期
| 方法 | 作用 |
|---|---|
| Local::now | 当前本地时间 |
| Utc::now | 当前 UTC 时间 |
| NaiveDate::from_ymd_opt | 手动创建日期(返回 Option) |
rust
// Cargo.toml 添加依赖:
// [dependencies]
// chrono = "0.4"
use chrono::{Local, NaiveDate, Utc};
fn main() {
// 1. 获取当前本地时间: 会受到服务器时区设置的影响
let now = Local::now();
println!("本地时间: {}", now.format("%Y-%m-%d %H:%M:%S")); // 每次运行结果不同
// 2. 获取当前 UTC 时间(格林尼治时间)
let utc = Utc::now();
println!("UTC 时间: {}", utc.format("%Y-%m-%d %H:%M:%S")); // 每次运行结果不同
// 3. 手动创建日期(返回 Option, 不合法返回 None)
let date = NaiveDate::from_ymd_opt(2026, 6, 1).expect("日期不合法");
println!("{date}"); // 2026-06-01
// 不合法日期: 2 月没有 30 号
let date = NaiveDate::from_ymd_opt(2026, 2, 30);
println!("{date:?}"); // None
}格式化与解析
常用格式符: %Y 年 %m 月 %d 日 %H 时(24小时制) %M 分 %S 秒
rust
// Cargo.toml 添加依赖:
// [dependencies]
// chrono = "0.4"
use chrono::NaiveDate;
fn main() {
let date = NaiveDate::from_ymd_opt(2026, 6, 1).expect("日期不合法");
// format: 日期格式化为字符串
println!("{}", date.format("%Y/%m/%d")); // 2026/06/01
println!("{}", date.format("%Y年%m月%d日")); // 2026年06月01日
// parse_from_str: 字符串解析为日期
let parsed = NaiveDate::parse_from_str("2026-06-01", "%Y-%m-%d").expect("解析失败");
println!("{parsed}"); // 2026-06-01
// 格式不匹配会解析失败
let result = NaiveDate::parse_from_str("2026-13-01", "%Y-%m-%d");
println!("{result:?}"); // Err(ParseError(OutOfRange))
}日期运算
rust
// Cargo.toml 添加依赖:
// [dependencies]
// chrono = "0.4"
use chrono::{Datelike, Days, NaiveDate};
fn main() {
let d1 = NaiveDate::from_ymd_opt(2026, 1, 1).expect("日期不合法");
// checked_add_days: 加天数(返回 Option, 溢出返回 None)
let d2 = d1.checked_add_days(Days::new(100)).expect("日期溢出");
println!("{d2}"); // 2026-04-11
// 两个日期相减: 得到天数差
let diff = d2 - d1;
println!("相差 {} 天", diff.num_days()); // 相差 100 天
// 星期几 (weekday 定义在 Datelike trait 上, 需要引入)
println!("{d1} 是 {}", d1.weekday()); // 2026-01-01 是 Thu
}时间戳与日期互转
rust
// Cargo.toml 添加依赖:
// [dependencies]
// chrono = "0.4"
use chrono::{DateTime, Utc};
fn main() {
// 时间戳 -> 日期时间
let dt = DateTime::from_timestamp(1_700_000_000, 0).expect("时间戳不合法");
println!("{dt}"); // 2023-11-14 22:13:20 UTC
// 日期时间 -> 时间戳
let ts = dt.timestamp();
println!("{ts}"); // 1700000000
// 当前时间戳
let now_ts = Utc::now().timestamp();
println!("当前时间戳: {now_ts}"); // 每次运行结果不同
}相关开源库
- chrono: 日期时间处理的事实标准, Local会受到服务器时区设置的影响
- chrono-tz: 处理时区相关的问题(比如: 将utc时间转为 Asia/Shanghai 时间)
- time: chrono 的替代品, API 更严谨
- humantime: 人类可读的时间格式解析与格式化(如 "2h 30m")
rust
// Cargo.toml 添加依赖:
// [dependencies]
// humantime = "2"
fn main() {
// parse_duration: 解析人类可读的时间间隔
let d = humantime::parse_duration("2h 30m").expect("解析失败");
println!("{d:?}"); // 9000s
// format_duration: 格式化为人类可读
println!("{}", humantime::format_duration(d)); // 2h 30m
}