1. 期间和计算

1.1 测量运行时间

  测量从 time::Instant::now 开始运行的时间 time::Instant::elapsed。调用 time::Instant::elapsed 将返回 time::Duration,在实例末尾打印该时间。此方法不会更改或者重置 time::Instant 对象。

use std::thread;
use std::time::{Duration, Instant};

fn expensive_function() {
thread::sleep(Duration::from_secs(2));
}

fn main() {
let start = Instant::now();
expensive_function();
let duration = start.elapsed();

println!("expensive_function() 函数运行的时间是: {:?}", duration);
}
  • 运行cargo run输出
expensive_function() 函数运行的时间是: 2.000175481s

1.2 执行日期检查和时间计算

  需要安装chrono库,可通过cargo add chrono 命令安装

[dependencies]
chrono = "0.4.24"

  使用 DateTime::checked_add_signed 计算并显示两周之后的日期和时间,使用 DateTime::checked_sub_signed 计算并显示前一天的日期。如果无法计算出日期和时间,这些方法将返回 None。可以在 chrono::format::strftime 中找到适用于 DateTime::format 的转义序列。

use chrono::{DateTime, Duration, Utc};

fn day_earlier(date_time: DateTime<Utc>) -> Option<DateTime<Utc>> {
date_time.checked_sub_signed(Duration::days(1))
}

fn main() {
let now = Utc::now();
println!("{}", now);

let almost_three_weeks_from_now = now
.checked_add_signed(Duration::weeks(2))
.and_then(|in_2weeks| in_2weeks.checked_add_signed(Duration::weeks(1)))
.and_then(day_earlier);

match almost_three_weeks_from_now {
Some(x) => println!("{}", x),
None => eprintln!("将近三周后!"),
}

match now.checked_add_signed(Duration::max_value()) {
Some(x) => println!("{}", x),
None => eprintln!("我们不能用 chrono 来判断太阳系绕银河中心完成超过一圈完整轨道的时间."),
}
}
  • 运行cargo run输出
2023-04-16 13:23:26.368785736 UTC
2023-05-07 13:23:26.368785736 UTC
我们不能用 chrono 来判断太阳系绕银河中心完成超过一圈完整轨道的时间.

1.3 时间的时区转换

  使用 offset::Local::now 获取本地时间并显示,然后使用 DateTime::from_utc 结构体方法将其转换为 UTC 标准格式。最后,使用 offset::FixedOffset 结构体,可以将 UTC 时间转换为 UTC+8UTC-2

use chrono::{DateTime, FixedOffset, Local, Utc};

fn main() {
let local_time = Local::now();
let utc_time = DateTime::<Utc>::from_utc(local_time.naive_utc(), Utc);
let china_timezone = FixedOffset::east_opt(8 * 3600).unwrap();
let rio_timezone = FixedOffset::west_opt(2 * 3600).unwrap();
println!("现在当地时间是 {}", local_time);
println!("UTC 时间现在是{}", utc_time);
println!("现在香港时间是 {}", utc_time.with_timezone(&china_timezone));
println!(
"现在里约热内卢时间是 {}",
utc_time.with_timezone(&rio_timezone)
);
}
  • 运行cargo run输出
现在当地时间是 2023-04-16 13:31:33.619954917 +00:00
UTC 时间现在是2023-04-16 13:31:33.619954917 UTC
现在香港时间是 2023-04-16 21:31:33.619954917 +08:00
现在里约热内卢时间是 2023-04-16 11:31:33.619954917 -02:00

2. 解析与显示

2.1 检查日期和时间

  通过 Timelike 获取当前 UTC DateTime 及其时/分/秒,通过 Datelike 获取其年/月/日/工作日。

use chrono::{Datelike, Timelike, Utc};

fn main() {
let now = Utc::now();

let (is_pm, hour) = now.hour12();
println!(
"当前的 UTC 时间是 {:02}:{:02}:{:02} {}",
hour,
now.minute(),
now.second(),
if is_pm { "下午" } else { "上午" }
);
println!("自午夜以来已有 {} 秒", now.num_seconds_from_midnight());

let (is_common_era, year) = now.year_ce();
println!(
"当前的 UTC 时间是 {}-{:02}-{:02} {:?} ({})",
year,
now.month(),
now.day(),
now.weekday(),
if is_common_era { "AD" } else { "BC" }
);
println!("公元于 {} 天前开始", now.num_days_from_ce());
}
  • 运行cargo run输出
