Chrono:Rust 日期與時間函式庫

Chrono 旨在提供在公曆格里高利曆中執行正確日期與時間操作所需的所有功能:

  • DateTime 類型預設具備時區感知能力,同時提供獨立的時區無關類型。
  • 可能產生無效或模糊日期與時間的操作會回傳 OptionMappedLocalTime
  • 可配置的解析與格式化功能,採用受 strftime 啟發的日期時間格式化語法。
  • Local 時區可與作業系統的當前時區協同運作。
  • 類型與操作的實作充分考量了合理的執行效率。
  • 為限制二進位檔案大小,Chrono 預設不附帶時區資料。請使用配套套件 Chrono-TZtzfile 以獲得完整的時區支援。

功能特性

Chrono 支援多種執行環境與作業系統,並提供數個可啟用或停用的功能選項。

預設功能:

  • alloc:啟用依賴記憶體配置的功能(主要用於字串格式化)。
  • std:啟用依賴標準函式庫的功能。此為 alloc 的超集,增加了與標準函式庫類型及特徵的互通性。
  • clock:啟用讀取本地時區(Local)的功能。此為 now 的超集。
  • now:啟用讀取系統時間(now)的功能。
  • wasmbind:為 wasm32 目標提供與 JS Date API 的介面。

可選功能:

  • serde:透過 serde 啟用序列化/反序列化。
  • rkyv:已棄用,請改用 rkyv-* 功能。
  • rkyv-16rkyv-32rkyv-64:透過 rkyv 啟用序列化/反序列化,分別使用 16 位元、32 位元或 64 位元整數。
  • rkyv-validation:使用 bytecheck 啟用 rkyv 驗證支援。
  • arbitrary:使用 Arbitrary 套件建構類型的任意實例。
  • unstable-locales:啟用本地化功能。此功能會新增帶有 _localized 後綴的多種方法。

概述

時間差/持續時間

Chrono 提供 TimeDelta 類型來表示時間跨度的長度。這是以秒與奈秒表示的「精確」持續時間,不包含如天或月等「名義」單位。

TimeDelta 類型先前命名為 Duration(仍作為類型別名提供)。與類似的 core::time::Duration 的主要區別在於它是有符號值而非無符號值。

日期與時間

Chrono 提供 DateTime 類型來表示特定時區中的日期與時間。

DateTime 具備時區感知能力,必須從 TimeZone 物件建構,該物件定義了本地日期如何轉換為 UTC 日期並反向轉換。有三種廣為人知的 TimeZone 實作:

  • Utc 指定 UTC 時區。其效率最高。
  • Local 指定系統本地時區。
  • FixedOffset 指定任意固定時區,例如 UTC+09:00 或 UTC-10:30。

不同 TimeZone 類型的 DateTime 是互異的,不能混合使用,但可使用 DateTime::with_timezone 方法相互轉換。

您可以在 UTC 時區(Utc::now())或本地時區(Local::now())取得當前日期與時間。

use chrono::prelude::*;

let utc: DateTime<Utc> = Utc::now(); // 例如 `2014-11-28T12:45:59.324310806Z`
let local: DateTime<Local> = Local::now(); // 例如 `2014-11-28T21:45:59.324310806+09:00`

此外,您也可以自行建立日期與時間:

use chrono::offset::MappedLocalTime;
use chrono::prelude::*;

let dt = Utc.with_ymd_and_hms(2014, 7, 8, 9, 10, 11).unwrap(); // `2014-07-08T09:10:11Z`

格式化與解析

格式化透過 format 方法完成,其格式等同於熟悉的 strftime 格式。

預設的 to_string 方法與 {:?} 格式說明符也提供了合理的表示方式。Chrono 還提供 to_rfc2822to_rfc3339 方法用於常見格式。

Chrono 現在還提供幾乎任何語言的日期格式化功能,無需額外的 C 函式庫。此功能在 unstable-locales 特性下提供:

use chrono::prelude::*;

let dt = Utc.with_ymd_and_hms(2014, 11, 28, 12, 0, 9).unwrap();
assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2014-11-28 12:00:09");
assert_eq!(dt.format_localized("%A %e %B %Y, %T", Locale::fr_BE).to_string(), 
           "vendredi 28 novembre 2014, 12:00:09");

解析可透過兩種方法完成:

  1. 標準的 FromStr 特徵(以及字串上的 parse 方法)可用於解析 DateTime<FixedOffset>DateTime<Utc>DateTime<Local> 值。
  2. DateTime::parse_from_str 解析帶有偏移量的日期與時間,並回傳 DateTime<FixedOffset>
use chrono::prelude::*;

let dt = "2014-11-28T12:00:09Z".parse::<DateTime<Utc>>().unwrap();
let fixed_dt = DateTime::parse_from_str("2014-11-28 21:00:09 +09:00", "%Y-%m-%d %H:%M:%S %z").unwrap();

與 EPOCH 時間戳的轉換

使用 DateTime::from_timestamp(seconds, nanoseconds) 從 UNIX 時間戳建構 DateTime<Utc>

使用 DateTime.timestampDateTime 取得時間戳(以秒為單位)。此外,您可以使用 DateTime.timestamp_subsec_nanos 取得額外的奈秒數。

use chrono::{DateTime, Utc};

// 從 epoch 建構 datetime:
let dt: DateTime<Utc> = DateTime::from_timestamp(1_500_000_000, 0).unwrap();
assert_eq!(dt.to_rfc2822(), "Fri, 14 Jul 2017 02:40:00 +0000");

// 從 datetime 取得 epoch 值:
let dt = DateTime::parse_from_rfc2822("Fri, 14 Jul 2017 02:40:00 +0000").unwrap();
assert_eq!(dt.timestamp(), 1_500_000_000);

限制

  • 僅支援向前推算的格里高利曆(即擴展以支援更早的日期)。
  • 日期類型限制在公元紀元前後約 262,000 年內。
  • 時間類型限制為奈秒精度。
  • 可表示閏秒,但 Chrono 不完全支援它們。