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 组合创建

先构造 NaiveDateNaiveTime

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 时区名称/缩写,例如 UTCCST,不能保证解析偏移数字

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 表示同一时间点
posted @ 2025-11-13 23:05  lxd670  阅读(7)  评论(0)    收藏  举报