当前的 UTC 时间是 01:39:35 下午
自午夜以来已有 49175 秒
当前的 UTC 时间是 2023-04-16 Sun (AD)
公元于 738626 天前开始

2.2 日期和 UNIX 时间戳的互相转换

  使用 NaiveDateTime::timestamp 将由NaiveDate::from_ymd 生成的日期和由 NaiveTime::from_hms 生成的时间转换为 UNIX 时间戳。然后,它使用 NaiveDateTime::from_timestamp 计算自 UTC 时间 1970 年 01 月 01 日 00:00:00 开始的 20 亿秒后的日期。

use chrono::{NaiveDate, NaiveDateTime};

fn main() {
let date_time: NaiveDateTime = NaiveDate::from_ymd_opt(2023, 04, 16)
.unwrap()
.and_hms_opt(17, 33, 44)
.unwrap();
println!(
"1970-01-01 00:00:00 和 {} 之间的秒数是 {}.",
date_time,
date_time.timestamp()
);

let date_time_after_a_billion_seconds =
NaiveDateTime::from_timestamp_opt(20_0000_0000, 0).unwrap();
println!(
"二十亿秒后的日期从 1970-01-01 00:00:00 是 {}.",
date_time_after_a_billion_seconds
);
}
  • 运行cargo run输出
1970-01-01 00:00:00 和 2023-04-16 17:33:44 之间的秒数是 1681666424.
十亿秒后的日期从 1970-01-01 00:00:00 是 2033-05-18 03:33:20.

2.3 日期和时间的格式化显示

  使用 Utc::now 获取并显示当前 UTC 时间。使用 DateTime::to_rfc2822 将当前时间格式化为熟悉的 RFC 2822 格式,使用 DateTime::to_rfc3339 将当前时间格式化为熟悉的 RFC 3339 格式,也可以使用 DateTime::format自定义时间格式。

use chrono::{DateTime, Utc};

fn main() {
let now: DateTime<Utc> = Utc::now();

println!("UTC 现在是: {}", now);
println!("现在在 RFC 2822 中的 UTC 是: {}", now.to_rfc2822());
println!("现在在 RFC 3339 中的 UTC 是: {}", now.to_rfc3339());
println!(
"现在采用自定义格式的 UTC 是: {}",
now.format("%Y:%m:%d %H:%M:%S")
);
}
  • 运行cargo run输出
UTC 现在是: 2023-04-16 13:52:53.430260493 UTC
现在在 RFC 2822 中的 UTC 是: Sun, 16 Apr 2023 13:52:53 +0000
现在在 RFC 3339 中的 UTC 是: 2023-04-16T13:52:53.430260493+00:00
现在采用自定义格式的 UTC 是: 2023:04:16 13:52:53

2.4 将字符串解析为 DateTime 结构体

  时间格式 RFC 2822RFC 3339,以及自定义时间格式,通常用字符串表达。要将这些字符串解析为 DateTime 结构体,可以分别用 DateTime::parse_from_rfc2822DateTime::parse_from_rfc3339,以及 DateTime::parse_from_str。可以在 chrono::format::strftime 中找到适用于 DateTime::parse_from_str 的转义序列。注意:DateTime::parse_from_str 要求这些 DateTime 结构体必须是可创建的,以便它唯一地标识日期和时间。要解析不带时区的日期和时间,请使用 NaiveDateNaiveTime,以及 NaiveDateTime

use chrono::format::ParseError;
use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime};

fn main() -> Result<(), ParseError> {
let rfc2822 = DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:16:09 GMT").unwrap(); //部分无法解析
println!("{}", rfc2822);

let rfc3339 = DateTime::parse_from_rfc3339("1896-12-19T16:39:57-08:00").unwrap();
println!("{}", rfc3339);

let custom =
DateTime::parse_from_str("5.8.2022 8:00 am +0000", "%d.%m.%Y %H:%M %P %z").unwrap();
println!("{}", custom);

let time_only = NaiveTime::parse_from_str("23:56:04", "%H:%M:%S").unwrap();
println!("{}", time_only);

let date_only = NaiveDate::parse_from_str("2023-09-05", "%Y-%m-%d").unwrap();
println!("{}", date_only);

let no_timezone =
NaiveDateTime::parse_from_str("2022-12-05 23:56:04", "%Y-%m-%d %H:%M:%S").unwrap();
println!("{}", no_timezone);

Ok(())
}
  • 运行cargo run输出
2015-02-18 23:16:09 +00:00
1896-12-19 16:39:57 -08:00
2022-08-05 08:00:00 +00:00
23:56:04
2023-09-05
2022-12-05 23:56:04