16 releases (8 breaking)

0.9.2 Mar 8, 2024
0.8.0 Dec 31, 2023
0.6.0 Sep 23, 2023
0.4.0 Jul 30, 2023
0.2.1 May 28, 2022

#29 in Date and time

Download history 10/week @ 2023-12-16 4/week @ 2023-12-23 25/week @ 2023-12-30 2/week @ 2024-01-06 23/week @ 2024-01-20 38/week @ 2024-01-27 1/week @ 2024-02-03 63/week @ 2024-02-17 900/week @ 2024-02-24 1307/week @ 2024-03-02 2165/week @ 2024-03-09 1514/week @ 2024-03-16

5,901 downloads per month
Used in 3 crates

MIT license

53KB
1K SLoC

Fancier Durations now in an easily consumable library

A "fancy duration" is a text description of the duration. For example, "1h 20m 30s" which might be read as "one hour, twenty minutes and thirty seconds". Expression in a duration type is transparent through a variety of means; chrono and the time crate are supported, as well as serialization into and from string types with serde. Time support starts in years and funnels down to nanoseconds.

Here are the docs.

What follows are some usage examples. You can either wrap your duration-like type in a FancyDuration struct, or use types which allow for monkeypatched methods that allow you to work directly on the target type. For example, use AsFancyDuration to inject fancy_duration calls to perform the construction (which can be formatted or converted to string) and ParseFancyDuration to inject parse_fancy_duration constructors to accept strings into your favorite type. std::time::Duration, time::Duration, and chrono::Duration are all supported (some features may need to be required) and you can make more types eligible by implementing the AsTimes trait.

use std::time::Duration;
use fancy_duration::FancyDuration;

pub fn main() {
    assert_eq!(FancyDuration(Duration::new(20, 0)).to_string(), "20s");
    assert_eq!(FancyDuration(Duration::new(600, 0)).to_string(), "10m");
    assert_eq!(FancyDuration(Duration::new(120, 0)).to_string(), "2m");
    assert_eq!(FancyDuration(Duration::new(185, 0)).to_string(), "3m 5s");
    assert_eq!(FancyDuration::<Duration>::parse("3m 5s").unwrap().duration(), Duration::new(185, 0));
    assert_eq!(FancyDuration(Duration::new(185, 0)).to_string(), "3m 5s");

    // these traits are also implemented for chrono and time
    use fancy_duration::{ParseFancyDuration, AsFancyDuration};
    assert_eq!(Duration::new(20, 0).fancy_duration().to_string(), "20s");
    assert_eq!(Duration::new(600, 0).fancy_duration().to_string(), "10m");
    assert_eq!(Duration::new(120, 0).fancy_duration().to_string(), "2m");
    assert_eq!(Duration::new(185, 0).fancy_duration().to_string(), "3m 5s");
    assert_eq!(Duration::parse_fancy_duration("3m 5s".to_string()).unwrap(), Duration::new(185, 0));
    assert_eq!(Duration::new(185, 0).fancy_duration().to_string(), "3m 5s");

    #[cfg(feature = "time")]
    {
        // also works with time::Duration from the `time` crate
        assert_eq!(FancyDuration(time::Duration::new(20, 0)).to_string(), "20s");
        assert_eq!(FancyDuration(time::Duration::new(600, 0)).to_string(), "10m");
        assert_eq!(FancyDuration(time::Duration::new(120, 0)).to_string(), "2m");
        assert_eq!(FancyDuration(time::Duration::new(185, 0)).to_string(), "3m 5s");
        assert_eq!(FancyDuration::<time::Duration>::parse("3m 5s").unwrap().duration(), time::Duration::new(185, 0));
        assert_eq!(FancyDuration(time::Duration::new(185, 0)).to_string(), "3m 5s");
    }

    #[cfg(feature = "chrono")]
    {
        // also works with chrono!
        assert_eq!(FancyDuration(chrono::Duration::seconds(20)).to_string(), "20s");
        assert_eq!(FancyDuration(chrono::Duration::seconds(600)).to_string(), "10m");
        assert_eq!(FancyDuration(chrono::Duration::seconds(120)).to_string(), "2m");
        assert_eq!(FancyDuration(chrono::Duration::seconds(185)).to_string(), "3m 5s");
        assert_eq!(FancyDuration::<chrono::Duration>::parse("3m 5s").unwrap().duration(), chrono::Duration::seconds(185));
        assert_eq!(FancyDuration(chrono::Duration::seconds(185)).to_string(), "3m 5s");
    }
}

Benchmarks

Each interval test increases the number of things that will be formatted. The first set of parse tests parse one string with several terms, the others parse a static set of 5 terms in a single iteration.

Benchmarking system was a Ryzen 5900X with 64GB RAM running Linux 6.6.8 in a desktop configuration.

As of 0.9.1:

fancy duration format seconds: std
                        time:   [644.13 ps 645.34 ps 646.96 ps]
fancy duration format seconds: time
                        time:   [6.6756 ns 6.6945 ns 6.7181 ns]
fancy duration format seconds: chrono
                        time:   [658.36 ps 658.73 ps 659.15 ps]
fancy duration format minutes: std
                        time:   [666.00 ps 666.50 ps 667.03 ps]
fancy duration format minutes: time
                        time:   [6.6301 ns 6.6324 ns 6.6349 ns]
fancy duration format minutes: chrono
                        time:   [646.99 ps 647.24 ps 647.50 ps]
fancy duration format hours: std
                        time:   [658.35 ps 660.83 ps 662.88 ps]
fancy duration format hours: time
                        time:   [6.5761 ns 6.5792 ns 6.5826 ns]
fancy duration format hours: chrono
                        time:   [648.05 ps 648.38 ps 648.74 ps]
fancy duration format days: std
                        time:   [641.06 ps 641.33 ps 641.62 ps]
fancy duration format days: time
                        time:   [6.5374 ns 6.5410 ns 6.5452 ns]
fancy duration format days: chrono
                        time:   [662.60 ps 665.24 ps 667.41 ps]
fancy duration format weeks: std
                        time:   [641.06 ps 641.32 ps 641.61 ps]
fancy duration format weeks: time
                        time:   [6.7987 ns 6.8158 ns 6.8288 ns]
fancy duration format weeks: chrono
                        time:   [660.01 ps 662.64 ps 665.05 ps]
fancy duration format months: std
                        time:   [641.66 ps 642.02 ps 642.41 ps]
fancy duration format months: time
                        time:   [6.5435 ns 6.5498 ns 6.5573 ns]
fancy duration format months: chrono
                        time:   [672.00 ps 672.39 ps 672.83 ps]
fancy duration parse one: std
                        time:   [332.00 ns 332.48 ns 332.98 ns]
fancy duration parse one: time
                        time:   [346.25 ns 346.58 ns 346.92 ns]
fancy duration parse one: chrono
                        time:   [369.81 ns 371.26 ns 372.65 ns]
fancy duration parse 5 distinct items: std
                        time:   [1.9150 µs 1.9183 µs 1.9214 µs]
fancy duration parse 5 distinct items: time
                        time:   [1.8446 µs 1.8474 µs 1.8503 µs]
fancy duration parse 5 distinct items: chrono
                        time:   [1.8281 µs 1.8311 µs 1.8345 µs]

Author

Erik Hollensbe git@hollensbe.org

License

MIT

Dependencies

~2.3–4MB
~68K SLoC