chrono模块
1.类型说明
| 类型 | 说明 | 常用创建方法 |
|---|---|---|
NaiveDate |
仅日期(无时区) | NaiveDate::from_ymd_opt(y, m, d) |
NaiveTime |
仅时间(无日期) | NaiveTime::from_hms_opt(h, m, s) |
NaiveDateTime |
日期 + 时间(无时区) | NaiveDateTime::new(date, time) |
DateTime<Tz> |
带时区的完整时间 | Utc::now(), Local::now() |
Duration |
时间差 | Duration::seconds(5), Duration::days(1) |
2.DateTime时区
Local/Utc都是带时区的。
| 类型 | 说明 |
|---|---|
Utc |
世界标准时间(无夏令时) |
Local |
本地系统时间 |
FixedOffset |
固定偏移时区(例如 +08:00) |
2.1 创建时间
2.1.1 Local
use chrono::prelude::Local;
fn main() {
println!("{}", Local::now());
}
2025-11-13 21:47:00.692711 +08:00
2.1.2 Utc
use chrono::prelude::Utc;
fn main() {
// UTC是全球通用的标准时间基准,不隶属于任何国家或地区
println!("{}", Utc::now());
}
2025-11-13 13:47:57.262922 UTC
2.2 时区转换
2.2.1 Utc时区转换
推荐使用UTC 开始转换
东时区
FixedOffset::east_opt(secs)
西时区FixedOffset::west_opt(secs)
use chrono::{DateTime, FixedOffset, Utc};
fn main() {
// 假设有一个 UTC 时间
let utc_time: DateTime<Utc> = "2025-11-13T10:00:00Z".parse().unwrap();
// 创建北京时间时区 (+08:00)
// 8 * 3600秒 = 8小时
let beijing = FixedOffset::east_opt(8 * 3600).unwrap();
// 转换为北京时间
let bj_time = utc_time.with_timezone(&beijing);
println!("UTC: {}", utc_time);
println!("Beijing: {}", bj_time);
}
UTC: 2025-11-13 10:00:00 UTC
Beijing: 2025-11-13 18:00:00 +08:00
2.2.2 其它时区转换
先转换为
Utc时区,然后再转换到其他时区
use chrono::{FixedOffset, prelude::*};
fn main() {
// 假设系统本地时间是北京时间
let local_now = Local::now();
// 先转成 UTC
let utc_time = local_now.with_timezone(&Utc);
// 再转成俄罗斯时间
let russell = FixedOffset::east_opt(3 * 3600).unwrap();
let russell_time = utc_time.with_timezone(&russell);
// 转换成巴西时间
let brazil = FixedOffset::west_opt(3 * 3600).unwrap();
let brazil_time = utc_time.with_timezone(&brazil);
println!("Local: {}", local_now);
println!("UTC: {}", utc_time);
println!("Russell: {}", russell_time);
println!("Brazil: {}", brazil_time);
}
Local: 2025-11-13 21:24:26.122807 +08:00
UTC: 2025-11-13 13:24:26.122807 UTC
Russell: 2025-11-13 16:24:26.122807 +03:00
Brazil: 2025-11-13 10:24:26.122807 -03:00
2.3 除去时区
转换为
NaiveDateTime
2.3.1 Local去时区
naive_local
use chrono::prelude::Local;
fn main() {
let local_now = Local::now();
let naive = local_now.naive_local();
println!("now: {}", naive);
}
now: 2025-11-13 13:53:38.482506
2.3.2 Utc去时区
naive_utc
use chrono::prelude::Utc;
fn main() {
let utc_now = Utc::now();
let naive = utc_now.naive_utc(); // 去掉时区
println!("now: {}", naive);
}
now: 2025-11-13 13:55:41.335349
2.3.2 时间戳转为Utc
use chrono::{DateTime, FixedOffset};
fn main() {
let timestamp = 1763084203;
let naive_dt = DateTime::from_timestamp(timestamp, 0).unwrap();
let beijing = FixedOffset::east_opt(8 * 3600).unwrap();
let beijing_naive_dt = naive_dt.with_timezone(&beijing);
println!("{}", naive_dt);
println!("{}", beijing_naive_dt);
}
2025-11-14 01:36:43 UTC
2025-11-14 09:36:43 +08:00
3.NaiveDateTime无时区
返回无时区的时间
3.1 创建时间
3.1.1 链式创建
使用
NaiveDate创建时间
use chrono::NaiveDate;
fn main() {
let dt = NaiveDate::from_ymd_opt(2015, 05, 05)
.unwrap()
.and_hms_opt(11, 00, 02)
.unwrap();
println!("指定时间: {}", dt);
}
指定时间: 2015-05-05 11:00:02
3.1.2 组合创建
先构造
NaiveDate和NaiveTime
use chrono::{NaiveDate, NaiveTime, NaiveDateTime};
fn main() {
// 指定时间
let date = NaiveDate::from_ymd_opt(2025, 11, 13).unwrap();
let time = NaiveTime::from_hms_opt(14, 30, 45).unwrap();
let datetime = NaiveDateTime::new(date, time);
println!("指定时间: {}", datetime);
}
指定时间: 2025-11-13 14:30:45
3.1.3 时间戳创建
NaiveDateTime::from_timestamp_opt(秒, 纳秒)
推荐使用DateTime::from_timestamp
use chrono::NaiveDateTime;
fn main() {
// 以 Unix 时间戳(秒)和纳秒偏移创建
let secs: i64 = 1_762_789_499;
let dt = NaiveDateTime::from_timestamp_opt(secs, 0).unwrap();
println!("{}", dt);
}
2025-11-10 15:44:59
3.2 添加时区
NaiveDateTime本身没有时区信息,需要创建DateTime<FixedOffset>或DateTime<Utc>来附加偏移信息。
use chrono::{DateTime, FixedOffset, Local, NaiveDateTime, Utc};
fn main() {
// 1. 创建一个无时区的 NaiveDateTime
let naive = NaiveDateTime::parse_from_str("2025-11-13 14:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
println!("NaiveDateTime: {}", naive);
// 2. 转为 UTC
let dt_utc: DateTime<Utc> = DateTime::from_naive_utc_and_offset(naive, Utc);
println!("UTC DateTime: {}", dt_utc);
// 3. 转为固定时区 +08:00
let offset = FixedOffset::east_opt(8 * 3600).unwrap();
let dt_fixed: DateTime<FixedOffset> = DateTime::from_naive_utc_and_offset(naive, offset);
println!("FixedOffset DateTime: {}", dt_fixed);
// 4. 转为本地时区(Local)
// 需要 utc 间接转
let dt_local: DateTime<Local> = DateTime::from(dt_utc);
println!("Local DateTime: {}", dt_local);
}
NaiveDateTime: 2025-11-13 14:30:00
UTC DateTime: 2025-11-13 14:30:00 UTC
FixedOffset DateTime: 2025-11-13 22:30:00 +08:00
Local DateTime: 2025-11-13 22:30:00 +08:00
4.格式化时间
| 格式符 | 说明 |
|---|---|
%Y |
年(四位) |
%m |
月(两位) |
%d |
日(两位) |
%H |
小时(24h) |
%M |
分钟 |
%S |
秒 |
%z |
时区偏移 |
%z |
时区偏移,格式 +0800 或 -0500,四位数字表示小时分钟 |
%:z |
带冒号的时区偏移,格式 +08:00 或 -05:00 |
%Z |
时区名称/缩写,例如 UTC、CST,不能保证解析偏移数字 |
4.1 时间转String
| 方法 | 适用于 | 说明 |
|---|---|---|
to_string() |
NaiveDateTime / DateTime |
使用默认格式(ISO 8601) |
format("%Y-%m-%d %H:%M:%S") |
NaiveDateTime / DateTime |
自定义格式输出 |
to_rfc2822() |
仅 DateTime(带时区) |
按 RFC2822(邮件标准时间格式)输出 |
to_rfc3339() |
仅 DateTime(带时区) |
按 RFC3339(ISO8601 变体)输出 |
4.1.1 Local转String
use chrono::prelude::Local;
fn main() {
let now = Local::now();
let s1 = now.to_rfc2822();
let s2 = now.to_rfc3339();
let s3 = now.to_string();
// format返回的是chrono::format::DelayedFormat
let s4 = now.format("%Y-%m-%d %H:%M:%S").to_string();
let s5 =now.format("%Y-%m-%d %H:%M:%S %z").to_string();
let s6 =now.format("%Y-%m-%d %H:%M:%S %:z").to_string();
println!("to_rfc2822 : {}", s1);
println!("to_rfc3339 : {}", s2);
println!("to_string : {}", s3);
println!("无时区 : {}", s4);
println!("%z : {}", s5);
println!("%:z : {}", s6);
}
to_rfc2822 : Thu, 13 Nov 2025 22:08:32 +0800
to_rfc3339 : 2025-11-13T22:08:32.409315+08:00
to_string : 2025-11-13 22:08:32.409315 +08:00
无时区 : 2025-11-13 22:08:32
%z : 2025-11-13 22:08:32 +0800
%:z : 2025-11-13 22:08:32 +08:00
4.1.2 NaiveDateTime转String
use chrono::prelude::{NaiveDate, NaiveDateTime, NaiveTime};
fn main() {
let now = NaiveDateTime::new(
NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
NaiveTime::from_hms_opt(12, 0, 0).unwrap(),
);
let s1 = now.to_string();
// format返回的是chrono::format::DelayedFormat
let s2 = now.format("%Y-%m-%d %H:%M:%S").to_string();
// 转换为有时区的会报错
// let s3 =now.format("%Y-%m-%d %H:%M:%S %z").to_string();
// let s4 =now.format("%Y-%m-%d %H:%M:%S %:z").to_string();
println!("to_string : {}", s1);
println!("无时区 : {}", s2);
}
to_string : 2025-01-01 12:00:00
无时区 : 2025-01-01 12:00:00
4.2 String转时间
DateTime是带有时区的
NaiveDateTime是不带时区的
4.2.1 时区
4.2.1.1 String转Utc/Local
使用标准的
ISO 8601格式
转换
DateTime<Utc>会解析时会自动 转换成 UTC
use chrono::prelude::{DateTime, Utc, Local};
fn main() {
let utc_str = "2025-11-13T06:30:45+00:00";
let utc_dt: DateTime<Utc> = utc_str.parse().expect("解析失败");
println!("DateTime<Utc>: {}", utc_dt);
// 东6区自动转为 UTC 时间
let utc_str2 = "2025-11-13T06:30:45+06:00";
let utc_dt2: DateTime<Utc> = utc_str2.parse().expect("解析失败");
println!("DateTime<Utc>: {}", utc_dt2);
let local_str = "2025-11-13T06:30:45+08:00";
let local_dt: DateTime<Local> = local_str.parse().expect("解析失败");
println!("DateTime<local_dt>: {}", local_dt);
}
DateTime<Utc>: 2025-11-13 06:30:45 UTC
DateTime<Utc>: 2025-11-13 00:30:45 UTC
DateTime<local_dt>: 2025-11-13 06:30:45 +08:00
4.2.1.2 String转DateTime
注意无时区的
str不能转为DateTime
use chrono::prelude::DateTime;
fn main() {
let dt_str1 = "2025-11-13 06:30:45 +08:00";
let dt1 = DateTime::parse_from_str(&dt_str1, "%Y-%m-%d %H:%M:%S %:z").unwrap();
println!("dt1: {}", dt1);
let dt_str2 = "2025-11-13 06:30:45 +0800";
let dt2 = DateTime::parse_from_str(&dt_str2, "%Y-%m-%d %H:%M:%S %z").unwrap();
println!("dt2: {}", dt2);
// 带有毫秒的 %.6f
let s3 = "2025-11-13T18:09:14.306422+08:00";
let dt3 = DateTime::parse_from_str(&s3, "%Y-%m-%dT%H:%M:%S%.6f%:z").unwrap();
println!("dt3: {}", dt3);
// let dt_str4 = "2025-11-13 06:30:45";
// let dt4 = DateTime::parse_from_str(&dt_str4, "%Y-%m-%d %H:%M:%S").unwrap();
// println!("dt4: {}", dt4);
}
dt1: 2025-11-13 06:30:45 +08:00
dt2: 2025-11-13 06:30:45 +08:00
dt3: 2025-11-13 18:09:14.306422 +08:00
4.2.2 无时区
4.2.2.1 String转NaiveDateTime
use chrono::prelude::NaiveDateTime;
fn main() {
let s1 = "2025-11-13 18:09:14";
let s2 = "2025-11-13 18:09:14 +0800";
let s3 = "2025-11-13 18:09:14 +08:00";
let s4 = "2025-11-13T18:09:14.306422+08:00";
let dt1 = NaiveDateTime::parse_from_str(&s1, "%Y-%m-%d %H:%M:%S").unwrap();
let dt2 = NaiveDateTime::parse_from_str(&s2, "%Y-%m-%d %H:%M:%S %z").unwrap();
let dt3 = NaiveDateTime::parse_from_str(&s3, "%Y-%m-%d %H:%M:%S %:z").unwrap();
let dt4 = NaiveDateTime::parse_from_str(&s4, "%Y-%m-%dT%H:%M:%S%.6f%:z").unwrap();
println!("dt1: {}", dt1);
println!("dt2: {}", dt2);
println!("dt3: {}", dt3);
println!("dt4: {}", dt4);
}
dt1: 2025-11-13 18:09:14
dt2: 2025-11-13 18:09:14
dt3: 2025-11-13 18:09:14
dt4: 2025-11-13 18:09:14.306422
5.时间计算
使用
Duration计算时间,会返回当前计算的struc。
| 特性 | NaiveDateTime | DateTime |
|---|---|---|
| 时区信息 | 无 | 有(UTC/Local/FixedOffset) |
| 加减时间 | 仅按数字计算 | 按 UTC 绝对时间计算,显示受时区影响 |
| 适用场景 | 日历计算、日志、计时器 | 实际世界时间、跨时区事件 |
| 夏令时处理 | 不考虑 | 自动调整 |
5.1 NaiveDateTime计算
计算完返回新的
NaiveDateTime
use chrono::{NaiveDateTime, Duration};
fn main() {
let dt = NaiveDateTime::parse_from_str("2025-11-13 18:09:14", "%Y-%m-%d %H:%M:%S").unwrap();
let later = dt + Duration::hours(5);
let earlier = dt - Duration::days(1);
let sss = dt - Duration::seconds(10);
println!("原始时间: {}", dt);
println!("加5小时: {}", later);
println!("减1天: {}", earlier);
println!("减10秒: {}", sss);
}
原始时间: 2025-11-13 18:09:14
加5小时: 2025-11-13 23:09:14
减1天: 2025-11-12 18:09:14
减10秒: 2025-11-13 18:09:04
5.2 DateTime计算
计算完返回新的
DateTime
use chrono::{DateTime, Local, Duration};
fn main() {
let dt: DateTime<Local> = Local::now();
let dt_later = dt + Duration::hours(5); // 新的 DateTime
println!("原始: {}", dt);
println!("加5小时: {}", dt_later);
}
原始: 2025-11-13 22:55:35.468423 +08:00
加5小时: 2025-11-14 03:55:35.468423 +08:00
6.时间比较
6.1 NaiveDateTime
只比较时间点的数值大小,不考虑时区(因为没有时区)。
适合用在同一时区或纯时间运算。
use chrono::NaiveDateTime;
fn main() {
let dt1 = NaiveDateTime::parse_from_str("2025-11-13 12:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
let dt2 = NaiveDateTime::parse_from_str("2025-11-13 15:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
if dt1 < dt2 {
println!("dt1 比 dt2 早");
} else {
println!("dt1 比 dt2 晚或相等");
}
}
dt1 比 dt2 早
6.2 DateTime
内部比较的是
UTC时间,所以即使时区不同,也能正确比较
都转换为
UTC,然后再进行比较
use chrono::{DateTime, FixedOffset};
fn main() {
let dt1: DateTime<FixedOffset> = "2025-11-13T12:00:00+08:00".parse().unwrap();
let dt2: DateTime<FixedOffset> = "2025-11-13T04:00:00+00:00".parse().unwrap(); // UTC 对应时间
println!("dt1: {}", dt1);
println!("dt2: {}", dt2);
// 都转换为UTC,然后再进行比较
if dt1.with_timezone(&chrono::Utc) == dt2.with_timezone(&chrono::Utc) {
println!("dt1 和 dt2 表示同一时间点");
}
}
dt1: 2025-11-13 12:00:00 +08:00
dt2: 2025-11-13 04:00:00 +00:00
dt1 和 dt2 表示同一时间点

浙公网安备 33010602011771号