🦀

100日後にRustをちょっと知ってる人になる: [Day 74]日時操作: time

2022/12/02に公開

Day 74 のテーマ

Day 73 では、乱数を扱うクレートについて見てみました。そこでも少しふれましたけれど、他のプログラム言語であれば標準ライブラリで提供していそうな乱数の機能が Rust ではないということに驚いていました。また、今回もいかにも標準ライブラリで提供していそうな日時を扱う機能について見てみたいとおもっています。

また別の言語のことですが、Java では日時計算を行う時に利用する API として、Date and Time API が標準 API として提供されています。
このように、他のプログラム言語の経験者からすると標準ライブラリで充実した機能が提供されていないことに違和感を持ってしまうかもしれないですよね。

僕自身標準提供されている API を知るということよりも、多くのクレートで何ができるかを知っていくことも大事だと思っているところです。逆に考えれば、それだけ Rust の場合はエコシステムが広がりを見せてきているのかもしれないのかなと感じていたりします。とは
言っても、クレートをいろいろと覚えていかなければならないので学習範囲は広がりそうですけどね。

というわけで、今日は日時を扱う time というクレートを見ていきたいなと思います。

time

日時を扱うクレートで代表的なものには、timechrono という 2 つがあるようです。今日は time について使い方を学びたいなと思います。

以下が、time クレートに関するプロジェクトやドキュメントへのリンクです。

Book 中心にして time について見てみたいと思います。

まず最初に謳い文句として特徴についてです。

  • 簡単・安全

    • わかりやすい API 提供しているそうです。
      • たしかに、time::OffsetDateTime で提供しているメソッドを見てみると、例えば UTC時間での取得日曜日から始まる週番号の取得など直感的にやりたいことを実施できるようなメソッドなどが用意されていそうです。
  • 最適化・効率化

    • time は、ナノ秒の精度で ±9999 年の範囲の日付をサポートしています。
    • さらに大きな範囲で、±999,999 までの範囲は、large-dates 機能でサポートされています。
  • シリアライズ・デシリアライズ

    • シリアライゼーションするデファクトなフレームワークの serde に対応ということを銘打っています
    • serde
      • (まだ使ったことないです)
  • マクロで簡単に日付を作成

  • Windows、Linux、macOS、WebAssemblyターゲットなどをサポート

使い方

それではとにかく使ってみます。

まず依存関係を Cargo.toml に追加します。
ちなみに、今日時点の最新バージョンは v0.3.17 でした。
また、ここでは、macros フィーチャーを有効にしています。

cargo add time --features macros
コマンド実行結果
    Updating crates.io index
      Adding time v0.3.17 to dependencies.
             Features:
             + alloc
             + macros
             + std
             - formatting
             - large-dates
             - local-offset
             - parsing
             - quickcheck
             - rand
             - serde
             - serde-human-readable
             - serde-well-known
             - wasm-bindgen
[dependencies]
time = { version = "0.3.17", features = ["macros"] }

次に UTC 時間を取得する now_utc メソッドで現在時間を取得してみます。

use time::OffsetDateTime;
fn main() {
    let now = OffsetDateTime::now_utc();
    println!("Hello, world at {:?}", now);
}

実行結果:

Hello, world at 2022-12-01 23:49:32.605876 +00:00:00

簡単に日時を取得できたことが分かると思います。
こうなると次は現地時間 (ここでは日本時間) を取得したくなりますよね。その場合は、次のフィーチャーを有効にします。

  • local-offset
[dependencies]
time = { version = "0.3.17", features = ["macros", "local-offset"] }

そして、now_utc メソッドを now_local メソッドに変更するのみです。

    let now = OffsetDateTime::now_local();
    println!("Hello, world at {:?}", now);

特徴としても言われているように日時取得がかなり簡単にできることが分かります。

いろいろな日時

日時に関する構造体がいろいろとあるのを見つけました。

time::Date

この型は、グレゴリアン暦における日付で使用します。

let date = Date::from_iso_week_date(2022, 48, time::Weekday::Friday).unwrap();

また、マクロから次のように簡単に Date を作成できます。

let _ = date!(2022-12-01);

time::Time

Time では、とある日付内の時刻表現を担当しています。その精度はナノ秒で行われます。

let datetime = date.with_hms(11, 22, 33).unwrap();

time::PrimitiveDateTime

日付と時刻を組み合わせたものです。

let date = Date::from_iso_week_date(2022, 48, time::Weekday::Friday).unwrap();
let datetime: PrimitiveDateTime = date.with_hms(11, 22, 33).unwrap();

日時間隔の計算も直感的に行うことができます。

let start = datetime!(2022-01-01 0:00:00);
let end = datetime!(2022-12-31 23:59:59);
let duration = end - start;

ここで使用している datetime!PrimitiveDateTime 型の日時を作成するマクロです。

Day 74 のまとめ

time クレートを使うことにより、日付表現を簡単に行うことが分かりました。かなり直感的に日付捜査ができるので日々使いながらもっといろいろな機能に見つけ慣れていきたいと思うクレートでした。

GitHubで編集を提案

Discussion